Jan*_*ane 27 java out-of-memory metaspace
在将我们的Java应用程序(在Tomcat上运行的服务)JRE从Java 7切换到Java 8后,我们开始看到java.lang.OutOfMemoryError: Metaspace运行了几天后流量很大.
堆使用没问题.在性能测试期间执行相同的代码流之后,元空间会跳转.
可能导致元空间内存问题的原因是什么?
目前的设置是:
-server -Xms8g -Xmx8g -XX:MaxMetaspaceSize=3200m -XX:+UseParNewGC
-XX:+UseConcMarkSweepGC -XX:MaxGCPauseMillis=1000
-XX:+DisableExplicitGC -XX:+PrintGCDetails
-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=7 -XX:NewSize=5004m
-XX:MaxNewSize=5004m -XX:MaxTenuringThreshold=12
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly -XX:+PrintFlagsFinal
-XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution
-XX:+PrintGCCause -XX:+PrintAdaptiveSizePolicy
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 -XX:GCLogFileSize=200M
Run Code Online (Sandbox Code Playgroud)
该应用程序也大量使用反射.我们还使用自定义类加载器.所有这些都在java 7中运行良好.
dil*_*aik 25
我假设您可以在一段时间内使用相同的请求(请求集)创建问题.定义MaxMetaspaceSize是一件好事,否则应用程序将使用本机内存,直到它用完为止.但我将从以下步骤开始:
Run Code Online (Sandbox Code Playgroud)-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -XX:+UnlockDiagnosticVMOptions
将visualvm(jvisualvm)连接到JVM后,单击monitor,然后查看加载的类数.在那里,您可以监视堆以及元空间.但我会添加其他工具来密切监视元空间.
选择map(sort(map(heap.objects('java.lang.ClassLoader'),'{loader:it,count:it.classes.elementCount}'),'lhs.count <rhs.count'),'toHtml (它)+"
"')
但上面名为"classloader loaded class"的查询将会很慢,这实际上会显示每个类加载器加载的类.
select { loader: cl,
classes: filter(map(cl.classes.elementData, 'it'), 'it != null') }
from instanceof java.lang.ClassLoader cl
Run Code Online (Sandbox Code Playgroud)
JMC
连接到VM然后在连接后单击右侧顶部的JMC中的"诊断命令".由于我们已启用UnlockDiagnosticVMOptions,因此可以执行GC.class_stats.您可能希望使用show all columns运行它并在csv中打印.所以命令看起来像:
GC.class_stats -all=true -csv=true
Run Code Online (Sandbox Code Playgroud)
然后,您可以比较不同时期的类统计信息,并找出导致问题的哪些类(元空间增长)或哪些类在元空间中具有相关信息(方法/方法数据).如何分析当时收集的csv输出:我会把csv加载到数据库或其他地方的两个相似的表(代表csv)中以比较GC.class_stats csv输出,我可以运行一些SQL或任何其他分析工具.这样可以更好地了解元空间中的增长情况.GC类统计信息包含以下列:
指数,超级,InstSize,InstCount,InstBytes,镜子,KlassBytes,K_secondary_supers,VTab,ITAB,OopMap,IK_methods,IK_method_ordering,IK_default_methods,IK_default_vtable_indices,IK_local_interfaces,IK_transitive_interfaces,IK_fields,IK_inner_classes,IK_signers,class_annotations,class_type_annotations,fields_annotations,fields_type_annotations,methods_annotations, methods_parameter_annotations,methods_type_annotations,methods_default_annotations,注释,CP,CpTags,CpCache,CpOperands,CpRefMap,CpAll,MethodCount,MethodBytes,ConstMethod,MethodData,StackMap,字节码,MethodAll,ROAll,RWAll,道达尔,类名,类加载器
希望能帮助到你.此外,如果它不会导致1.7中的任何泄漏,则该错误可能出现在Java 8中.
如果任何人持有对类加载器的任何引用,那么这些类也不会从元空间中卸载.如果您知道您的类加载器应该是GCed并且没有人应该保存对类加载器的引用,您可以返回到visualvm中的堆转储并单击类加载器实例并右键单击以查找"最近的GC根",这将告诉您你持有对类加载器的引用的你.
我们遇到了类似的问题,根本原因是60K类文件被加载到元空间内存中,但没有卸载。在JVM arg下面添加解决了问题。
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
Run Code Online (Sandbox Code Playgroud)
https://issues.apache.org/jira/browse/CXF-2939
希望这可以帮助。
| 归档时间: |
|
| 查看次数: |
54288 次 |
| 最近记录: |