查看自己设置的jvm参数
java -XX:+PrintCommandLineFlags
idea日志
C:\Users\Lenovo\.IntelliJIdea2018.1\system\log
查看idea的参数配置 在help 里的custom vm options
# custom IntelliJ IDEA VM options
-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
jstat最杰出的功能便是监控JVM进行垃圾回收(GC)的相关信息
使用示例:jstat –gc –h3 6033 250 10
解释:监控gc的信息,每三行输出一次表头,监控的进程pid为6033,每250ms输出一次信息,一共输出10次。
参数说明:
S0C: Survivor0(幸存区0)大小(KB)
S1C: Survivor1(幸存区1)1大小(KB)
S0U: Survivor0(幸存区0)已使用大小(KB)
S1U: Survivor1(幸存区1)已使用大小(KB)
EC : Eden(伊甸区)大小(KB)
EU : Eden(伊甸区)已使用大小(KB)
OC :老年代大小(KB)
OU : 老年代已使用大小(KB)
PC : Perm永久代大小(KB)
PU : Perm永久代已使用大小(KB)
YGC:新生代GC个数
YGCT:新生代GC的耗时(秒)
FGC :Full GC次数
FGCT:Full GC耗时(秒)
GCT :GC总耗时(秒)
查看各个代的容量情况
jstat –-gccapacity –h3 6033 250 10
NGCMN:新生代最小值(KB)
NGVMX:新生代最大值(KB)
NGC:当前新生代大小(KB)
S0C:同上
S1C:同上
EC:同上
OGCMN:老年代最小值(KB)
OGCMX:老年代最大值(KB)
OGC:当前老年代大小(KB)
OC:同上
PGCMN:永久代最小值(KB)
PGCMX:永久代最大值(KB)
PGC:当前永久代大小(KB)
PC:同上
YGC:同上
FGC:同上
Jconsole使用
cmd 中输入 jconsole 就可以了 但后监听pid点击确定
JVM的新生代、老年代、MinorGC、MajorGC - Nutty - 博客园
新生代又分为 Eden区、ServivorFrom、ServivorTo三个区。
ServivorTo:保留了一次MinorGC过程中的幸存者。
ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者。
MinorGC的过程:
MinorGC采用复制算法。首先,把Eden和ServivorFrom区域中存活的对象复制到ServicorTo区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果ServicorTo不够位置了就放到老年区);然后,清空Eden和ServicorFrom中的对象;最后,ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区。
永久代
主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域. 它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。 在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。类的元数据放入 native memory, 字符串池和类的静态变量放入java堆中. 这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制.
JVM的组成(5)
方法区,java堆,虚拟机栈,本地方法区,程序计数器。
JAVA内存区域与和区域OOM问题
1:程序计数器
当前线程执行的字节码文件的行号指示器,用于线程切换之后恢复上次执行时的位置继续执行。各个线程之间的计数器互不影响,“线程私有”。
这是唯一一个在JVM中没有OOM异常的区域。
2:虚拟机栈
这也是线程私有的,保留了当前线程的方法栈帧:每个方法执行时会创建栈帧,用于存储局部变量、操作数、方法出口等。每个方法从调用到执行完成就对应这一个栈帧在虚拟机栈中入栈到出栈的过程。
这个区域有两种异常:方法栈的深度大于虚拟机所允许的深度就会抛出StackOverflowError异常;栈的大小扩展时如果无法获得足够的内存就会抛出OOM异常。
3:本地方法栈
为本地的Native方法服务,功能与虚拟机栈类似,也会由于深度问题或扩展时内存不够而抛出StackOverflowError或OOM异常。
4:Java堆
被所有线程共享的一片区域,所有对象实例以及数组都在堆上分配内存。可以通过:-Xmx、-Xmx设置堆的大小上下限。我们习惯上把堆划分为新生代和老年代,具体划分在GC机制的博文详述。
当堆的内存不足时,抛出OOM异常。
5:方法区
被各个线程共享,存储被虚拟机加载的类的信息、常量、静态变量等,为了与堆进行区分,又有“非堆”的别名。
由于在HotSpot虚拟机中把GC机制扩展到了方法区,使得垃圾收集器可以像Java堆那样管理这部分内存,故方法区又叫“永久代”。这部分区域的垃圾回收为废弃常量和无用的类。废弃常量:常量池中没有被任何对象引用的常量值。无用的类:无任何对象实例、类加载器已被回收、Class对象没有被引用的类文件。
当方法区内存达到-XX:MaxPermSize上限时抛出OOM异常。
GC算法
一:复制算法
将可用内存划分为大小相等的两块。每次只使用其中一块,当这块内存用完了就将仍然存活的对象复制到另一块上,然后把已使用完的这一块清理掉。这样可以保证空闲区域总是连续的。复制算法一般用于新生代中的垃圾回收。
二:标记—清除算法
首先标记出需要回收的对象,然后统一回收所有被标记的对象。这种方法的不足之处在于:一是效率问题,需要两次遍历;二是清除之后产生大量不连续的内存碎片,当需要分配大内存给较大对象时无法找到合适的连续空间而不得不提取触发垃圾收集。
三:标记—整理算法
对标记—清除算法进行改进:首先标记出需要清理的对象,然后让所有存活的对象向一端移动,然后清理掉存活对象区域的边界之外的内存。这样就使得回收产生的空闲区连续。
四:分代收集算法
当代的商业虚拟机都采用分代收集算法。对堆中的新生代采取复制算法,老年代采取标记—清除算法或者标记—整理算法。
JVM分配策略
一:对象优先分配在线程的本地分配缓冲区
二:堆中优先分配Eden
三:大对象直接进入老年代
四:长期存活的对象“晋入”老年代
五:空间分配担保
在MinorGC之前,会先检查老年代最大可用空间是否可以容纳新生代所有对象(防止新生代全部晋升时放不下),如果可以容纳,则MinorGC可以安全执行。否则,检查是否允许担保失败,是则检查老年代最大可用空间是否大于历次晋升到老年代的对象的平均大小,是则尝试进行MinorGC;小于或者MinorGC失败,则会发起一次FullGC清理老年代。
JVM类加载机制
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终成为被虚拟机直接使用的Java对象,这就是JVM的类加载机制。
类的生命周期
类的生命周期包括7个部分:加载——验证——准备——解析——初始化——使用——卸载
JVM调优
JVM原理讲解和调优 - Thinking的专栏 - CSDN博客
几种情况:
旧生代空间不足
调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象
Pemanet Generation空间不足
增大Perm Gen空间,避免太多静态对象
统计得到的GC后晋升到旧生代的平均大小大于旧生代剩余空间
控制好新生代和旧生代的比例
System.gc()被显示调用
垃圾回收不要手动触发,尽量依靠JVM自身的机制
调优手段主要是通过控制堆内存的各个部分的比例和GC策略来实现,下面来看看各部分比例不良设置会导致什么后果
1)新生代设置过小
一是新生代GC次数非常频繁,增大系统消耗;二是导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发Full GC
2)新生代设置过大
一是新生代设置过大会导致旧生代过小(堆总量一定),从而诱发Full GC;二是新生代GC耗时大幅度增加
一般说来新生代占整个堆1/3比较合适
3)Survivor设置过小
导致对象从eden直接到达旧生代,降低了在新生代的存活时间
4)Survivor设置过大
导致eden过小,增加了GC频率
另外,通过-XX:MaxTenuringThreshold=n来控制新生代存活时间,尽量让对象在新生代被回收
由内存管理和垃圾回收可知新生代和旧生代都有多种GC策略和组合搭配,选择这些策略对于我们这些开发人员是个难题,JVM提供两种较为简单的GC策略的设置方式
1)吞吐量优先
JVM以吞吐量为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,来达到吞吐量指标。这个值可由-XX:GCTimeRatio=n来设置
2)暂停时间优先
JVM以暂停时间为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,尽量保证每次GC造成的应用停止时间都在指定的数值范围内完成。这个值可由-XX:MaxGCPauseRatio=n来设置