一、JVM运行时数据区域
1.线程共享区域:堆(存放对象实例以及数组)、元空间(存储已被虚拟机加载的类信息、常量、静态变量、即使吧编译器编译后的代码等数据,又称Non-Heap(非堆))
2.线程私有区域:虚拟机栈(局部变量表)、程序计数器、本地方法栈
堆空间的基本结构
-
eden(8/10)
-
s0(from survivor)(1/3)
-
s1(to survivor)(1/3)
-
tentired(占堆空间大小的2/3)
其中eden、s0、s1属于新生代,tentired属于老年代。
堆内存分配策略:
- 对象优先在eden区分配
- 大对象直接进入 老年代
- 长期存活的对象将进入老年代
二、ClassLoader(类加载器)
1.主要作用:从系统外获得Class二进制数据流,它是Java核心组件,所有的Class都是由Classloader负责加载的,Classloader负责通过将Class文件里的二进制数据流装载进系统,然后交给Java虚拟机进行连接、初始化等操作。
2.种类:
1)BootStrapClassLoader:C++编写,负责加载核心库 java.*
2)ExtClassloader:Java编写,加载拓展库 javax.*
3)AppClassloader:Java编写,加载程序所在目录
4)自定义Classloader:Java编写,定制化加载
3.类加载器的双亲委派机制
- 定义:在类加载的时候,系统会首先判断当前类是否被加载过。已经加载的类会直接返回,否则才会被加载。加载的时候 ,**首先会把该请求委派该父类加载器的loadClass()处理,因此所有的请求最终都会应该传到顶层的启动类加载器BootstrapClassLoader中。**当父类加载器无法处理时,才由自己处理。
1)自底向上检查类是否已经加载 CustomClassloader->AppClassloader->ExtClassloader->BootStrapClassloader
2)自顶向下尝试加载类
三、如何判断对象已将死亡?
-
引用计数法:
1)通过判断对象的引用数量来决定对象是否可以被回收;
2)每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1;
3)任何引用计数为0的对象实例都可以被当作垃圾回收 -
优缺点
1)优点:执行效率高,程序执行受影响较小
2)缺点:无法检测出循环引用的情况,会导致内存泄漏 -
可达性分析算法:通过一系列称为“GC Root”的对象为起点,从这些节点开始向下搜索,走过的路径称为引用链。当一个对象到GC Root没有任何引用链相连的话,则证明该对象是不可达的,会被回收掉。
1)可以作为GC Root的对象:
a.虚拟机栈中引用的对象(栈帧中的局部变量表)
b.方法区中的常量引用的对象
c.方法区中类静态属性引用的对象
d.本地方法栈中的引用对象
e.活跃线程的引用对象
四、垃圾回收算法
-
标记-清除算法(Mark and Sweep):算法分“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
1)缺点:
a.会产生大量不连续的内存碎片
b.执行效率低 -
复制算法(Copying):
1)分为对象面和空闲面;
2)对象在对象面上创建;
3)存活的对象被从对象面复制到空闲面;
4)将对象面所有的对象内存清除2.2 优点:
1)解决碎片化问题;
2)顺序分配内存,简单高效;
3)适用于存活率低的场景 -
标记-整理算法(Compacting)
1)避免内存的不连续性;
2)不用设置两块内存互换;
3)适用于存活率低的场景 -
分代收集算法(Generational Collector)
1)根据对象存活周期的不同将内存划分为几块。一般将Java Heap分为新生代和老年代,这样我们就可以根据各个年代的特点选择适合的垃圾收集算法。
4.1 目的:提高JVM回收效率
4.2 GC的分类:
1)Minor GC(复制->清除->交换):Minor GC又称为新生代GC : 指的是发生在新生代的垃圾收集。因为Java对象大多都具备朝生夕灭的特性, 因此Minor GC(采用复制算法)非常频繁,一般回收速度也比较快。
2) Full GC:Full GC 又称为老年代GC或者Major GC.指发生在老年代的垃圾收集。出现了Major GC,经常会伴随至少一次的Minor GC(并非绝对,在Parallel Scavenge收集器中就有直接进行Full GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。
4.3 Stop-the-world
1) JVM由于要执行GC而停止了应用程序的执行;
2)任何一种GC算法中都会发生
3)多数GC优化提高减少Stop-the-world发生的时间来提高程序性能。
4.4 Safepoint
1)分析过程中对象引用关系不会发生变化的点;
2)产生Safepoint的地方:方法调用、循环跳转、异常跳转等
3)安全点的数量的得适中
五、垃圾收集器:
-
Serial收集器(-XX:+UseSerialIGC,复制算法)
1)单线程收集,进行垃圾收集时,必须暂停所有工作线程
2)简单高效,Client模式默认的年轻代收集器 -
ParNew收集器(-XX:+UseParNewGC,复制算法)
1)多线程收集,其余的行为、特点和Serial收集器一样
2)单核执行效率不如Serial收集器,在多核下执行才有优势 -
Parallel Scavenge收集器(-XX:+UseParallelGC,复制算法)
1)比起关注用户线程停顿的时间,更加关注系统的吞吐量
2)在多核下执行才有优势,Server模式下默认的年轻代收集器 -
Serial Old收集器(-XX:+UseSerialGC,标记-整理算法)
1)单线程收集,进行垃圾收集时,必须暂停所有工作线程
2)简答高效,Client模式下默认的老年代收集器 -
Parallel Old收集器(-XX:+UseParallelGC,标记-整理算法)
1)多线程,吞吐量优先 -
CMS收集器(-XX:UseConcMarkSweepGC,标记-清除算法)
多线程执行,是老年代常使用的垃圾回收器
-
Garbage First收集器(-XX:+UseG1GC)
7.1 特点:
1)并行和并发;
2)分代收集
3)空间整合
4)可预测的停顿
7.2 G1收集器的运作步骤:
- 初始标记
- 并发标记
- 最终标记
- 筛选回收
六、Java中的四大引用
1.强引用(Strong Reference)
1)最普遍的引用:Object obj = new Object();
2)抛出OOM终止程序也不会回收具有强引用的对象
3)通过将对象设置为null来弱化引用,使其被回收
2.软引用(Soft Reference)
1)对象处在有用但非必须的状态;
2)只有当内存空间不足时,GC会回收该引用对象的内存
3)可以用来实现高速缓存
String str = new String(“abc”);
SoftReference sr = new SoftReference<>();
3.弱引用(Weak Reference)
1)非必须的对象,比软引用更弱一些;
2)GC时会被回收
3)被回收的概率也不大,因为GC线程 优先级比较低;
4)适用于引用偶尔被使用 且不影响垃圾收集的对象
String str = new String(“abc”);
WeakReference wr = new WeakReference<>();
4.虚引用(PhantomReference)
1)不会决定对象的生命周期
2)任何时候都可能被垃圾收集器回收
3)跟踪对象被垃圾收集回收的活动,起哨兵作用
4)必须和引用队列ReferenceQueue一起使用
String str = new String(“abc”);
ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(str,queue);
七、调用System.gc()是否会立即执行垃圾回收?
答:**不会。**当我们调用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收。当我们直接调用System.gc()只会把这次gc请求记录下来,等到runFinalization=true的时候才会先去执行GC,runFinalization=true之后会在允许一次system.gc()。之后在call System.gc()还会重复上面的行为。