0
点赞
收藏
分享

微信扫一扫

Java虚拟机(JVM_3)


深入学习

3.1 JVM参数

3.1.1 标准参数

-version -help -server -cp

Java虚拟机(JVM_3)_JVM



3.1.2 -X参数

非标准参数,各个jdk版本中可能会变化

-Xint 解释执行模式

-Xcomp 编译模式

-Xmixed 混合模式 由JVM自己决定

Java虚拟机(JVM_3)_G1_02



3.1.3 -XX参数

使用最多的参数,非标准化参数,主要用于JVM调优和Debug

a.Boolean类型:-XX:[+-]<name> + -符号表示启用/禁用

例如:-XX:+UseG1GC

b.非Boolean类型 -XX:<name>=<value> <value>表示属性的值

例如:-XX:MaxHeapSize=1024M


3.1.4 其他参数

-Xms1024M ==> -XX:InitialHeapSize=1024M

-Xmx1024M ==> -XX:MaxHeapSize=1024M

-Xss512M ==> -XX:ThreadStackSize=512M


3.1.5 查看参数

java -XX:+PrintFlagsFinal -version > flags.txt

Java虚拟机(JVM_3)_老年代_03


其中“=”表示默认值 “:=”表示被程序员或者JVM修改过的值


3.1.6 常用参数含义


参数

含义

说明

-XX:CICompilerCount=3

最大并行编译数

如果设置大于1,虽然编译速度

会提高,但是同样影响系统稳定

性,会增加JVM崩溃的可能

-XX:InitialHeapSize=100M

初始化堆大小

简写-Xms100M

-XX:MaxHeapSize=100M

最大堆大小

简写-Xmx100M

-XX:NewSize=20M

设置年轻代的大小


-XX:MaxNewSize=50M

年轻代最大大小


-XX:OldSize=50M

设置老年代大小


XX:MetaspaceSize=50M

设置方法区大小


-XX:MaxMetaspaceSize=50M

方法区最大大小


-XX:+UseParallelGC

使用ParallelGC

新生代,吞吐量优先

-XX:+UseParallelOldGC

使用ParallelOldGC

老年代,吞吐量优先

-XX:+UseConcMarkSweepGC

使用CMS

老年代,停顿时间优先

-XX:+UseG1GC

使用G1 GC

新生代、老年代停顿时间优先

-XX:NewRatio

新生代和老年代的比值

比如-XX:Ratio=4,则表示新生代:老年代=1:4,也就是新生代占整个堆内存的1/5

-XX:SurvivorRatio

两个S区和Eden区的比值

比如-XX:SurvivorRatio=8,也就是(S0+S1):Eden=2:8,也就是一个S占整个新生代的1/10

-XX:+HeapDumpOnOutOfMemoryError

启动堆内存溢出打印

当JVM堆内存发生溢出时,也就是OOM,自动生成dump文件

-XX:HeapDumpPath=heap.hprof

指定堆内存溢出打印目录

表示在当前目录生成一个

heap.hprof文件

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-XX:+PrintGCDateStamps

打印GC日志


-XX:ThreadStackSize=512k

设置每个线程的堆栈大小

-Xss128k

-XX:MaxTenuringThreshold=6

提升年老代的最大临界值 默认值为 15

在对象头中,只占4bit,该值最大值为15

-XX:InitiatingHeapOccupancyPercent

启动并发GC周期时堆内存使用占比

G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比.值为 0 则表示”一直执行GC循环”.默认值为 45.

-XX:G1HeapWastePercent

允许的浪费堆空间的占比

默认是10%,如果并发标记可回收的空间小于10%,则不会触发MixedGC。

-XX:MaxGCPauseMillis=200ms

G1最大停顿时间

暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。

-XX:Cnotallow=n

并发垃圾收集器使用的线程数量

默认值随JVM运行的平台不同而不同

-XX:G1MixedGCLiveThresholdPercent=65

混合垃圾回收周期中要包括的旧区域设置占用率阈值

默认占用率为 65%

-XX:G1MixedGCCountTarget=8

设置标记周期完成后,对存活数据上限为G1MixedGCLIveThresholdPercent的旧区域执行混合垃圾回收的目标次数

默认8次混合垃圾回收,混合回收的目标是要控制在此目标次数以内

-XX:G1OldCSetReginotallow=1

描述Mixed GC时,Old Region被加入到CSet中

默认情况下,G1只把10%的OldRegion加入到CSet中



3.2 常用命令

3.2.1 jps

查看java进程

Java虚拟机(JVM_3)_G1_04



3.2.2 jinfo

实时查看和调整JVM配置参数

jinfo -flag 参数名 pid 查看参数的值

例如; jinfo -flag MaxHeapSize 2169928

jinfo -flag InitialHeapSize 2169928

Java虚拟机(JVM_3)_G1_05



修改:参数只有被标记为manageable 的flags可以被实时修改

jinfo -flag [+|-] PID

jinfo -flag <name>=<value> PID


查看曾经赋过值的一些参数

jinfo -flags PID

Java虚拟机(JVM_3)_JVM_06



3.2.3 jstat

查看虚拟机性能统计信息;

查看类装载信息

jstat -class PID 1000 10 查看该java进程的类装载信息,每1000毫秒输出一次,共10次

Java虚拟机(JVM_3)_老年代_07



查看垃圾收集信息

jstat -gc PID 1000 10 查看该java进程的gc信息,每1000毫秒输出一次,共10次

Java虚拟机(JVM_3)_G1_08



3.2.4 jstack

查看线程堆栈信息

Java虚拟机(JVM_3)_老年代_09


