JVM性能

简介: JVM性能

JVMJava Virtual MachineJava虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。


引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。在JDK1.7之前JVM存在年轻代(Young Generation)、年老代(Old Generationn)和持久代(Permanent Generation)。


1. 年轻代与年老代中没有被回收的数据块存储


      年轻代分为Eden区和Survivor区。Eden区有一个存储单元,Survivor区有两个存储单元,为了描述方便,假设Eden区做多可以存储三个数据块,Survivor区做多可以存储四个数据块。年老代也只有一个区,最多可存储四个数据块。下面来看一下年轻代与年老代中没有被回收的数据块存储。

               


image.png

3-36  年轻代与年老代中没有被回收的数据块存储


1)新来数据块a1a2,进入年轻代的Eden区。见图3-361)所示。


2)数据块a3 产生,进入Eden区,Eden区满了,把a1a2a3移入Survivor区的第一个存储单元。见图3-362)所示。


3Eden区的指针指向Survivor区的第一个存储单元。数据块a2a3被回收,留下了数据块a1Eden区进入了数据块b1b2。见图3-363)所示。


4)数据块b3 产生,进入Eden区,Eden区满了,把b1b2b3移入Survivor区的第一个存储单元。见图3-364)所示。


5Survivor区第一个存储单元满了,把a1b1b2b3Survivor区的第一个存储单元移入Survivor区的第二个存储单元。见图3-365)所示。


6Eden区的指针指向Survivor区的第二个存储单元。数据块c1c2产生,进入Eden区, Survivor区的第二个存储单元中b3被回收,剩下a1b1b2。见图3-366)所示。


7Eden区产生数据块c3Eden区满了,这时候由于Survivor区的第二个存储单元a1被回收,而b1b2没有被回收,所以这时候只能把Eden区的c1c2Eden区移入Survivor区的第二个存储单元。见图3-367)所示。


8Survivor区的第二个存储单元中存在b1b2c1c2,这时候Survivor区的第二个存储单元满了,但是由于b1b2是从Survivor区的第二个存储单元中过来的,而c1c2是从Eden区过来的,所以只能把数据块b1b2Survivor区的第二个存储单元移入到年老代。见图3-368)所示。


9)这个时候再把Eden区的数据块c3Eden区移入Survivor区的第二个存储单元。见图3-369)所示。


10Eden区产生数据块d1d3d3Eden区满了,而Survivor区的第二个存储单元仅存在了数据块c3,把Eden区的d1d3d3移入Survivor区的第二个存储单元。见图3-3610)所示。


11)由于当前Survivor区的第二个存储单元中的数据块c3d1d3d3都是从Eden区过来的,这个时候Survivor区已经满了,所以要把数据块c3d1d3d3Survivor区的第二个存储单元移到Survivor区的第一个存储单元。见图3-3611)所示。


12Eden区的指针返回指向Survivor区的第一个存储单元。Eden区产生了新的数据块e1e2Survivor区的第一个存储单元中的d1d3被回收,剩下c3d2。见图3-3612)所示。


13Eden区产生数据块e3Eden区满了,这时候Survivor区的第一个存储单元中存在数据块c3d2,所以只能把Eden区的e1e2先移入到Survivor区的第一个存储单元中。见图3-3613)所示。


14Survivor区的第一个存储单元中目前存在数据块c3d2e1e2,由于c3d2是从Survivor区的第二个存储单元中过来的,而e1e2是从Eden区过来的,所以只能把c3d2Survivor区的第一个存储单元中移入到老年代。见图3-3614)所示。


15)接下来再把Eden区产生数据块e3移入到Survivor区的第一个存储单元。见图3-3615)所示。


16)按照这种规律进行下去。


17)这个时候,Eden区有数据块g1g2Survivor区的第二个存储单元e1e2 f1f2,年老代中存在数据块b1b2c1d2。见图3-3617)所示。


18Survivor区的第二个存储单元与年老代中存在数据块都满,把年老代中得数据块丢弃,把Survivor区的Survivor区的第一个存储单元数据块中e1e2移入年老代。见图3-3618)所示。按照这个规律进行下去


由此看见。

新产生的数据首先进入Eden区。

Eden区的数据满后进入Survivor区。

只有在两个Survivor区都存储过的数据才可以进入老年代。

Eden区轮询指向Survivor区中的两个区。

老年代存在数据,但是年轻代数据已满,会清空老年代。


2. 元空间


