首頁>科技>

每日分享最新,最流行的軟件開發知識與最新行業趨勢,希望大家能夠一鍵三連,多多支持,跪求關注,點贊,留言。

瞭解有關 JVM 以及如何檢查 Java 元空間區域內容的更多信息。

JVM 內存有以下區域:

  1. Young Generation
  2. Old Generation
  3. Metaspace
  4. Others region

圖:JVM 內存區域要查看哪些對象存儲在哪個區域,您可以參考此視頻剪輯。有時您的應用程序可能會遇到本文中討論的 " java.lang.OutOfMemoryError: Metaspace"。在這種情況下,您可能希望查看 JVM 的 Metaspace 區域中加載了哪些內容。簡而言之,JVM 內存中的 Metaspace 區域包含執行應用程序所需的類元數據定義。如果想了解類元數據定義是什麼意思,可以參考這個文檔. 它有很多細節,你可能不必瞭解它的所有細節。基本上,如果您能夠了解加載到內存中的類是什麼,那麼它將很好地瞭解 JVM 內存的 Metaspace 區域中存在哪些內容。在這篇文章中,讓我們探索可用於查看加載到元空間中的類的選項。以下是查看元空間中加載的類的選項:

-verbose:class-Xlog:class+loadjcmd GC.class_histogramProgrammatic approachHeap Dump analysis

1. -Verbose: Class

如果您在 Java 版本 8 或更低版本上運行,則可以使用此選項。當您在啟動期間將“ -verbose:class”選項傳遞給您的應用程序時,它將打印所有加載到內存中的類。加載的類將打印在標準錯誤流中(即控制檯,如果您沒有將錯誤流路由到日誌文件)。java {app_name} -verbose :class以下是傳遞“-verbose:class”參數時開源BuggyApp 程序的示例輸出:

[Opened C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Object from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.io.Serializable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Comparable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.CharSequence from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.String from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.reflect.AnnotatedElement from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.reflect.GenericDeclaration from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.reflect.Type from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Class from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Cloneable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.ClassLoader from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.System from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Throwable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Error from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.ThreadDeath from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.Exception from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.RuntimeException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.SecurityManager from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.security.ProtectionDomain from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.security.AccessControlContext from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.security.SecureClassLoader from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.ReflectiveOperationException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.ClassNotFoundException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.LinkageError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.NoClassDefFoundError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.ClassCastException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.ArrayStoreException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.VirtualMachineError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.OutOfMemoryError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar] [Loaded java.lang.StackOverflowError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]

2.-Xlog:類+加載如果您在 Java 版本 9 或更高版本上運行,則可以使用此選項。當您在啟動期間將“-Xlog:class+load”選項傳遞給您的應用程序時,它將打印所有加載到內存中的類。加載的類將打印在您配置的文件路徑中。java {app_name} -Xlog:class+load=info:/opt/log/loadedClasses.txt以下是傳遞“-Xlog:class+load”參數時 java 程序的示例輸出:

