Runtime Data Area 运行时数据区
1. method area
线程共享
存放已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等信息。多个线程同时加载一个类时,只有一个会请求Class Loader加载,另一个会等待。
MetaSpace 元数据空间
从JDK1.8 开始method area被metaspace完全取代。metaspace使用本地内存存放数据,意味着java.lang.OutOfMemoryError: PermGen的空间问题将不复存在,并且不再需要调整和监控这个内存空间。一个新的参数 (MaxMetaspaceSize)可以使用。允许你来限制用于类元数据的本地内存。如果没有特别指定,元空间将会根据应用程序在运行时的需求动态设置大小。
2. java stack
线程私有 每创建一个线程,虚拟机就会创建一个java stack,它表示java方法执行的内存模型. 每调用一个方法,就会生成一个栈帧(stack frame)用于存放方法的本地变量、 操作栈、方法出口等信息,当这个方法执行完后,就会弹出相应的栈帧。
如果请求的栈深度过大,虚拟机就会抛出StackOverflowError。如果虚拟机的实现中允许java stack动态扩展,当内存不足的时候,会抛出OutOfMemoryError。
调整栈空间大小: java -Xss1m 默认1M
method frame 方法帧
分为三部分:Local Variables 局部变量区、 Operand Stack 操作数栈 和 Frame Data 帧数据区
3. Native Method Stack
与java Stack类似,只是执行本地方法时使用。
4. Heap
线程共享
虚拟机中用于存放对象和数组实例的地方,垃圾回收的主要区域就是这里(还可能有方法区)。
设置堆大小:
-Xmx128m (默认物理内存的1/4)
-Xms16m
Heap 可以细分为:
新生代
Eden区
Survivor 1区
Survivor 2区
老年代
4.Program Counter Register 程序计数器
线程私有
记录当前线程执行的指令地址,用于多线程间切换时恢复每一个线程的执行位置。 如果当前执行的是本地方法,存储的值是Undefined
Minor GC 和 Full GC
Minor GC:新生代GC,指发生在新生代的垃圾收集动作
如果Eden空间占满了, 会触发 minor GC。 Minor GC 后仍然存活的对象会被复制到S0中去。这样Eden就被清空可以分配给新的对象。又触发了一次 Minor GC , S0和Eden中存活的对象被复制到S1中, 并且S0和Eden被清空。 在同一时刻, 只有Eden和一个Survivor Space同时被操作。
当每次对象从Eden复制到Survivor Space或者从Survivor Space中的一个复制到另外一个,有一个计数器会自动增加值。 默认情况下如果复制发生超过16次, JVM 会停止复制并把他们移到老年代中去。
Major GC/Full GC:老年代GC,指发生在老年代的GC。
如果一个对象不能在Eden中被创建,它会直接被创建在老年代中。 如果老年代的空间被占满会触发老年代的 GC,也被称为 Full GC。full GC 是一个压缩处理过程,所以它比Minor GC要慢很多。
Minor GC ,Full GC 触发条件
Minor GC触发条件:
当Eden区满时,触发Minor GC。
Full GC触发条件:
(1)调用System.gc时,系统建议执行Full GC,但是不必然执行
(2)老年代空间不足
(3)方法去空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
如何确定某个对象是“垃圾
1.引用计数器算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值加1;当引用失效时,计数器的值减;当该对象的计数器的值为0时,标志该对象失效。
2.跟搜索算法
基本思路:通过一系列的名为“GCRoots”的对象作为起始点,从这些节点开始向下搜索,搜索过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明对象是不可用的。
垃圾收集算法 及 垃圾收集器
http://www.cnblogs.com/dolphin0520/p/3783345.html
查看Jvm状态的工具
jvisualvm.exe
jmc.exe
jconsole.exe
参数设置
堆设置:
-Xms 初始堆大小
-Xmx 最大堆大小
-XX:NewSize=n 年轻代大小
-XX:NewRatio=n 设置年轻代和年老代的比值。如n=3表示年轻代和年老代的比值为1:3。默认n=2, 即年轻代占Heap大小的1/3, 年老代占2/3。
-XX:SurvivorRatio=n 设置Eden区与两个Survivor区的比值。如n=3,表示Eden区与两个Survivor区的比值为3:1:1, Eden区占整个年轻代大小的3/5。默认n=1。
-XX:MaxPermSize=n 设置持久代大小, 即方法区的大小。
-XX:MaxTenuringThreshold=n 默认n=5 设置垃圾最大存活阀值。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
-XX:MaxPermSize=128m 设置永久代的大小,JDK1.8以后这个参数被废除
-XX:MetaspaceSize JDK8里的Metaspace
-XX:MaxMetaspaceSize JDK8里的Metaspace 超过这个值会触发垃圾回收
收集器设置
-XX:+UseSerialGC 设置串行收集器
-XX:+UseParallelGC 设置并行收集器
-XX:+ParallelGCThreads=4 设置并行收集器线程数
-XX:+UseParallelOldGC 设置并行年老代收集器
-XX:+UseConcMarkSweepGC 设置CMS收集器
-XX:ParallelCMSThreads=4 设置CMS收集器线程数
-XX:+UseG1GC 设置G1收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename 将日志写入到文件
参考:
<怎么在面试时回答Java垃圾回收机制(GC)相关问题> https://www.zhihu.com/question/35164211
<Java垃圾回收机制> http://www.cnblogs.com/dolphin0520/p/3783345.html
<JVM 参数> http://www.tuicool.com/articles/RNjUfa
<Java 8最快的垃圾搜集器是什么> http://www.importnew.com/16533.html
<从PermGen 到 MetaSpace>http://blog.csdn.net/zhyhang/article/details/17246223