由于持久代的问题比较多,从JDK8开始废弃了持久代迎来元空间(Metaspace),官方原文是这样写的:This is part of theJRockit and Hotspot convergence effort. JRockit customers do not need toconfigure the permanent generation (since JRockit does not have a permanentgeneration) and are accustomed to not configuring the permanent generation.


下面来看一下元空间。

•元空间的内存大小。

元空间是方法区的在HotSpot jvm 中的实现,方法区主要用于存储类的信息、常量池、方法数据、方法代码等。方法区逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫“非堆”。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。,理论上取决于32/64位系统可虚拟的内存大小。可见也不是无限制的,需要配置参数。


•常用配置参数。

ØMetaspaceSize

初始化的Metaspace大小,控制元空间发生GC的阈值。GC后,动态增加或降低MetaspaceSize。在默认情况下,这个值大小根据不同的平台在12M20M浮动。使用Java -XX:+PrintFlagsInitial命令可以查看初始化参数。


ØMaxMetaspaceSize

限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序。该参数的默认值为4294967295B(大约4096MB)。


ØMinMetaspaceFreeRatio

当进行过Metaspace GC以后,会计算当前Metaspace的空闲空间的比例,如果这个比例小于这个参数(即实际非空闲占比过大,内存不够用),那么虚拟机将增长Metaspace的大小。参数的默认值为40%。设置该参数可以控制Metaspace的增长的速度,设置得太小会导致Metaspace增长的缓慢,Metaspace的使用逐渐趋于饱和,可能会影响之后类的加载。而设置得太大,会导致Metaspace增长的过快,浪费内存。


ØMaxMetasaceFreeRatio

当进行过Metaspace GC之后,会计算当前Metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机就会释放Metaspace的部分空间。参数的默认值为70%


ØMaxMetaspaceExpansion

Metaspace增长时的最大幅度。该参数的默认值为5452592B(大约为5MB)。

ØMinMetaspaceExpansion

Metaspace增长时的最小幅度。该参数的默认值为340784B(大约330KB为)。


3. jps


jpsJava VirtualMachine Process Status Tool)是Java提供的一个显示当前所有Java进程pid的命令。

命令格式:jps [options ] [ hostid ]


[options]选项。

Ø-q。仅输出VM标识符,不包括classname,jar name,argumentsin main method

Ø-m。输出main method的参数。

Ø-l。输出完全的包名,应用主类名,jar的完全路径名。

Ø-v。输出jvm参数。