用法:jstack PID

Java虚拟机(JVM_3)_老年代_10



死锁案列:

Java虚拟机(JVM_3)_G1_11


运行结果:

Java虚拟机(JVM_3)_JVM_12



jstack分析,拉到最后:

Java虚拟机(JVM_3)_老年代_13



3.2.5 jmap

生成堆转储快照:

Java虚拟机(JVM_3)_JVM_14


打印堆内存相关信息:

Java虚拟机(JVM_3)_老年代_15



dump出堆内存相关信息: jmap -dump:format=b,file=heap.hprof PID

Java虚拟机(JVM_3)_JVM_16



设置JVM参数,当堆内存溢出时,自动dump出文件:

XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=heap.hprof


性能优化

JVM性能优化可以分为代码层面和非代码层面。代码层面一般结合字节码进行优化,非代码层面一般从内存,gc,CPU占用率等方面进行优化。JVM一般不需要优化。


4.1 内存

4.1.1 内存分配

正常情况下不需要设置,但在秒杀和促销的场景下,需要调整。默认情况下young:old=1:2,秒杀的情况下,就可能出现young区内存不够


4.1.2 内存溢出(OOM)

一般有两种原因:1.大并发场景 2:内存泄漏导致OOM


4.1.2.1 大并发(秒杀)优化

a.浏览器缓存、本地缓存、验证码

b.CDN静态资源服务器

c.集群+负载均衡

d.动静态资源分离、限流(基于令牌桶、漏桶算法)

e.应用级别缓存、接口防刷限流、队列、tomcat性能优化

f.异步消息中间件

g.Redis热点数据对象缓存(数据预热)

h.分布式锁、数据库锁

i.5分钟内没有支付订单,取消订单,恢复库存


4.1.2.2 内存泄漏导致内存溢出

ThreadLocal 使用完未删除,会导致内存泄漏


4.2 GC

4.2.1 是否选用G1

官网:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/G1.html#use_cases

a.50%以上的堆被存活对象占用

b.对象分配和晋升速度变化比较大

c.垃圾回收时间比较长

4.2.2 G1调优

a.使用G1垃圾收集器:-XX:+UseG1GC

获取GC日志,使用GCViewer分析吞吐量和响应时间


b.调整内存大小之后,再获取gc日志分析

可以调整内存的大小

最大停顿时间:-XX:MaxGCPauseNillis=200

启动并发GC时堆内存占用百分比:-XX:InitiatingHeapOccupancyPercent=45


4.3 JVM性能优化指南

Java虚拟机(JVM_3)_G1_17



4.4. 常见问题

4.4.1 内存泄漏与内存溢出的区别

内存泄漏是指不再使用的对象无法得到及时的回收,持续占用内存空间,从而造成内存空间的浪费。内存泄漏很容易导致内存溢出,但内存溢出不一定是内存泄漏导致的。


4.4.2 young GC会有stw嘛?

无论什么


4.4.3 major gc 和full gc的区别

Major GC在很多参考资料中是等价于 Full GC 的,我们也可以发现很多性能监测工具中只有 Minor GC 和 Full GC。一般情况下,一次 Full GC 将会对年轻代、老年代、元空间以及堆外内存进行垃圾回收。触 发 Full GC 的原因有很多:当年轻代晋升到老年代的对象大小,并比目前老年代剩余的空间大小还要大 时,会触发 Full GC;当老年代的空间使用率超过某阈值时,会触发 Full GC;当元空间不足时(JDK1.7 永久代不足),也会触发 Full GC;System.gc() 也会安排一次 Full GC。


4.4.4 什么是直接内存

Java的NIO库允许Java程序使用直接内存。直接内存是在java堆外的、直接向系统申请的内存空间。通 常访问直接内存的速度会优于Java堆。因此出于性能的考虑,读写频繁的场合可能会考虑使用直接内 存。由于直接内存在java堆外,因此它的大小不会直接受限于Xmx指定的最大堆大小,但是系统内存是 有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存


4.4.5 垃圾判断方式

引用计数法:指的是如果某个地方引用了这个对象就+1,如果失效了就-1,当为0就会回收但是JVM没 有用这种方式,因为无法判定相互循环引用(A引用B,B引用A)的情况。

根可达:通过一种GC ROOT的对象(方法区中静态变量引用的对象等-static变量)来判断,如果有 一条链能够到达GC ROOT就说明,不能到达GC ROOT就说明可以回收。


4.4.6 不可达对象一定要被回收嘛

即使在可达性分析法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑阶段”,要真 正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行 一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法。当对象没有覆盖 finalize 方法,或 finalize 方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。 被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个 对象建立关联,否则就会被真的回收。


4.4.7 为什么要区分新生代和老年代

虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将


4.4.8 G1和CMS的区别是什么?

CMS 主要集中在老年代的回收,而 G1 集中在分代回收,包括了年轻代的 Young GC 以及老年代的 Mix GC;G1 使用了 Region 方式对堆内存进行了划分,且基于标记整理算法实现,整体减少了垃圾碎片的 产生;在初始化标记阶段,搜索可达对象使用到的 Card Table,其实现方式不一样。


4.4.9 方法区中的无用类回收

方法区主要回收的是无用的类,那么如何判断一个类是无用的类的呢?判定一个常量是否是“废弃常量”比较简单,而要判定一个类是否是“无用的类”的条件则相对苛刻许多。 类需要同时满足下面 3 个条件才能算是 “无用的类” :

a-该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。

b-加载该类的 ClassLoader 已经被回收。

c-该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。



举报

相关推荐

0 条评论