admin管理员组文章数量:1584610
GC Root
为了解决引用计数法的循环引用问题,java使用了可达性分析方法
所谓的"GC Root"或者说tracing GC的根集合,就是一组必须活跃的引用。
基本思路就是通过一系列名为"GC Root"的对象作为起始点,从这个被称为GC Root的对象开始详细搜索,如果一个对象到GC Root没有任何的引用链时,则说明此对象不可用。也即给定一个集合引用作为根出发,通过引用关系遍历对象图,能够被遍历到的(可到达的)对象就被判定为存活;没有遍历到 的 自然就判定死亡。
注意:即使可达性算法中不可达的对象,也不是一定要马上被回收,还有可能被抢救一下。网上例子很多,基本上和深入理解JVM一书讲的一样对象的生存还是死亡
要真正宣告对象死亡需经过两个过程。
1.可达性分析后没有发现引用链
2.查看对象是否有finalize方法,如果有重写且在方法内完成自救[比如再建立引用],还是可以抢救一下,注意这边一个类的finalize只执行一次,这就会出现一样的代码第一次自救成功第二次失败的情况。[如果类重写finalize且还没调用过,会将这个对象放到一个叫做F-Queue的序列里,这边finalize不承诺一定会执行,这么做是因为如果里面死循环的话可能会时F-Queue队列处于等待,严重会导致内存崩溃,这是我们不希望看到的。
可以作为GC Root的对象
- 虚拟机栈(栈帧中的局部变量区,也叫局部变量表)中引用的对象。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象
- 本地方法栈中JNI(Native方法)引用的对象
JVM参数类型
JVM参数分为3种类型,分别是:标配参数,x参数 ,xx参数。
标配参数
标配参数就是JVM自带的参数,如:
-version
-help
java -showversion
X参数
-Xint :解释执行
-Xcomp:第一次使用就编译成本地代码
-Xmixed:混合模式
XX参数(重点)
xx参数又分为Boolean类型,KV设值类型。
Boolean类型
公式: -XX:+或者-某个属性值(+表示开启,-表示关闭)
例如:我们要查看一个java进程是否开启打印GC细节,如下代码查下面代码运行的是否开启了打印GC
public class HelloGc {
public static void main(String[] args) throws InterruptedException {
System.out.println("-----hello gc-----");
Thread.sleep(MAX_VALUE);
}
}
-
我们先使用java的jps命令查看java正在运行的进程
C:\Users\18133\IdeaProjects\javastudy>jps -l 10024 10296 11384 org.jetbrains.jps.cmdline.Launcher 11720 com.fangyajun.javastudy.HelloGc 14604 org.jetbrains.idea.maven.server.RemoteMavenServer 16444 sun.tools.jps.Jps
-
在使用java的jinfo命令打印该进程的是否开启了PrintGCDetails
C:\Users\18133\IdeaProjects\javastudy>jinfo -flag PrintGCDetails 11720 -XX:-PrintGCDetails
从结果可以看出,-XX:-PrintGCDetails表示没有开启打印GC细节
-XX:-PrintGCDetails 表示没有开启打印GC细节 -XX:+PrintGCDetails 表示开启打印GC细节
现在我们启动时把PrintGCDetails打开
在看看结果:C:\Users\18133\IdeaProjects\javastudy>jinfo -flag PrintGCDetails 12832 -XX:+PrintGCDetails
从结果可以看出
-XX:+PrintGCDetails
表示打印GC信息开启。
KV设值类型
公式:-XX:属性key=属性值value
如:-XX:MetaspaceSize=128m
先查看没有设置前MetaspaceSize默认大小
C:\Users\18133\IdeaProjects\javastudy>jps -l
17904 org.jetbrains.jps.cmdline.Launcher
17252 com.fangyajun.javastudy.HelloGc
3860 org.jetbrains.idea.maven.server.RemoteMavenServer
14168
10956 sun.tools.jps.Jps
C:\Users\18133\IdeaProjects\javastudy>jinfo -flag MetaspaceSize 17252
-XX:MetaspaceSize=21807104
从结果可以看出,默认大小是-XX:MetaspaceSize=21807104
设置后:
C:\Users\18133\IdeaProjects\javastudy>jinfo -flag MetaspaceSize 1260
-XX:MetaspaceSize=1073741824
从结果可以看出已经修改成功-XX:MetaspaceSize=1073741824
查看一个java进程的JVM参数:
先使用jps -l
命令查看进程号,然后使用jinfo -flags 进程号
命令进程查看,如下:
C:\Users\18133\IdeaProjects\javastudy>jinfo -flags 1260
Attaching to process ID 1260, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b15
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=266338304 -XX:MaxHeapSize=4261412864 -XX:MaxNewSize=1420296192 -XX:MetaspaceSize=1073741824 -XX:MinHeapDeltaBytes=52
4288 -XX:NewSize=88604672 -XX:OldSize=177733632 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+U
seParallelGC
Command line: -XX:MetaspaceSize=1024m -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.5\lib\idea_rt.jar=56432:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.5\bin -Dfi
le.encoding=UTF-8
KV设值类型注意点:
两个经典参数:-Xms 和 -Xmx ,如-Xms1024m ,-Xmx1024m这个2个 参数属于哪种类型的参?
-Xms 等价于 -XX:InitialHeapSize 初始化堆内存
-Xmx 等价于 -XX:MaxHeapSize
以上2个参数也是-XX参数的KV类型,只不过常用,就可以这些写了
查看JVM参数初始化默认值
第一种:查看参数,盘点家底
jps -l
jinfo -flag 具体参数值 java进程编号
jinfo -flags java进程编号
第二种,查看参数,盘点家底
-
-XX:PrintFlagsInitial 主要查看初始默认值
公式:java -XX:+PrintFlagsInitial -version
或java -XX:+PrintFlagsInitial
如下:这个命令会打印出 所有的JVM初始化参数
-
-XX:PrintFlagsFinal 主要查看修改更新
公式:java -XX:+PrintFlagsFinal -version
或java -XX:+PrintFlagsFinal
注意:
=
号表示没修改过的参数
:=
这样 的符号表示被人为修改过或者JVM修改过的参数
-
-XX:+PrintCommandLineFlags 打印命令行参数
公式:java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=266275648 -XX:MaxHeapSize=4260410368 -XX:+PrintCommandLineFlags - XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC java version "1.8.0_91" Java(TM) SE Runtime Environment (build 1.8.0_91-b15) Java HotSpot(TM) 64-Bit Server VM (build 25.91-b15, mixed mode)
JVM参数配置
-
-Xms( -XX:InitialHeapSize): 初始化堆内存一般默认是物理内存的1/64
-
-Xmx( -XX:MaxHeapSize): 最大的堆内存一般默认是物理是内存的1/4
例子:public class HelloGc { public static void main(String[] args) throws InterruptedException { // 返回java虚拟机的内存总量 long totalMemory = Runtime.getRuntime().totalMemory(); // 返回java虚拟机试图使用的最大内存量 long maxMemory = Runtime.getRuntime().maxMemory(); System.out.println("初始化堆内存大小:-Xms=" + (totalMemory/1024/1024) + "M"); System.out.println("最大堆内存大小:-Xmx=" + (maxMemory/1024/1024) + "M"); } }
输出结果:
电脑内存时16G初始化堆内存大小:-Xms=243M 最大堆内存大小:-Xmx=3612M
-
-XSS(-XX:ThreadStackSize):设置单个线程栈的大小,一般默认是512k~1024k
官网描述如下: -
-Xmn:设置年轻代大小,默认是堆大小的1/3,一般不用调
-
-XX:MetaspaceSize:设置元空间大小
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间和永久代的最大区别在于:元空间并不在虚拟机中,而是使用本地内存。因此默认情况下,元空间大小仅受本地内存的限制系统默认MetaspaceSize一般比较小,如下
C:\Users\18133\IdeaProjects\javastudy>jps -l 17280 org.jetbrains.jps.cmdline.Launcher 3860 org.jetbrains.idea.maven.server.RemoteMavenServer 14168 16760 sun.tools.jps.Jps 2876 com.fangyajun.javastudy.HelloGc 9660 com.fangyajun.javastudy.HelloGc C:\Users\18133\IdeaProjects\javastudy>jinfo -flag MetaspaceSize 9660 -XX:MetaspaceSize=21807104
系统默认的元空间大小是21807104个字节,大约不到21M,
在实际的系统调优中,这个参数一般可以适当调大一点。 -
-XX:PrintGCDetails: 打印垃圾回收细节信息
看以下案例,我们配置初始堆内存和最大堆内存大小都是10m
代码程序:public class HelloGc { public static void main(String[] args) throws InterruptedException { // 创建一个大小为10m的数组 int[] a = new int[10*1024*1024]; } }
运行结果:
[GC (Allocation Failure) [PSYoungGen: 1805K->488K(2560K)] 1805K->696K(9728K), 0.0008999 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 488K->504K(2560K)] 696K->744K(9728K), 0.0005319 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 504K->0K(2560K)] [ParOldGen: 240K->614K(7168K)] 744K->614K(9728K), [Metaspace: 3260K->3260K(1056768K)], 0.0051251 secs] [Times: user=0.03 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 614K->614K(9728K), 0.0006900 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) Exception in thread "main" java.lang.OutOfMemoryError: Java heap space [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 614K->596K(7168K)] 614K->596K(9728K), [Metaspace: 3260K->3260K(1056768K)], 0.0052183 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] at com.fangyajun.javastudy.HelloGc.main(HelloGc.java:6) Heap PSYoungGen total 2560K, used 96K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000) eden space 2048K, 4% used [0x00000000ffd00000,0x00000000ffd18330,0x00000000fff00000) from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000) to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000) ParOldGen total 7168K, used 596K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000) object space 7168K, 8% used [0x00000000ff600000,0x00000000ff6951a0,0x00000000ffd00000) Metaspace used 3306K, capacity 4496K, committed 4864K, reserved 1056768K class space used 362K, capacity 388K, committed 512K, reserved 1048576K
从输出信息看看出,发生了一次GC回收,
GC信息参数解析:[PSYoungGen: 1805K->488K(2560K)] 1805K->696K(9728K), 0.0008999 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
各个参数解析如图:
Full GC信息参数解析:[Full GC (Allocation Failure) [PSYoungGen: 504K->0K(2560K)] [ParOldGen: 240K->614K(7168K)] 744K->614K(9728K), [Metaspace: 3260K->3260K(1056768K)], 0.0051251 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
各个参数解析:
规律:名称:GC前内存占用 -> GC后内存占用(该区内存总大小) -
-XX:SurvivorRatio:设置 新生代中eden和S0/S1空间比例
默认:-XX:SurvivorRatio=8,Eden:S0:S1 = 8:1:1
假如:-XX:SurvivorRatio=4,就是 Eden:S0:S1 = 4:1:1
SurvivorRatio值就是设置eden区的比例占多少,S0/S1相同如下默认情况: -XX:SurvivorRatio=8
C:\Users\18133\IdeaProjects\javastudy>jps -l 18116 org.jetbrains.jps.cmdline.Launcher 3860 org.jetbrains.idea.maven.server.RemoteMavenServer 12424 com.fangyajun.javastudy.HelloGc 14168 2812 sun.tools.jps.Jps C:\Users\18133\IdeaProjects\javastudy>jinfo -flag SurvivorRatio 12424 -XX:SurvivorRatio=8
-
-XX:NewRatio:配置年轻代与老年代在堆中的占比
默认:-XX:NewRatio=2 新生代占1,老年代占2,年轻代占整个堆内存的1/3
假如:-XX:NewRatio=4 表示新生代占1,老年代占4,年轻代占整个堆内存的1/5,
NewRatio值就是设置老年代的占比,剩下的一给新生代如:我们打印-XX:PrintGCDetails,可以看出信息
运行结果:
Heap PSYoungGen total 75776K, used 6503K [0x000000076b580000, 0x0000000770a00000, 0x00000007c0000000) eden space 65024K, 10% used [0x000000076b580000,0x000000076bbd9e20,0x000000076f500000) from space 10752K, 0% used [0x000000076ff80000,0x000000076ff80000,0x0000000770a00000) to space 10752K, 0% used [0x000000076f500000,0x000000076f500000,0x000000076ff80000) ParOldGen total 173568K, used 0K [0x00000006c2000000, 0x00000006cc980000, 0x000000076b580000) object space 173568K, 0% used [0x00000006c2000000,0x00000006c2000000,0x00000006cc980000) Metaspace used 3267K, capacity 4496K, committed 4864K, reserved 1056768K class space used 358K, capacity 388K, committed 512K, reserved 1048576K
从结果可以看出,新生代内存占用75776K,老年代内存占用173568K,二者的比例接近1:2
-
-XX:MaxTenuringThreshold:设置进入年老代的年龄
默认:系统默认是15:表示在年轻代经过15次垃圾回收没有被回收的对象就进入年老代。C:\Users\18133\IdeaProjects\javastudy>jinfo -flag MaxTenuringThreshold 16200 -XX:MaxTenuringThreshold=15
注意:在jdk8及以后,MaxTenuringThreshold只能是0-15之间,如下示例调成20会报错
参数配置案例:
看如下参数配置:
-Xms128m -Xmx4096m -Xss1024k -XX:MetaspaceSize=512m -XX:+PrintCommandLineFlags
-XX:+PrintGCDetails -XX:+UseSerialGC
以上参数表示:初始堆内存128m,最大堆内存4096m,初始 栈大小1024k,元空间大小512m,开启打印命令行初始参数配置,开启打印GC回收细节,开启串型垃圾回收器
程序代码:
public class HelloGc {
public static void main(String[] args) throws InterruptedException {
System.out.println("-------------------");
Thread.sleep(Integer.MAX_VALUE);
}
}
没有配参数前:参数行就配置-XX:+PrintCommandLineFlags 这个参数
运行结果:
-XX:InitialHeapSize=266275648
-XX:MaxHeapSize=4260410368
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
配参数后:
运行结果:
-XX:InitialHeapSize=134217728
-XX:MaxHeapSize=4294967296
-XX:MetaspaceSize=536870912
-XX:+PrintCommandLineFlags
-XX:+PrintGCDetails
-XX:ThreadStackSize=1024
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation
-XX:+UseSerialGC
从2个结果对比可以看出,配置的 参数已经生效,在实际的工作中,一般需要配置的参数也就是上面那些常用参数配置。
版权声明:本文标题:JVM参数配置详解 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1727947978a1139212.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论