Ø-V。输出通过flag文件传递到JVM中的参数(.hotspotrc文件或-XX:Flags=所指定的文件。

Ø-Joption。传递参数到vm,例如:-J-Xms512m


[hostid]

[protocol:][[//]hostname][:port][/servername]


•命令的输出格式。

lvmid [ [ classname| JARfilename | "Unknown"] [ arg* ] [jvmarg* ] ]


jps。做基本使用方式。

>jps
20388 Bootstrap
14364 Jps

jps -l。输出主类或者jar的完全路径名。

>jps -l
18756 sun.tools.jps.Jps
20388 org.apache.catalina.startup.Bootstrap


jps -v。输出jvm参数。

>jps -v
20388 Bootstrap-Djava.util.logging.config.file=C:\xampp\tomcat\conf\logging.properties-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager-Djava.endorsed.dirs=C:\xampp\tomcat\endorsed -Dcatalina.base=C:\xampp\tomcat-Dcatalina.home=C:\xampp\tomcat -Djava.io.tmpdir=C:\xampp\tomcat\temp
13948 Jps -Denv.class.path=C:\ProgramFiles\Java\jdk1.8.0_131\\lib\dt.jar;C:\Program Files\Java\jdk1.8.0_131\\lib\tools.jar;C:\apache\apache-tomcat-8.0.30\lib\servlet-api.jar;-Dapplication.home=C:\Program Files\Java\jdk1.8.0_131 -Xms8m


jps -q。仅仅显示java进程号。

>jps -q
20388
server.resin.Resin


jps -mlv <IP>。远程查看


4. jstat


      jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。关于jstat的使用查看表3-15所示。


3-15 jstat命令

参数

解释

jstat –class<pid>

显示加载class的数量,及所占空间等信息

jstat -compiler <pid>

显示VM实时编译的数量等信息

jstat -gc <pid>

可以显示gc的信息,查看gc的次数,及时间

jstat -gccapacity <pid>

可以显示,VM内存中(young,old)对象的使用和占用大小

jstat -gcutil <pid>

统计gc信息

jstat -gcnew <pid>

年轻代对象的信息

jstat -gcnewcapacity<pid>

年轻代对象的信息及其占用量

jstat -gcold <pid>

old代对象的信息

jstat -gcoldcapacity <pid>

old代对象的信息及其占用量

jstat -printcompilation <pid>

当前VM执行的信息


5. jVisualVM & jmap


      通过命令jmap-dump:format=b,file=<path>\<filename>.hprof  <pid>,把<pid>的信息导入.hprof格式的文件,然后打开jVisualVMGUI 界面,载入刚生成的.hprof文件,即可查看该进程在JVM的信息了。如图3-36所示。

image.png

3-36  jVisualVM


星云测试

http://www.teststars.cc

奇林软件

http://www.kylinpet.com

联合通测

http://www.quicktesting.net

目录
相关文章
|
2月前
|
存储 监控 算法
jvm-性能调优(二)
jvm-性能调优(二)
|
4月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
427 3
|
4月前
|
监控 Java 测试技术
JVM 性能调优 及 为什么要减少 Full GC
JVM 性能调优 及 为什么要减少 Full GC
121 4
|
5月前
|
监控 Java 调度
探秘Java虚拟机(JVM)性能调优:技术要点与实战策略
【6月更文挑战第30天】**探索JVM性能调优:**关注堆内存配置(Xms, Xmx, XX:NewRatio, XX:SurvivorRatio),选择适合的垃圾收集器(如Parallel, CMS, G1),利用jstat, jmap等工具诊断,解决Full GC问题,实战中结合MAT分析内存泄露。调优是平衡内存占用、延迟和吞吐量的艺术,借助VisualVM等工具提升系统在高负载下的稳定性与效率。
102 1
|
1月前
|
存储 缓存 监控
聊聊JIT是如何影响JVM性能的!
聊聊JIT是如何影响JVM性能的!
|
2月前
|
Kubernetes Java 编译器
解锁极致性能:Quarkus如何让JVM应用调优变得前所未有的简单与高效!
Quarkus是一款专为GraalVM和OpenJDK设计的Kubernetes Native Java框架,采用AOT编译技术将Java应用转化为本地代码,大幅提升启动速度与运行效率。它简化了性能调优流程,如自动优化垃圾回收、类加载、内存管理及线程管理等,使开发者无需深入理解JVM细节即可轻松提升应用性能。与传统JVM应用相比,Quarkus显著降低了性能调优的复杂度。
99 2
|
4月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
106 8
|
4月前
|
缓存 监控 Java
Java虚拟机(JVM)性能调优实战指南
在追求软件开发卓越的征途中,Java虚拟机(JVM)性能调优是一个不可或缺的环节。本文将通过具体的数据和案例,深入探讨JVM性能调优的理论基础与实践技巧,旨在为广大Java开发者提供一套系统化的性能优化方案。文章首先剖析了JVM内存管理机制的工作原理,然后通过对比分析不同垃圾收集器的适用场景及性能表现,为读者揭示了选择合适垃圾回收策略的数据支持。接下来,结合线程管理和JIT编译优化等高级话题,文章详细阐述了如何利用现代JVM提供的丰富工具进行问题诊断和性能监控。最后,通过实际案例分析,展示了性能调优过程中可能遇到的挑战及应对策略,确保读者能够将理论运用于实践,有效提升Java应用的性能。 【
202 10
|
4月前
|
JSON Java BI
一次Java性能调优实践【代码+JVM 性能提升70%】
这是我第一次对系统进行调优,涉及代码和JVM层面的调优。如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误。本次调优的代码是埋点系统中的报表分析功能,小公司,开发结束后,没有Code Review环节,所以下面某些问题,也许在Code Review环节就可以避免。
162 0
一次Java性能调优实践【代码+JVM 性能提升70%】
|
3月前
|
监控 算法 Java
深入理解Java虚拟机:JVM调优与性能提升
本文旨在为Java开发者提供一条清晰的路径,以深入掌握Java虚拟机(JVM)的内部机制和性能调优技巧。通过具体案例分析,我们将探讨如何识别性能瓶颈、选择合适的工具进行监控与调试,以及实施有效的优化策略,最终达到提高应用程序性能的目的。文章不仅关注理论,更注重实践应用,帮助读者在面对复杂的Java应用时能够游刃有余。
72 0