[0.004s][info][class,load] opened: /home/ec2-user/jdk-9.0.4/lib/modules [0.006s][info][class,load] java.lang.Object source: jrt:/java.base [0.007s][info][class,load] java.io.Serializable source: jrt:/java.base [0.007s][info][class,load] java.lang.Comparable source: jrt:/java.base [0.007s][info][class,load] java.lang.CharSequence source: jrt:/java.base [0.007s][info][class,load] java.lang.String source: jrt:/java.base [0.007s][info][class,load] java.lang.reflect.AnnotatedElement source: jrt:/java.base [0.007s][info][class,load] java.lang.reflect.GenericDeclaration source: jrt:/java.base [0.007s][info][class,load] java.lang.reflect.Type source: jrt:/java.base [0.008s][info][class,load] java.lang.Class source: jrt:/java.base [0.008s][info][class,load] java.lang.Cloneable source: jrt:/java.base [0.008s][info][class,load] java.lang.ClassLoader source: jrt:/java.base [0.008s][info][class,load] java.lang.System source: jrt:/java.base [0.008s][info][class,load] java.lang.Throwable source: jrt:/java.base [0.008s][info][class,load] java.lang.Error source: jrt:/java.base [0.008s][info][class,load] java.lang.ThreadDeath source: jrt:/java.base [0.008s][info][class,load] java.lang.Exception source: jrt:/java.base [0.008s][info][class,load] java.lang.RuntimeException source: jrt:/java.base [0.008s][info][class,load] java.lang.SecurityManager source: jrt:/java.base [0.008s][info][class,load] java.security.ProtectionDomain source: jrt:/java.base [0.009s][info][class,load] java.security.AccessControlContext source: jrt:/java.base [0.009s][info][class,load] java.security.SecureClassLoader source: jrt:/java.base [0.009s][info][class,load] java.lang.ReflectiveOperationException source: jrt:/java.base [0.009s][info][class,load] java.lang.ClassNotFoundException source: jrt:/java.base [0.009s][info][class,load] java.lang.LinkageError source: jrt:/java.base [0.009s][info][class,load] java.lang.NoClassDefFoundError source: jrt:/java.base [0.009s][info][class,load] java.lang.ClassCastException source: jrt:/java.base [0.009s][info][class,load] java.lang.ArrayStoreException source: jrt:/java.base [0.009s][info][class,load] java.lang.VirtualMachineError source: jrt:/java.base [0.009s][info][class,load] java.lang.OutOfMemoryError source: jrt:/java.base [0.009s][info][class,load] java.lang.StackOverflowError source: jrt:/java.base [0.009s][info][class,load] java.lang.IllegalMonitorStateException source: jrt:/java.base [0.009s][info][class,load] java.lang.ref.Reference source: jrt:/java.base [0.009s][info][class,load] java.lang.ref.SoftReference source: jrt:/java.base [0.009s][info][class,load] java.lang.ref.WeakReference source: jrt:/java.base [0.009s][info][class,load] java.lang.ref.FinalReference source: jrt:/java.base [0.009s][info][class,load] java.lang.ref.PhantomReference source: jrt:/java.base [0.009s][info][class,load] java.lang.ref.Finalizer source: jrt:/java.base [0.009s][info][class,load] java.lang.Runnable source: jrt:/java.base [0.009s][info][class,load] java.lang.Thread source: jrt:/java.base [0.009s][info][class,load] java.lang.Thread$UncaughtExceptionHandler source: jrt:/java.base [0.009s][info][class,load] java.lang.ThreadGroup source: jrt:/java.base [0.010s][info][class,load] java.util.Map source: jrt:/java.base [0.010s][info][class,load] java.util.Dictionary source: jrt:/java.base [0.010s][info][class,load] java.util.Hashtable source: jrt:/java.base [0.010s][info][class,load] java.util.Properties source: jrt:/java.base [0.010s][info][class,load] java.lang.Module source: jrt:/java.base [0.010s][info][class,load] java.lang.reflect.AccessibleObject source: jrt:/java.base

3. jcmd gc.class_histogramJDK 包含一個名為“ jcmd”的工具。您可以在 JVM 運行時調用此工具來檢查 Metaspace 區域的內容。當您使用" GC.class_histogram"參數調用此工具時,它將打印加載到內存中的類列表。您可以在兩種模式下調用此工具:A. 在控制檯上打印加載的類jcmd {pid} GC.class_histogram當您調用jcmd如上所示的“”時,它將在控制檯中打印所有加載的類。這裡 {pid} 是您的 java 應用程序的進程 ID。 B. 在文件上打印加載的類jcmd {pid} GC.class_histogram filename={file-path}當您jcmd如上所示調用""時,它將打印"filename"參數中指定的文件路徑中的所有加載類。這裡 {pid} 是您的 java 應用程序的進程 ID。這是一篇博客文章,可幫助您快速識別進程 ID。以下是傳遞"參數時開源BuggyApp程序的示例輸出:jcmd GC.class_histogram’

