1. Overview
1.概述
In this tutorial, we’ll learn different techniques to list all classes loaded in the JVM. For example, we can load the JVM’s heap dump or connect the running applications to various tools and list all the classes loaded in that tool. Also, there are various libraries to accomplish this programmatically.
在本教程中,我们将学习不同的技术来列出JVM中加载的所有类。例如,我们可以加载JVM的堆转储,或者将正在运行的应用程序连接到各种工具,然后列出该工具中加载的所有类。此外,还有各种库来以编程方式完成这个任务。
We’ll explore both the non-programmatic well as programmatic approaches.
我们将探讨非计划性以及计划性的方法。
2. Non-Programmatic Approach
2.非计划性的方法
2.1. Using VM Argument
2.1.使用虚拟机参数
The most straightforward approach for listing all classes loaded would be to log that in a console output or file.
列出所有加载的类的最直接的方法是将其记录在控制台输出或文件中。
We’ll run the Java Application with the below JVM Argument:
我们将用下面的JVM参数来运行Java应用程序。
java <app_name> --verbose:class
[Opened /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Object from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.io.Serializable from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.String from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.reflect.Type from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Class from /Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/jre/lib/rt.jar]
...............................
For Java 9, we’ll use the -Xlog JVM Argument to log the classes loaded onto file:
对于Java 9,我们将使用-Xlog JVM Argument来记录加载到文件中的类。
java <app_name> -Xlog:class+load=info:classloaded.txt
2.2. Using Heap Dump
2.2.使用堆转储
We’ll see how different tools use the JVM heap dump to extract class-loaded information. But, first, we’ll generate the heap dump using the command below:
我们将看到不同的工具如何使用JVM heap dump来提取类加载的信息。但是,首先,我们将使用下面的命令生成堆转储。
jmap -dump:format=b,file=/opt/tmp/heapdump.bin <app_pid>
The above heap dump can be opened in various tools to get different metrics.
上述堆转储可以在各种工具中打开以获得不同的指标。
In Eclipse, we’ll load the heap dump file heapdump.bin in the Eclipse Memory Analyzer and use the Histogram Interface:
在Eclipse中,我们将在Eclipse内存分析器中加载堆转储文件heapdump.bin并使用直方图接口。
We’ll now open the heap dump file heapdump.bin in the Java VisualVM interface and use the classes by instances or size option:
现在我们将在Java VisualVM接口中打开堆转储文件heapdump.bin,并使用按实例或大小选项的类。
2.3. JProfiler
2.3 JProfiler
JProfiler is one of the top Java Application Profilers with a rich set of features to view different metrics.
JProfiler是顶级的Java应用分析器之一,具有丰富的功能,可以查看不同的指标。
In JProfiler, we can attach to running JVM or load the heap dump file and get all the JVM-related metrics, including names of all classes loaded.
在JProfiler中,我们可以附加到正在运行的JVM或加载堆转储文件并获得所有与JVM相关的指标,包括所有加载的类的名称。
We’ll use the attach process feature to let JProfiler connect to the running application ListLoadedClass:
我们将使用附加进程功能,让JProfiler连接到正在运行的应用程序ListLoadedClass。
Then, we’ll take the snapshot of the application and use that to get all classes loaded:
然后,我们将采取应用程序的快照,并使用它来获得所有的类的加载。
Below, we can see the names of the loaded classes instance counts using Heap Walker functionality:
下面,我们可以看到使用Heap Walker功能加载的类实例计数的名称。
3. Programmatic Approach
3.计划性方法
3.1. Instrumentation API
3.1.仪器仪表API
Java provides Instrumentation API, which helps in getting valuable metrics on the application. First, we’ll have to create and load a Java Agent to acquire an instance of the Instrumentation interface into the application. A Java agent is a tool to instrument programs running on the JVM.
Java提供了Instrumentation API,这有助于获得应用程序的宝贵指标。首先,我们要创建并加载一个Java Agent,以获取Instrumentation接口的实例到应用程序中。Java代理是一种工具,用于检测在JVM上运行的程序。
Then, we’ll need to invoke the Instrumentation method getInitiatedClasses(Classloader loader) to get all the classes loaded by a particular class loader type.
然后,我们需要调用Instrumentation method getInitiatedClasses(Classloader loader) 以获得所有由特定类装载器类型装载的类。
3.2. Google Guava
3.2. Google Guava
We’ll see how the Guava Library can get a list of all classes loaded into JVM using a current class loader.
我们将看到Guava库如何使用当前的类加载器获得加载到JVM的所有类的列表。
Let’s start by adding the Guava dependency to our Maven project:
让我们先把Guava依赖性添加到我们的Maven项目。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
We’ll initialize the ClassPath object with the current class loader instance:
我们将用当前的类加载器实例初始化ClassPath对象。
ClassPath classPath = ClassPath.from(ListLoadedClass.class.getClassLoader());
Set<ClassInfo> classes = classPath.getAllClasses();
Assertions.assertTrue(4 < classes.size());
3.3. Reflections API
3.3.反思API
We’ll use the Reflections library that scans the current classpath and allows us to query it at runtime.
我们将使用Reflections库,它可以扫描当前的classpath并允许我们在运行时查询。
Let’s start by adding the reflections dependency to our Maven project:
让我们先把reflections依赖项添加到我们的Maven项目中。
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
Now, we’ll look into the sample code, which returns a set of classes under a package:
现在,我们来看看示例代码,它返回一个包下的一组类。
Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
Set<Class> classes = reflections.getSubTypesOf(Object.class)
.stream()
.collect(Collectors.toSet());
Assertions.assertEquals(4, classes.size());
4. Conclusion
4.总结
In this article, we’ve learned various ways of listing all the classes loaded in the JVM. First, we’ve seen how using a VM Argument can log the list of loaded classes.
在这篇文章中,我们已经学习了列出JVM中所有加载的类的各种方法。首先,我们看到了使用VM Argument可以记录加载的类的列表。
Then, we’ve explored how various tools can load the heap dump or connect to the JVM to show various metrics, including classes loaded. Lastly, we’ve covered some of the Java libraries.
然后,我们探讨了各种工具如何加载堆转储或连接到JVM来显示各种指标,包括加载的类。最后,我们介绍了一些Java库的情况。
As always, all the code is available over on GitHub.
像往常一样,所有的代码都可以在GitHub上找到。