做java后台开发,对jvm的考察就是最重要的了!面试官肯定会问你对jvm的理解,你就要从以下几个角度来描述:
- JVM内存的划分
- 垃圾回收问题(定义、回收的东西)
- GC算法
- 新生代、老年代、(jdk8之前还有永久代,jkd8开始取消了永久代的划分)
一、jvm运行时的数据区域
jvm在执行Java程序的过程中会把它所管理的内存划分为5个不同的数据区域。5区域存储不同类型的数据,5区域的内存分配和销毁的时间也不同,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。
方法区+堆区——线程共享的(所有线程只有一个方法区/堆区,共享使用)
jvm栈+本地方法栈+程序计数器——线程私有的(每个线程都有一个)
5个区域分别存什么(主要知道方法区、堆区、jvm栈就行)?
方法区:存储类信息和方法信息。具体包括:方法、成员变量、全局变量(static修饰)、常量
堆区:存储new出来的对象
注:jvm垃圾回收区域主要是堆区,由程序员申请和释放,如果程序员没有释放,将一直存在直至程序运行结束。
栈:存储方法内部的局部变量、基本数据类型、堆中对象的引用
注:对于栈空间,最后会自动释放资源,所以不需要垃圾回收。
二、java中内存的区域分配
在java中,声明的对象是先在栈内存中为其开辟内存空间,在对其进行实例化后则在堆内存中为其分配内存地址。
例如:
Person p = null ; 只在栈中为其开辟空间
p = new Person(); 则在堆中为其分配地址
例如:
People b = new People ();
b.show();
以上代码的内存实现原理为:
1.People类首先被加载到虚拟机的方法区。
2.在栈中分配引用变量b,开辟内存空间。
3.在堆中分配内存空间,将栈中引用变量b,指向堆内存的首地址。
4.使用引用变量b调用方法show
三、垃圾回收机制
1、垃圾回收器(Garbage collection,GC)
垃圾回收机制是jvm自带的一个线程,用于回收没有被引用的对象。
2、需要垃圾回收的区域:
只有方法区与堆。因为程序计数器、JVM栈、本地方法栈的生命周期是和线程同步的,随着线程的销毁,它们占用的内存会自动释放,所以只有方法区和堆需要进行垃圾回收。
3、垃圾回收算法(4种):
- 标记-清除算法
- 复制算法
- 标记-整理算法
- 分代收集算法(重要)
4、常见的垃圾收集器:
- Serial收集器 复制算法
- Serial old收集器 标记-整理算法
- ParNew收集器 复制算法
- Parallel Scavenge收集器 复制算法
- CMS(Concurrent Mark Sweep)收集器 标记-清除算法
5、JVM的分代收集算法:
堆被分成许多称为代的部分,每个部分根据“年龄”来保存对象。
分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为多个区域。一般情况下将堆区划分为新生代、老年代,在堆区之外还有一个代就是永久代。新生代每次会回收大量对象垃圾,而老年代每次会回收少量对象垃圾,那么就可以根据不同代的特点采取最适合的收集算法。
**新生代:用于存放新创建的对象。绝大多数新创建的对象会被分配到这里,大部分对象在创建之后会变得很快不可达。 -----复制算法
**老年代:在新生代中经历了N次垃圾回收后仍然存活的对象,就会被复制到老年代中。因此,老年代中存放的都是一些生命周期较长的对象。-----标记-整理算法或标记-清除算法
**永久代:永久代也称方法区。用于存放静态文件,如类、方法、成员变量、全局变量等。永久代对垃圾回收没有显著影响。
6、如何判断对象是否是垃圾
使用两种算法判断:(1)程序计数器 (2)可达性分析(相比于第一种更常用)
上述两种算法的工作原理也得会,自行查找材料。
7、当没有足够的堆空间来容纳新对象的存储时会发生什么?
jvm会抛出异常:OutOfMemoryError,但是如果经常出现java.lang.outOfMemoryError,就得检查程序是否出现内存泄漏了。