java虚拟机操作 如何正确学会Java虚拟机调优?
如何正确学会Java虚拟机调优?
一点经验仅供参考,:。
1)堆
运行时数据区,从中分配所有类实例和数组的内存。在Java虚拟机启动时创建。对象的堆内存由一个称为垃圾收集器的自动内存管理系统回收。
这个堆由两部分组成,:。
从一个空间到另一个空间的伊甸园也叫年轻一代,旧空间叫老一代。
其中有S1和S0(会在JDK ;的自带工具),分别引用幸存者空间,存储每次垃圾回收后幸存的对象。
老一代,主要存储应用程序中存活的生命周期长的对象。
垃圾回收主要回收年轻一代块和老一代块的内存,YG用来放新生成的对象,几次没有回收的对象移到OG。
YG垃圾收集也称为MinorGC,OG垃圾收集称为MajorGC。这两个内存集合互不干扰。
2)非堆内存
JVM有一个由所有线程共享的方法区域。方法区域属于非堆内存。它存储每个类的结构,比如运行时常量池、字段和方法数据,以及方法和构造函数的代码。它是在Java虚拟机启动时创建的。
除了方法区域,Java虚拟机实现可能需要内存来进行内部处理或优化,这也是非堆内存。比如JIT编译器需要内存来存储Java虚拟机代码转换来的原生代码,从而获得高性能。
永久代(图中的永久空间)存储JVM 自己的反射对象,比如类对象和方法对象。
3)恢复算法和过程
JVM采用分代收集策略,扫描收集年轻对象的频率高,称为次要收集,而检查收集旧对象的频率低得多,称为主要收集。这样,就没有必要每次GC都检查内存中的所有对象。
当访问一个URL时,内存应用过程如下:
A.JVM将尝试在Eden中为相关的Java对象初始化一个内存区域。
B.当Eden有足够的空间时,内存应用程序就结束了。否则转到下一步。
C.JVM试图释放Eden中所有不活动的对象(属于1或更高的垃圾收集)。如果伊登被释放了,n空间还是不够放新的对象,所以我们尝试把伊甸园里的一些活动对象放到幸存者区。
D.幸存者区被用作伊甸园和旧世界的中间交换区。当旧区的空间足够时,幸存者区的对象将被移到旧区,否则它们将被保留在幸存者区。
E.当旧区域中没有足够的空间时,JVM将在旧区域中进行完整的垃圾收集(0级)。
F.完成垃圾收集后,如果幸存者和旧区仍然可以 t存储一些从Eden复制的对象,这样JVM就可以 不要在Eden区域为新对象创建内存区域内存不足错误 "会出现。
物体的老化过程
年轻一代的记忆由一个伊甸园(Eden,有趣)和两个幸存者空间(1.4文档中称为半空间)组成。新创建的对象的内存是从eden分配的。两个幸存空间中的一个将总是空闲的,并用作复制集合的目标空间。Minor收集的过程是将现有幸存者空间中的eden和活体对象复制到空闲的幸存者空间中。所谓的幸存者,也就是大部分被实验者在伊甸园出生后,根本一次GC都活不下来。在年轻一代进行一定数量的未成年人收集后,当一个对象年老时,它将被移动到老一代,这就是所谓的保有权。(是不是只有在幸存者空间不足的情况下,旧对象才会终身保有?在当前数据中没有找到描述)
剩余内存空间不足会触发GC,比如eden空间不足,minor收集,old代空间不足,major收集,永久代空间不足会触发full GC。
下一部分解释了当TOMCAT或其他服务器出现以下错误时:的分析。
1.首先:Java堆空间。
解释:
堆大小设置
JVM堆的设置是指在java程序运行过程中,JVM可以分配和使用的内存空间的设置。JVM启动时会自动设置堆大小的值,其初始空间(-Xms)为物理内存的1/64,最大空间(-Xmx)为物理内存的1/4。可以使用JVM提供的-Xmn -Xms -Xmx等选项。进行设置。堆大小是年轻一代和终身通用Aion的总和。
提示:如果JVM中98%的时间用于GC,而可用堆的大小小于2%,就会抛出这个异常消息。
提示:堆大小最多不应该超过可用物理内存的80%。通常,-Xms和-Xmx选项应该设置为相同,并且-Xmn是-Xmx值的1/4。
解决方案:
手动设置堆大小。
修改TOMCAT_并在上面添加下面一行 "回声使用CATALINA_BAS: $卡特琳娜基地 ":
Java代码
s:maxn:maxnewsize 256m
或者修改
在上面加上下面一行 "回声使用CATALINA_BAS: $卡特琳娜基地 ":
JAVA _ OPTS $ JAVA _ OPTS-s:max newsize 256m
2,其次是:PermGen空间。
原因:
PermGen空间的全称是永久生成空间,指的是内存的永久存储区域。这个内存主要由JVM用来存储类和元信息。当类被加载时,它将被放在PermGen空间中,这个空间不同于存储类实例的堆区域。GC(垃圾收集)在主程序运行过程中不会清理PermGen空间,所以如果你的应用非常类,很可能会出现PermGen空间错误,这是web服务器预编译JSP时常见的。如果您在WEB应用程序下使用大量的第三方jar,并且它们的大小超过了jvm的默认大小(4M ),就会生成这个错误消息。
解决方案:
1.手动设置MaxPermSize。
修改TOMCAT _(Linux在x)下,在Java代码中
在上面加上下面一行 "回声使用CATALINA_BAS: $卡特琳娜基地 ":
s:p:maxpermsize 512m
在上面加上下面一行 "回声使用CATALINA_BAS: $卡特琳娜基地 ":
s:p:maxp:p:maxp:p:maxp:minh:ma堆比来指定。
服务器一般会将-Xms和-Xmx设置为相等,以避免在每次GC后调整堆的大小,因此上述两个参数没有用。
-Xmn设置年轻一代的堆大小。
-xx echo 22-@ 。comminheapfreeratio和-xx echo 23-@ 。Commaxheapfreeratio设置空闲内存占总内存的比例范围。这两个参数将影响GC的频率和单个GC的时间消耗。-XX:N:N:MaxN:P:MaxP: JDK下的内存管理工具的使用。
查看jvm内存状态:
jstat -gcutil pid 1000 20
异常情况的例子
jstat -gcutil pid 1000 20
S1和YGC,FGC和GCT
0.00 0.00 99.99 82.51 53.11 2409 1.205 10117 7250.393 7251.598
0.00 0.00 83.42 82.55 53.10 2409 1.205 10118 7252.650 7253.855
0.00 0.00 56.06 82.46 53.10 2410 1.205 10120 7254.467 7255.672
0.00 0.00 32.11 82.55 53.10 2411 1.205 10121 7256.673 7257.877
0.00 0.00 99.99 82.55 53.10 2412 1.205 10123 7257.026 7258.231
0.00 0.00 76.00 82.50 53.10 2412 1.205 10124 7259.241 7260.446
该数据表明,完全GC经常发生。
正常情况的例子
S1和YGC,FGC和GCT
0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031
0.000.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031
0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031
0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031
0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031
0.00 0.00 0.24 55.39 99.60 171 0.667 1339 393.364 394.031
参数含义:
S0:堆上幸存者空间0段的已用空间百分比。
S1:堆上幸存者空间1段的已用空间百分比。
e:堆上Eden空间段的已用空间百分比。
O:旧空间段的已用空间百分比O:堆。
perm空间中已用空间的百分比。
YGC:从程序启动到采样,年轻GC发生的次数。
YCT:年轻GC所用时间(单位秒)
FGC:从程序启动到采样的全GC次数。
FGCT:完全GC所用的时间(单位秒)
GCT:垃圾收集的总时间(单位秒)
2转储内存不足
2.1找出要转储的线程pid。
在Linux下,使用ps -aux。
2.2转储内存使用详细信息
您可以使用以下命令:
jmap-dump: fil:jmap -heap 2343,大家可以看到。
正在附加到进程ID 2343,请稍候...
调试器已成功附加。
检测到服务器编译器。
JVM版本是11.0-b16
使用线程本地对象分配。
8线程并行GC
希普·Configuration:
最小自由比率40
MaxH:
PS年轻一代
伊登·Spac:
容量1260060672 (1201.6875MB)
已用64868288(61.6821484375 MB)
免费(1195192385
5.1428935546367%已使用
来自Spac:
容量85524480 (81.5625MB)
已用空间59457648(56.181152344 MB)
自由26066832(24.888476562 MB)
使用了69.5359195%
去Spac:
容量85852160 (81.875MB)
已用0 (0.0MB)
免费85852160 (81.875MB)
使用了0.0%
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~这三块就是上面说的YG大小和用法。
PS老一代
容量2291138560(2185.0兆字节)
使用了1747845928(17478兆字节)的内存。17687.888686866687
免费的543292632(18.23兆字节)54329253326
使用了76.2099989%
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
PS烫发一代
容量108265472 (103.25MB)
用过的107650712(102.667191772461兆字节)
可用空间614760 (0.5862808227539062MB)
使用了99.3728436%
jstat
Jstat是一个针对vm的状态监控工具,包括类加载、运行时编译和GC。
使用时需要添加查看流程的流程id和选择的参数。下面详细描述了每个参数的含义。
JSTAT-class pid:显示诸如加载的类的数量和占用的空间等信息。
JSTAT-Compil:显示VM实时编译器的数量等信息。
JSTAT-gc pid:可以显示gc的信息,查看GC的次数,以及时间。后五项分别是年轻gc数、年轻gc时间、满gc数、满gc时间、gc总时间。
JSTAT -gccapacity:可以显示VM内存中三代(年轻、年老、perm)对象的使用情况和占用大小,如:PGCMN显示最小perm内存使用情况,PGCMX显示最大perm内存使用情况,PGC显示新生成的perm内存使用情况,PC显示之前的perm内存使用情况。其他的可以据此类推,OC是old中的纯占位。
jstat-gcn:新对象信息。
jstat-gcn:n:old object。
jstat-gcoldpactivity PID : old对象的信息及其占用情况。
pid: P:统计gc信息统计。
打印pid:当前VM执行的编译信息。
除了上面的参数,还可以同时加两个数,比如jstat -printcompilation 3024 250 6每250毫秒打印一次,一共打印6次,还可以加-H3每隔三行显示一次标题。
示例:
jstat -gcutil pid 1000 20
S1和YGC,FGC和GCT
47.49 0.00 64.82 46.08 47.69 20822 2058.631 68 22.734 2081.365
YG GC或MinorGC花了0.06秒
46.69 0.00 15.19 46.18 47.69 20824 2058.776 68 22.734 2081.510
46.69 0.00 74.59 46.18 47.69 20824 2058.776 68 22.734 2081.510
0.00 40.29 19.95 46.24 47.69 20825 2058.848 68 22.734 2081.582
MajorGC平均时间:22.734/680.334秒。
MinorGC平均时间:2058.691/208230.099秒。
作为一名程序员,了解java虚拟机类加载机制,有什么用?
这是一个非常重要的课题。昨天刚写了一篇文章,楼主可以找找看。
Java类加载机制Java中的类加载机制是Java技术体系中相对核心的部分,虽然我们不 t通常接触不多,类装入器也不会。;我不经常和大多数软件开发人员打交道。但是我们在这里学习Java的累加器背后的机制,可以帮助我们理解和排除程序中类加载失败等技术问题,就像上一篇文章中的辐射一样。学完这些,你回头看的时候就容易明白了。
为什么要使用类加载?
在我们学习的java语言中,类的加载是在我们的程序运行时完成的。尽管这种方法在加载类时会给主机增加一点性能开销,但它可以为Java程序提供高度的灵活性。
在我们写完带后缀的文件后,类加载过程。java,这些。java文件将被编译成带后缀的文件。由编译器在java中初始化。在我们走进。类文件,我们可以看到它存储了编译转换后的java代码的虚拟指令。
当我们准备好使用这个类时,jvm Virtual将加载它的。类文件并创建相应的。类对象。我们将把这个类文件加载到jvm虚拟机的内存中。这个过程叫做类装入。
加载:加载是指我们从文件中获取类信息,然后加载到JVM虚拟机的方法/常量区域,也就是内存。
验证:在本模块中,我们将验证加载的结构是否符合Java语言规范和JVM规范的描述。在这个过程中,它是班级再版中最复杂的一块,在时间上的花费也是最长的一块。我们使用的大部分调试程序也在检查这部分的错误。
准备:通过检查后,我们将分配一个结构来存储类的信息。在这个结构中,我们将存储我们在类中定义的成员变量、方法和接口的数据信息。
Resolving: Resolution意味着我们将这个类中常量池中的所有符号引用都改为直接引用。
初始化:一旦解析完成,我们就可以提取类中的变量,并将它们初始化为适当的值。通过执行静态初始化程序,可以将静态变量初始化为指定的值。
这里我们应该把重点放在装载上,剩下的过程应该明白了。
与其他阶段相比,加载阶段,也就是说获取类的二进制字节流的阶段,是我们程序开发周期中最可控的阶段。原因是在加载阶段,我们可以使用我们系统提供的ClassLoader来获取类的二进制字节流。当然,这也可以通过我们的自定义类加载器来获得。
当我们加载完成后,jvm虚拟机外的二进制字节流会按照jvm要求的格式存储在方法区,数据存储格式由jvm自己定义和实现。然后在Java堆中实例化一个类对象,这是我们的程序访问方法区数据的外部接口。
这是java中的类加载器。如果对楼主有帮助,就关注一下。
谢谢大家一直以来的关心~世界很大,感谢你们~
请在评论区留下你的疑问或困惑,我会每天和你分享我的看法和经验。
聚焦最新科技资讯,探索未来智能领域。我 马里奥先生。
版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。