Java垃圾回收
java运行时内存区
(1)线程私有区:
- 程序计数器,记录正在执行的虚拟机字节码的地址;
- 虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;
- 本地方法栈:虚拟机的Native方法执行的内存区;
(2)线程共享区:
- Java堆:对象分配内存的区域,这是垃圾回收的主战场;
- 方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据,另外还有一个常量池。当然垃圾回收也会在这个区域工作。
什么时候
说明minor gc/full gc的触发条件、OOM的触发条件,降低GC的调优的策略。
①大多数情况下,对象在新生代的Eden区分配,如果没有足够空间,则虚拟机将发起一次Minor GC(Minor GC发生在新生代的垃圾回收)
②Full GC的触发条件:
- 老年代代空间不足
- 方法区空间不足时(HotSpot的永久区)
- 统计得到的Minor GC晋升到老年代的平均大小大于老年代的剩余空间。
例如程序第一次触发Minor GC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,
则执行Full GC。 - 堆中分配很大的对象,需要大量连续内存空间的java对象,此种对象会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full GC。
- System.gc()方法的调用:比较少用
eden满了minor gc,升到老年代的对象大于老年代剩余空间full gc,
或者小于时被HandlePromotionFailure参数强制full gc;gc与非gc时间耗时超过了GCTimeRatio的限制引发OOM,调优诸如通过NewRatio控制新生代老年代比例,通过MaxTenuringThreshold控制进入老年前生存次数等
对什么东西
从gc roots搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。
做什么事情
能说出诸如新生代做的是复制清理、from survivor、to survivor是干啥用的、老年代做的是标记清理、标记清理后碎片要不要整理、复制清理和标记清理有有什么优劣势等。
还能讲清楚串行、并行(整理/不整理碎片)、CMS等搜集器可作用的年代、特点、优劣势,并且能说明控制/调整收集器选择的方式。
可达性算法
这是目前主流的虚拟机都是采用GC Roots Tracing算法
可以作为GC Roots的对象(见下图):
- 虚拟机栈的栈帧的局部变量表所引用的对象;
- 本地方法栈的JNI(Java Native Interface)所引用的对象;
- 方法区的静态变量和常量所引用的对象;
参考资料:
-
作者:郭无心
链接:https://www.zhihu.com/question/35164211/answer/68265045
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -
作者:Gityuan
链接:https://www.zhihu.com/question/21539353
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -
深入理解JVM虚拟机. https://book.douban.com/subject/24722612/