JVM参数配置详解

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的对象

  1. 虚拟机栈(栈帧中的局部变量区,也叫局部变量表)中引用的对象。
  2. 方法区中类静态属性引用的对象。
  3. 方法区中常量引用的对象
  4. 本地方法栈中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);
    }
}
  1. 我们先使用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
    
  2. 在使用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进程编号

第二种,查看参数,盘点家底

  1. -XX:PrintFlagsInitial 主要查看初始默认值
    公式:java -XX:+PrintFlagsInitial -versionjava -XX:+PrintFlagsInitial
    如下:这个命令会打印出 所有的JVM初始化参数
    在这里插入图片描述

  2. -XX:PrintFlagsFinal 主要查看修改更新
    公式:java -XX:+PrintFlagsFinal -versionjava -XX:+PrintFlagsFinal
    在这里插入图片描述
    注意
    =号表示没修改过的参数
    := 这样 的符号表示被人为修改过或者JVM修改过的参数
    在这里插入图片描述

  3. -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参数配置

  1. -Xms( -XX:InitialHeapSize): 初始化堆内存一般默认是物理内存的1/64

  2. -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
    
    
  3. -XSS(-XX:ThreadStackSize):设置单个线程栈的大小,一般默认是512k~1024k
    官网描述如下:在这里插入图片描述

  4. -Xmn:设置年轻代大小,默认是堆大小的1/3,一般不用调

  5. -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,
    在实际的系统调优中,这个参数一般可以适当调大一点。

  6. -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后内存占用(该区内存总大小)

  7. -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
    
  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

  9. -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个结果对比可以看出,配置的 参数已经生效,在实际的工作中,一般需要配置的参数也就是上面那些常用参数配置。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值