每日分享最新,最流行的软件开发知识与最新行业趋势,希望大家能够一键三连,多多支持,跪求关注,点赞,留言。了解有关JVM以及如何检查Java元空间区域内容的更多信息。 JVM内存有以下区域: YoungGenerationOldGenerationMetaspaceOthersregion 图:JVM内存区域 要查看哪些对象存储在哪个区域,您可以参考此视频剪辑。有时您的应用程序可能会遇到本文中讨论的java。lang。OutOfMemoryError:Metaspace。在这种情况下,您可能希望查看JVM的Metaspace区域中加载了哪些内容。简而言之,JVM内存中的Metaspace区域包含执行应用程序所需的类元数据定义。如果想了解类元数据定义是什么意思,可以参考这个文档。它有很多细节,你可能不必了解它的所有细节。基本上,如果您能够了解加载到内存中的类是什么,那么它将很好地了解JVM内存的Metaspace区域中存在哪些内容。在这篇文章中,让我们探索可用于查看加载到元空间中的类的选项。 以下是查看元空间中加载的类的选项: verbose:class Xlog:classload jcmdGC。classhistogram Programmaticapproach HeapDumpanalysis 让我们在这篇文章中详细讨论每个选项。 1。Verbose:Class 如果您在Java版本8或更低版本上运行,则可以使用此选项。当您在启动期间将verbose:class选项传递给您的应用程序时,它将打印所有加载到内存中的类。加载的类将打印在标准错误流中(即控制台,如果您没有将错误流路由到日志文件)。 java{appname}verbose:class 以下是传递verbose:class参数时开源BuggyApp程序的示例输出: 〔OpenedC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ObjectfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。io。SerializablefromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ComparablefromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。CharSequencefromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。StringfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。reflect。AnnotatedElementfromC:Program FilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。reflect。GenericDeclarationfromC:Program FilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。reflect。TypefromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ClassfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。CloneablefromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ClassLoaderfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。SystemfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ThrowablefromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ErrorfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ThreadDeathfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ExceptionfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。RuntimeExceptionfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。SecurityManagerfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。security。ProtectionDomainfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。security。AccessControlContextfromC:Program FilesJavajre1。8。0171librt。jar〕 〔Loadedjava。security。SecureClassLoaderfromC:Program FilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ReflectiveOperationExceptionfromC:Program FilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ClassNotFoundExceptionfromC:Program FilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。LinkageErrorfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。NoClassDefFoundErrorfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ClassCastExceptionfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。ArrayStoreExceptionfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。VirtualMachineErrorfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。OutOfMemoryErrorfromC:ProgramFilesJavajre1。8。0171librt。jar〕 〔Loadedjava。lang。StackOverflowErrorfromC:ProgramFilesJavajre1。8。0171librt。jar〕 2。Xlog:类加载 如果您在Java版本9或更高版本上运行,则可以使用此选项。当您在启动期间将Xlog:classload选项传递给您的应用程序时,它将打印所有加载到内存中的类。加载的类将打印在您配置的文件路径中。 java{appname}Xlog:classloadinfo:optlogloadedClasses。txt以下是传递Xlog:classload参数时java程序的示例输出: 〔0。004s〕〔info〕〔class,load〕opened:homeec2userjdk9。0。4libmodules 〔0。006s〕〔info〕〔class,load〕java。lang。Objectsource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。io。Serializablesource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。lang。Comparablesource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。lang。CharSequencesource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。lang。Stringsource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。lang。reflect。AnnotatedElementsource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。lang。reflect。GenericDeclarationsource:jrt:java。base 〔0。007s〕〔info〕〔class,load〕java。lang。reflect。Typesource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。Classsource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。Cloneablesource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。ClassLoadersource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。Systemsource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。Throwablesource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。Errorsource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。ThreadDeathsource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。Exceptionsource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。RuntimeExceptionsource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。lang。SecurityManagersource:jrt:java。base 〔0。008s〕〔info〕〔class,load〕java。security。ProtectionDomainsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。security。AccessControlContextsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。security。SecureClassLoadersource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ReflectiveOperationExceptionsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ClassNotFoundExceptionsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。LinkageErrorsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。NoClassDefFoundErrorsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ClassCastExceptionsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ArrayStoreExceptionsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。VirtualMachineErrorsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。OutOfMemoryErrorsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。StackOverflowErrorsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。IllegalMonitorStateExceptionsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ref。Referencesource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ref。SoftReferencesource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ref。WeakReferencesource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ref。FinalReferencesource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ref。PhantomReferencesource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ref。Finalizersource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。Runnablesource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。Threadsource:jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ThreadUncaughtExceptionHandlersource: jrt:java。base 〔0。009s〕〔info〕〔class,load〕java。lang。ThreadGroupsource:jrt:java。base 〔0。010s〕〔info〕〔class,load〕java。util。Mapsource:jrt:java。base 〔0。010s〕〔info〕〔class,load〕java。util。Dictionarysource:jrt:java。base 〔0。010s〕〔info〕〔class,load〕java。util。Hashtablesource:jrt:java。base 〔0。010s〕〔info〕〔class,load〕java。util。Propertiessource:jrt:java。base 〔0。010s〕〔info〕〔class,load〕java。lang。Modulesource:jrt:java。base 〔0。010s〕〔info〕〔class,load〕java。lang。reflect。AccessibleObjectsource:jrt:java。base 3。jcmdgc。classhistogram JDK包含一个名为jcmd的工具。您可以在JVM运行时调用此工具来检查Metaspace区域的内容。当您使用GC。classhistogram参数调用此工具时,它将打印加载到内存中的类列表。您可以在两种模式下调用此工具: A。在控制台上打印加载的类 jcmd{pid}GC。classhistogram 当您调用jcmd如上所示的时,它将在控制台中打印所有加载的类。这里{pid}是您的java应用程序的进程ID。 B。在文件上打印加载的类 jcmd{pid}GC。classhistogramfilename{filepath} 当您jcmd如上所示调用时,它将打印filename参数中指定的文件路径中的所有加载类。这里{pid}是您的java应用程序的进程ID。 这是一篇博客文章,可帮助您快速识别进程ID。 以下是传递参数时开源BuggyApp程序的示例输出:jcmdGC。classhistogram’ jcmd19684GC。classhistogram 19684:hrnuminstancesbytesclassname 1:14303675523008〔Ljavassist。bytecode。ConstInfo; 2:71806070032224〔C 3:157355350353696java。util。HashMapNode 4:43012424732832〔Ljava。lang。Object; 5:100129024030960javassist。bytecode。Utf8Info 6:85826820598432java。util。ArrayList 7:71803717232888java。lang。String 8:14401114987488java。lang。Class 9:14308111447152〔Ljava。util。HashMapNode; 10:1430369154304javassist。bytecode。ClassFile 11:1430359154240javassist。CtNewClass 12:2861246892400〔B 13:1430856868080java。util。HashMap 14:2860786865872javassist。bytecode。ClassInfo 15:1430366865728〔〔Ljavassist。bytecode。ConstInfo; 16:1430495721960javassist。bytecode。MethodInfo 17:1430425721680javassist。bytecode。CodeAttribute 18:1433234586336java。util。HashtableEntry 19:1430384577216java。lang。ref。WeakReference 20:1430364577152javassist。bytecode。ConstPool 21:1430453433080javassist。bytecode。MethodrefInfo 22:1430453433080javassist。bytecode。NameAndTypeInfo 23:1430423433008javassist。bytecode。ExceptionTable 24:1430363432864javassist。bytecode。LongVector 25:1430363432864javassist。bytecode。SourceFileAttribute 26:1436222323336〔I 27:10788688〔Ljava。util。HashtableEntry; 28:64220544java。util。concurrent。ConcurrentHashMapNode 29:24413664java。lang。invoke。MemberName 30:34110912sun。misc。FDBigInteger 31:2128480java。lang。ref。SoftReference 32:1408400〔Ljava。lang。ref。SoftReference; 33:2347488java。lang。invoke。LambdaFormName 34:1767040java。lang。invoke。MethodType 35:2566144java。lang。Long 36:166016java。lang。Thread 37:1735880〔Ljava。lang。Class; 38:3665856java。lang。Object 39:1775664java。lang。invoke。MethodTypeConcurrentWeakInternSetWeakEntry 40:105280〔Ljava。util。concurrent。ConcurrentHashMapNode; 41:2564096java。lang。Byte 42:2564096java。lang。Integer 43:2564096java。lang。Short 44:734088java。lang。invoke。MethodTypeForm 45:823808〔Ljava。lang。invoke。LambdaFormName; 46:773696java。lang。invoke。LambdaForm 4。程序化方法 您还可以使用编程方法打印加载到内存中的类。开源Guava库提供API来打印加载的类。下面是利用Guava库在内存中打印加载的类的代码示例: ClassPathclassPathClassPath。from(BuggyAppLoader。class。getClassLoader()); SetclassesclassPath。getAllClasses(); for(ClassInfoclassInfo:classes){ logger。info(classInfo。getName()); } org。apache。catalina。core。AsyncContextImpl org。apache。catalina。core。AsyncListenerWrapper org。apache。catalina。core。Constants org。apache。catalina。core。ContainerBaseContainerBackgroundProcessor org。apache。catalina。core。ContainerBasePrivilegedAddChild org。apache。catalina。core。ContainerBaseStartChild org。apache。catalina。core。ContainerBaseStartStopThreadFactory org。apache。catalina。core。ContainerBaseStopChild org。apache。catalina。core。ContainerBase org。apache。catalina。core。DefaultInstanceManager1 org。apache。catalina。core。DefaultInstanceManager2 org。apache。catalina。core。DefaultInstanceManager3 org。apache。catalina。core。DefaultInstanceManagerAnnotationCacheEntry org。apache。catalina。core。DefaultInstanceManagerAnnotationCacheEntryType org。apache。catalina。core。DefaultInstanceManager org。apache。catalina。core。JreMemoryLeakPreventionListener org。apache。catalina。core。NamingContextListener org。apache。catalina。core。StandardContext1 org。apache。catalina。core。StandardContextContextFilterMaps org。apache。catalina。core。StandardContextNoPluggabilityServletContext org。apache。catalina。core。StandardContext org。apache。catalina。core。StandardContextValve org。apache。catalina。core。StandardEngineAccessLogListener org。apache。catalina。core。StandardEngineNoopAccessLog org。apache。catalina。core。StandardEngine org。apache。catalina。core。StandardEngineValve org。apache。catalina。core。StandardHost1 org。apache。catalina。core。StandardHostMemoryLeakTrackingListener org。apache。catalina。core。StandardHost org。apache。catalina。core。StandardHostValve org。apache。catalina。core。StandardPipeline org。apache。catalina。core。StandardServer org。apache。catalina。core。StandardService org。apache。catalina。core。StandardThreadExecutor org。apache。catalina。core。StandardWrapper org。apache。catalina。core。StandardWrapperFacade org。apache。catalina。core。StandardWrapperValve org。apache。catalina。core。ThreadLocalLeakPreventionListener 5。堆转储分析 查看加载到内存中的类的另一个选项是检查堆转储。堆转储报告加载到内存中的所有数据、对象和类。您可以使用此处给出的一种方法来捕获堆转储。捕获堆转储后,您可以使用EclipseMAT和HeapHero等堆转储分析工具来分析堆转储。 下面是HeapHero工具生成的报告的摘录,其中显示了加载到内存中的类。 你的记忆里有什么 注意:上面提到的所有方法都不会给您的应用程序增加明显的开销,但是堆转储方法是一种侵入性选项,它将给您的应用程序增加相当大的开销。捕获堆转储后,您的应用程序将暂停,直到捕获完成。