JVM 之入门

三种参数类型

jvm的参数类型分为三类,分别是:

  • 标准参数
    -help
    -version
  • -X参数 (非标准参数)
    -Xint
    -Xcomp
  • -XX参数(使用率较高)
    -XX:newSize
    -XX:+UseSerialGC

标准参数

jvm的标准参数,一般都是很稳定的,在未来的JVM版本中不会改变,可以使用java -help检索出所有的标准参数。
在这里插入图片描述

实战

实战1:查看jvm版本
在这里插入图片描述
实战2:通过-D设置系统属性参数

public class TestJVM {
    public static void main(String[] args) {
        String str = System.getProperty("str");
        if (str == null) {
            System.out.println("yq");
        } else {
            System.out.println(str);
        }
    }
}

进行编译、测试:

# 编译
javac TestJVM.java
# 测试
java TestJVM
yq
# 设置参数测试
java -Dstr=James TestJVM
James

-server与-client参数(了解)

可以通过-server或-client设置jvm的运行参数。

  • 它们的区别是Server VM的初始堆空间会大一些,默认使用的是并行垃圾回收器,启动慢运行快。
  • Client VM相对来讲会保守一些,初始堆空间会小一些,使用串行的垃圾回收器,它的目标是为了让JVM的启动速度更快,但运行速度会比Serverm模式慢些。
  • JVM在启动的时候会根据硬件和操作系统自动选择使用Server还是Client类型的JVM。
  • 32位操作系统
    – 如果是Windows系统,不论硬件配置如何,都默认使用Client类型的JVM。
    – 如果是其他操作系统上,机器配置有2GB以上的内存同时有2个以上CPU的话默认使用server模式,否则使用client模式。
  • 64位操作系统
    – 只有server类型,不支持client类型。

