将我们的Java应用程序(在Tomcat上运行的服务)JRE从Java 7切换到Java 8后,我们在运行了几天高流量后开始看{4}}。
堆使用情况还可以。在性能测试期间执行相同的代码流之后,Metaspace会跳转。
可能导致元空间内存问题的原因是什么?
当前设置为:
java.lang.OutOfMemoryError: Metaspace
该应用程序也大量使用反射。我们还使用自定义类加载器。所有这些都在java 7中运行良好。
答案 0 :(得分:22)
我假设您可以在一段时间内使用相同的请求(请求集)创建问题。 定义MaxMetaspaceSize是一件好事,否则应用程序将使用本机内存,直到它用完为止。 但我将从以下步骤开始:
-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(it)+“
”')
但上面那个名为“classloader loaded class”的查询会很慢,实际上会显示每个类加载器加载的类。
select { loader: cl,
classes: filter(map(cl.classes.elementData, 'it'), 'it != null') }
from instanceof java.lang.ClassLoader cl
JMC
连接到VM,然后在连接后单击右侧顶部的JMC中的“诊断命令”。由于我们已启用UnlockDiagnosticVMOptions,因此可以执行GC.class_stats。您可能希望使用show all columns运行它并在csv中打印。所以命令看起来像:
GC.class_stats -all=true -csv=true
然后,您可以比较不同时期的类统计信息,并找出哪些类导致问题(元空间增长)或哪些类在元空间中具有相关信息(方法/方法数据)。如何分析当时收集的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根”,这将告诉您你持有类加载器的引用。
答案 1 :(得分:5)
我们有类似的问题,根本原因是60K类文件被加载到元空间内存中,但没有任何内容被卸载。在JVM arg下面添加修复问题。
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
https://issues.apache.org/jira/browse/CXF-2939
希望这有帮助。
答案 2 :(得分:0)
如果某些自动部署(例如tomcat),也不要将备份保留在tomcat \ webapps中,否则可能会尝试加载备份并与这些资源冲突。