jcmd 19684 GC.class_histogram 19684: num #instances #bytes class name ---------------------------------------------- 1: 143036 75523008 [Ljavassist.bytecode.ConstInfo; 2: 718060 70032224 [C 3:1573553 50353696 java.util.HashMap$Node 4: 430124 24732832 [Ljava.lang.Object; 5:1001290 24030960 javassist.bytecode.Utf8Info 6: 858268 20598432 java.util.ArrayList 7: 718037 17232888 java.lang.String 8: 144011 14987488 java.lang.Class 9: 143081 11447152 [Ljava.util.HashMap$Node; 10: 143036 9154304 javassist.bytecode.ClassFile 11: 143035 9154240 javassist.CtNewClass 12: 286124 6892400 [B 13: 143085 6868080 java.util.HashMap 14: 286078 6865872 javassist.bytecode.ClassInfo 15: 143036 6865728 [[Ljavassist.bytecode.ConstInfo; 16: 143049 5721960 javassist.bytecode.MethodInfo 17: 143042 5721680 javassist.bytecode.CodeAttribute 18: 143323 4586336 java.util.Hashtable$Entry 19: 143038 4577216 java.lang.ref.WeakReference 20: 143036 4577152 javassist.bytecode.ConstPool 21: 143045 3433080 javassist.bytecode.MethodrefInfo 22: 143045 3433080 javassist.bytecode.NameAndTypeInfo 23: 143042 3433008 javassist.bytecode.ExceptionTable 24: 143036 3432864 javassist.bytecode.LongVector 25: 143036 3432864 javassist.bytecode.SourceFileAttribute 26: 143622 2323336 [I 27: 10 788688 [Ljava.util.Hashtable$Entry; 28:642 20544 java.util.concurrent.ConcurrentHashMap$Node 29:244 13664 java.lang.invoke.MemberName 30:341 10912 sun.misc.FDBigInteger 31:2128480 java.lang.ref.SoftReference 32:1408400 [Ljava.lang.ref.SoftReference; 33:2347488 java.lang.invoke.LambdaForm$Name 34:1767040 java.lang.invoke.MethodType 35:2566144 java.lang.Long 36: 166016 java.lang.Thread 37:1735880 [Ljava.lang.Class; 38:3665856 java.lang.Object 39:1775664 java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry 40: 105280 [Ljava.util.concurrent.ConcurrentHashMap$Node; 41:2564096 java.lang.Byte 42:2564096 java.lang.Integer 43:2564096 java.lang.Short 44: 734088 java.lang.invoke.MethodTypeForm 45: 823808 [Ljava.lang.invoke.LambdaForm$Name; 46: 773696 java.lang.invoke.LambdaForm

4. 程序化方法您還可以使用編程方法打印加載到內存中的類。開源 Guava 庫提供 API 來打印加載的類。下面是利用 Guava 庫在內存中打印加載的類的代碼示例:

ClassPath classPath = ClassPath.from(BuggyAppLoader.class.getClassLoader()); Set<ClassInfo> classes = classPath.getAllClasses(); for(ClassInfo classInfo : classes) { logger.info(classInfo.getName()); }

org.apache.catalina.core.AsyncContextImpl org.apache.catalina.core.AsyncListenerWrapper org.apache.catalina.core.Constants org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor org.apache.catalina.core.ContainerBase$PrivilegedAddChild org.apache.catalina.core.ContainerBase$StartChild org.apache.catalina.core.ContainerBase$StartStopThreadFactory org.apache.catalina.core.ContainerBase$StopChild org.apache.catalina.core.ContainerBase org.apache.catalina.core.DefaultInstanceManager$1 org.apache.catalina.core.DefaultInstanceManager$2 org.apache.catalina.core.DefaultInstanceManager$3 org.apache.catalina.core.DefaultInstanceManager$AnnotationCacheEntry org.apache.catalina.core.DefaultInstanceManager$AnnotationCacheEntryType org.apache.catalina.core.DefaultInstanceManager org.apache.catalina.core.JreMemoryLeakPreventionListener org.apache.catalina.core.NamingContextListener org.apache.catalina.core.StandardContext$1 org.apache.catalina.core.StandardContext$ContextFilterMaps org.apache.catalina.core.StandardContext$NoPluggabilityServletContext org.apache.catalina.core.StandardContext org.apache.catalina.core.StandardContextValve org.apache.catalina.core.StandardEngine$AccessLogListener org.apache.catalina.core.StandardEngine$NoopAccessLog org.apache.catalina.core.StandardEngine org.apache.catalina.core.StandardEngineValve org.apache.catalina.core.StandardHost$1 org.apache.catalina.core.StandardHost$MemoryLeakTrackingListener 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.堆轉儲分析查看加載到內存中的類的另一個選項是檢查堆轉儲。堆轉儲報告加載到內存中的所有數據、對象和類。您可以使用此處給出的一種方法來捕獲堆轉儲。捕獲堆轉儲後,您可以使用Eclipse MAT和HeapHero等堆轉儲分析工具來分析堆轉儲。下面是 HeapHero 工具生成的報告的摘錄,其中顯示了加載到內存中的類。你的記憶裡有什麼注意:上面提到的所有方法都不會給您的應用程序增加明顯的開銷,但是堆轉儲方法是一種侵入性選項,它將給您的應用程序增加相當大的開銷。捕獲堆轉儲後,您的應用程序將暫停,直到捕獲完成。

10
最新評論
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 比馬桶還髒!化妝工具不清洗,小心護膚不成變毀容