测试:(#由于机器是64位系统,所以不支持client模式)
在这里插入图片描述

-X参数

jvm的-X参数是非标准参数,在不同版本的jvm中,参数可能会有所不同,可以通过java -X查看非标准参数。
在这里插入图片描述

-XX参数

-XX参数也是非标准参数,主要用于jvm的调优和debug操作。
-XX参数的使用有2种方式,一种是boolean类型,一种是非boolean类型:

  • boolean类型
    格式:-XX:[+-]<name> 表示启用或禁用<name>属性
    如:-XX:+DisableExplicitGC 表示禁用手动调用gc操作,也就是说调用System.gc()无效
  • 非boolean类型
    格式:-XX:<name>=<value> 表示<name>属性的值为<value>
    如:-XX:NewRatio=1 表示新生代和老年代的比值
java -showversion -XX:+DisableExplicitGC TestJVM

-Xms与-Xmx参数(重要)

-Xms:设置初始 Java 堆大小。
-Xmx:设置最大 Java 堆大小。
-Xmx2048m:等价于-XX:MaxHeapSize,设置JVM最大堆内存为2048M。
-Xms512m:等价于-XX:InitialHeapSize,设置JVM初始堆内存为512M。
适当的调整jvm的内存大小,可以充分利用服务器资源,让程序跑的更快。

java -Xms512m -Xmx2048m TestJVM

查看jvm的运行参数

运行java命令时打印参数:

# 参数有boolean类型和数字类型,值的操作符是=或:=,分别代表默认值和被修改的值。
java -XX:+PrintFlagsFinal -version

查看正在运行的jvm参数:

# 首先,启动一个tomcat用于测试,来观察下运行的jvm参数。
# 查看所有的参数,
# 用法:jinfo -flags <进程id> 
# 通过jps 或者 jps -l 查看java进程
root@ubuntu:bin# jps
1698 Jps
1485 Bootstrap
root@ubuntu:bin# jps -l
1485 org.apache.catalina.startup.Bootstrap
1711 sun.tools.jps.Jps
root@ubuntu:bin# jinfo -flags 1485
Attaching to process ID 1485, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.141-b15
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=16777216 -XX:MaxHeapSize=262144000 -XX:MaxNewSize=87359488 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=5570560 -XX:OldSize=11206656 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps 
Command line:  -Djava.util.logging.config.file=/opt/apache-tomcat-7.0.57/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/opt/apache-tomcat-7.0.57/endorsed -Dcatalina.base=/opt/apache-tomcat-7.0.57 -Dcatalina.home=/opt/apache-tomcat-7.0.57 -Djava.io.tmpdir=/opt/apache-tomcat-7.0.57/temp

# 查看某一参数的值,用法:jinfo -flag <参数名> <进程id>
root@ubuntu:bin# jinfo -flag MaxHeapSize 1485
-XX:MaxHeapSize=262144000

jvm的内存模型

jdk1.7的堆内存模型

在这里插入图片描述

  • Young 年轻区(代)
    Young区被划分为三部分,Eden区和两个大小严格相同的Survivor区,其中,Survivor区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用,在Eden区间变满的时候, GC就会将存活的对象移到空闲的Survivor区间中,根据JVM的策略,在经过几次垃圾收集后,任然存活于Survivor的对象将被移动到Tenured区间。
  • Tenured 年老区
    Tenured区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young复制转移一定的次数以后,对象就会被转移到Tenured区,一般如果系统中用了application级别的缓存,缓存中的对象往往会被转移到这一区间。
  • Perm 永久区
    Perm代主要保存class,method,filed对象,这部份的空间一般不会溢出,除非一次性加载了很多的类,不过在涉及到热部署的应用服务器的时候,有时候会遇到java.lang.OutOfMemoryError : PermGen space 的错误,造成这个错误的很大原因就有可能是每次都重新部署,但是重新部署后,类的class没有被卸载掉,这样就造成了大量的class对象保存在了perm中,这种情况下,一般重新启动应用服务器可以解决问题。
  • Virtual区:
    最大内存和初始内存的差值,就是Virtual区。

jdk1.8的堆内存模型

在这里插入图片描述
由上图可以看出,jdk1.8的内存模型是由2部分组成,年轻代 + 年老代。
年轻代:Eden + 2*Survivor
年老代:OldGen
在jdk1.8中变化最大的Perm区,用Metaspace(元数据空间)进行了替换。
需要特别说明的是:Metaspace所占用的内存空间不是在虚拟机内部,而是在本地内存空间中,这也是与1.7的永久代最大的区别所在。
在这里插入图片描述

为什么要废弃1.7中的永久区?

在这里插入图片描述

通过jstat命令进行查看堆内存使用情况

jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下:

jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]

查看class加载统计

root@ubuntu:bin# jps
1939 Jps
1926 Bootstrap
root@ubuntu:bin# jstat -class 1926
Loaded  Bytes  Unloaded  Bytes     Time   
  2768  5470.3        0     0.0       1.74

说明:

  • Loaded:加载class的数量
  • Bytes:所占用空间大小
  • Unloaded:未加载数量
  • Bytes:未加载占用空间
  • Time:时间

查看编译统计

root@ubuntu:bin# jstat -compiler 1926
Compiled Failed Invalid   Time   FailedType FailedMethod
    1741      1       0     3.38          1 sun/misc/URLClassPath getResource

说明:

  • Compiled:编译数量。
  • Failed:失败数量
  • Invalid:不可用数量
  • Time:时间
  • FailedType:失败类型
  • FailedMethod:失败的方法

垃圾回收统计

root@ubuntu:bin# jstat -gc 1926
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
832.0  832.0  832.0   0.0    6976.0   3395.3   17256.0    15882.2   17024.0 16527.3 1920.0 1825.1     20    0.077   1      0.022    0.099

#也可以指定打印的间隔和次数,每1秒中打印一次,共打印5次
root@ubuntu:bin# jstat -gc 1926 1000 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
832.0  832.0  832.0   0.0    6976.0   4058.7   17256.0    15882.2   17024.0 16527.3 1920.0 1825.1     20    0.077   1      0.022    0.099
832.0  832.0  832.0   0.0    6976.0   4058.7   17256.0    15882.2   17024.0 16527.3 1920.0 1825.1     20    0.077   1      0.022    0.099
832.0  832.0  832.0   0.0    6976.0   4058.7   17256.0    15882.2   17024.0 16527.3 1920.0 1825.1     20    0.077   1      0.022    0.099
832.0  832.0  832.0   0.0    6976.0   4058.7   17256.0    15882.2   17024.0 16527.3 1920.0 1825.1     20    0.077   1      0.022    0.099
832.0  832.0  832.0   0.0    6976.0   4058.7   17256.0    15882.2   17024.0 16527.3 1920.0 1825.1     20    0.077   1      0.022    0.099

说明:

  • S0C:第一个Survivor区的大小(KB)
  • S1C:第二个Survivor区的大小(KB)
  • S0U:第一个Survivor区的使用大小(KB)
  • S1U:第二个Survivor区的使用大小(KB)
  • EC:Eden区的大小(KB)
  • EU:Eden区的使用大小(KB)
  • OC:老年代区大小(KB)
  • OU:老年代使用大小(KB)
  • MC:方法区(永久代、元数据区)的大小(KB)
  • MU:方法区(永久代、元数据区)的使用大小(KB)
  • CCSC:压缩类空间大小(KB)
  • CCSU:压缩类空间使用大小(KB)
  • YGC:系统运行迄今为止的Young GC次数
  • YGCT:Young GC总耗时
  • FGC:系统运行迄今为止的Full GC次数
  • FGCT:Full GC总耗时
  • GCT:所有GC的总耗时

jmap的使用以及内存溢出分析

通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如:内存使用情况的汇总、对内存溢出的定位与分析。

查看内存使用情况

root@ubuntu:~# jps
1926 Bootstrap
2539 Jps
root@ubuntu:~# jmap -heap 1926
Attaching to process ID 1926, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.141-b15

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration: #堆内存配置信息
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 262144000 (250.0MB)
   NewSize                  = 5570560 (5.3125MB)
   MaxNewSize               = 87359488 (83.3125MB)
   OldSize                  = 11206656 (10.6875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage: #堆内存使用情况
New Generation (Eden + 1 Survivor Space): #年轻代
   capacity = 7995392 (7.625MB)
   used     = 5168944 (4.9294891357421875MB)
   free     = 2826448 (2.6955108642578125MB)
   64.64903784579919% used
Eden Space:
   capacity = 7143424 (6.8125MB)
   used     = 4931176 (4.702735900878906MB)
   free     = 2212248 (2.1097640991210938MB)
   69.03098570097477% used
From Space:
   capacity = 851968 (0.8125MB)
   used     = 237768 (0.22675323486328125MB)
   free     = 614200 (0.5857467651367188MB)
   27.90809044471154% used
To Space:
   capacity = 851968 (0.8125MB)
   used     = 0 (0.0MB)
   free     = 851968 (0.8125MB)
   0.0% used
tenured generation: #年老代
   capacity = 17670144 (16.8515625MB)
   used     = 17114592 (16.321746826171875MB)
   free     = 555552 (0.529815673828125MB)
   96.85598487482615% used

12265 interned Strings occupying 1733688 bytes.

查看内存中对象数量及大小

#查看所有对象,包括活跃以及非活跃的
jmap -histo <pid> | more
#查看活跃对象
jmap -histo:live <pid> | more

root@ubuntu:~# jmap -histo:live 1926 | more

 num     #instances         #bytes  class name
----------------------------------------------
   1:         32600        7228680  [C
   2:          1579        1524392  [B
   3:         30967         743208  java.lang.String
   4:          2789         686136  [I
   5:         17142         548544  java.util.HashMap$Node
   6:          3082         350568  java.lang.Class
   7:          5437         333184  [Ljava.lang.Object;
   8:          3738         328944  java.lang.reflect.Method
   9:          1020         206896  [Ljava.util.HashMap$Node;
  10:          3105          99360  java.util.concurrent.ConcurrentHashMap$Node
  11:          1127          96728  [Ljava.lang.String;
  12:          1671          80208  java.util.HashMap
  13:          3278          69952  [Ljava.lang.Class;
  14:            63          66640  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  15:          2741          65784  java.util.ArrayList
  16:          1570          62800  java.util.LinkedHashMap$Entry
  17:          1271          61008  org.apache.tomcat.util.digester.CallMethodRule
  18:          1671          53472  com.sun.org.apache.xerces.internal.xni.QName
  19:           111          51696  [Ljava.util.WeakHashMap$Entry;
  20:          1533          49056  java.util.Hashtable$Entry
  21:           606          48480  java.lang.reflect.Constructor
  22:          2896          46336  java.lang.Object
  23:          1027          41080  java.util.TreeMap$Entry
  24:           846          40608  org.apache.tomcat.util.modeler.AttributeInfo
  25:           914          36560  java.lang.ref.SoftReference
  26:            30          31200  [[C
  27:           921          29472  java.lang.ref.WeakReference
  28:           693          27720  java.lang.ref.Finalizer
  29:          1001          24024  java.util.LinkedList$Node
  30:           309          22248  java.util.logging.Logger
  31:           155          20640  [Ljava.util.Hashtable$Entry;
  32:           615          19680  javax.management.MBeanAttributeInfo
  33:           537          17184  java.util.concurrent.locks.ReentrantLock$NonfairSync
--More--

#对象说明
B byte
C char
D double
F float
I int
J long
Z boolean
[ 数组,如[I表示int[]
[L+类名 其他对象

将内存使用情况dump到文件中

#用法:
jmap -dump:format=b,file=dumpFileName <pid>
#示例
root@ubuntu:~# jmap -dump:format=b,file=./dump.dat 1926
Dumping heap to /root/dump.dat ...
Heap dump file created
root@ubuntu:~# ls
dump.dat
root@ubuntu:~# 

通过jhat对dump文件进行分析

将jvm的内存dump到文件中,文件是一个二进制的文件,不方便查看,这时我们可以借
助于jhat工具进行查看。

#用法:
jhat -port <port> <file>

#示例:
root@ubuntu:~# jhat -port 9999 ./dump.dat 
Reading from ./dump.dat...
Dump file created Thu Jul 02 21:38:10 CST 2020
Snapshot read, resolving...
Resolving 158610 objects...
Chasing references, expect 31 dots...............................
Eliminating duplicate references...............................
Snapshot resolved.
Started HTTP server on port 9999
Server is ready.

打开浏览器进行访问:http://192.168.56.71:9999/
在这里插入图片描述
在最后面有OQL查询功能。
在这里插入图片描述
查询字符串长度大于10000的内容。
在这里插入图片描述

通过MAT工具对dump文件进行分析

-XX:NewSize=5242880 -XX:MaxNewSize=5242880 -XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=10485760 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log

-XX:NewSize 初始新生代大小
-XX:MaxNewSize 最大新生代大小
-XX:InitialHeapSize 初始堆大小
-XX:MaxHeapSize 最大堆大小
-XX:PretenureSizeThreshold=10485760 指定了大对象阈值是10MB

-XX:NewSize=104857600
-XX:MaxNewSize=104857600
-XX:InitialHeapSize=209715200
-XX:MaxHeapSize=209715200
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=15
-XX:PretenureSizeThreshold=20971520
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:gc.log

-Xms4096M -Xmx4096M -Xmn3072M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=92 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSScavengeBeforeRemark

-Xms4096M
-Xmx4096M
-Xmn3072M
-Xss1M
-XX:PermSize=256M
-XX:MaxPermSize=256M
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=92
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSParallelInitialMarkEnabled
-XX:+CMSScavengeBeforeRemark

假设用默认的JVM参数,可能年轻代就几百MB的内存,Survivor区域就几十MB的内存

那么每次垃圾回收过后存活对象可能会有几十MB,这是因为在垃圾回收的一瞬间可能有部分请求没处理完毕,此时会有几十MB对象是存活的,所以很容易触发动态年龄判定规则,让部分对象进入老年代。

jstat显示出来的Full GC和Young GC的次数都是系统启动以来的总次数,耗时都是所有GC加起来的总耗时。

jstat -gc 1000 20
每隔一秒打印一次统计信息,连续打印20次

jmap -dump:live,format=b,file=F:\dump.hprof 6900

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值