Java如何查看java应用加载了哪些类
Java:如何查看java应用加载了哪些类?
先直接给出结论:
#1
jcmd
GC.class_histogram
或 #2
jmap -histo
或 #3
jmap -histo:live
执行结果如下所示:
num #instances #bytes class name (module)
1: 476831 43623368 [B (java.base@16.0.1)
2: 176012 21862544 [C (java.base@16.0.1)
3: 571102 18275264 java.util.HashMap$Node ( )
4: 666997 16007928 java.lang.String ( )
5: 151332 11937928 [I (java.base@16.0.1)
6: 117792 9024648 [Ljava.util.HashMap$Node; (java.base@16.0.1)
7: 140910 8463264 [Ljava.lang.Object; (java.base@16.0.1)
8: 68296 6286424 [J (java.base@16.0.1)
9: 92323 4431504 java.util.HashMap ( )
10: 87662 3506480 java.util.LinkedHashMap$Entry ( )
11: 25716 3158832 java.lang.Class ( )
12: 58626 2739904 [Ljava.lang.String; (java.base@16.0.1)
13: 104695 2512680 java.util.ArrayList ( )
14: 25001 2400096 org.apache.maven.model.Dependency
15: 66238 2119616 java.util.Collections$UnmodifiableMap ( )
16: 35971 2014376 java.util.LinkedHashMap ( )
17: 27768 1999296 org.eclipse.emf.ecore.util.EContentsEList$FeatureIteratorImpl
18: 53012 1696384 org.apache.maven.model.InputLocation
19: 16823 1586224 [[C (java.base@16.0.1)
20: 34742 1389680 org.eclipse.aether.artifact.DefaultArtifact
21: 42643 1364576 java.util.concurrent.ConcurrentHashMap$Node ( )
22: 48042 1153008 org.eclipse.emf.ecore.util.EcoreUtil$ProperContentIterator
23: 34663 1109216 org.eclipse.aether.graph.Dependency
24: 33835 1082720 jdk.internal.jimage.ImageReader$Resource
25: 43937 1054488 java.lang.StringBuilder ( )
26: 25816 1032640 java.util.WeakHashMap$Entry ( )
27: 29809 953888 jdk.internal.jimage.ImageReader$Resource
28: 39024 936576 org.eclipse.emf.ecore.impl.BasicEObjectImpl$3
29: 10551 928488 java.lang.reflect.Method ( )
30: 33835 812040 jdk.internal.jimage.ImageLocation
31: 29809 715416 jdk.internal.jimage.ImageLocation
32: 1597 675072 [Ljava.util.concurrent.ConcurrentHashMap$Node; (java.base@16.0.1)
33: 16695 667800 org.eclipse.emf.ecore.util.EcoreEMap$DelegateEObjectContainmentEList
34: 27768 666432 org.eclipse.emf.ecore.util.EContentsEList
35: 19935 637920 org.eclipse.emf.common.util.AbstractEList$EIterator
36: 15468 618720 org.eclipse.emf.common.util.AbstractEList$NonResolvingEListIterator
37: 15359 614360 org.eclipse.emf.ecore.util.EcoreEMap
38: 17879 572128 java.util.Hashtable$Entry ( )
39: 16014 512448 org.eclipse.emf.common.util.URI$LazyFragmentInitializer
40: 15363 491616 org.eclipse.emf.common.util.BasicEMap$View
41: 11795 471800 org.codehaus.plexus.util.xml.Xpp3Dom
42: 11673 466920 org.eclipse.equinox.internal.p2.metadata.RequiredCapability
43: 13 426192 [Ljava.util.concurrent.ForkJoinTask; (java.base@16.0.1)
44: 1160 417440 [[Ljava.lang.Object; (java.base@16.0.1)
45: 17894 405280 [Ljava.lang.Class; (java.base@16.0.1)
46: 24815 397040 org.eclipse.jdt.internal.ui.text.spelling.engine.AbstractSpellDictionary$ByteArrayWrapper
47: 16022 384528 org.eclipse.emf.common.util.URI$Fragment
48: 16014 384336 org.eclipse.emf.ecore.impl.MinimalEObjectImpl$1ArrayDelegatingAdapterList
49: 11738 375616 org.eclipse.osgi.container.ModuleCapability
50: 4177 375112 [S (java.base@16.0.1)
它会根据占用内存的大小进行排序。
其中#2和#3的区别是,#3会先做一次FullGC,然后把存活下来的对象打印出来
如果还需要知道是否加载了某些类,可以再加上grep,比如想知道是否用到了log4j
jmap -histo
| grep log4j
其实jcmd和jmap还有很多参数,可以用来获取java应用的信息,这些参数基本可以做到望文生义:
C:\Java\jdk1.8.0_261\bin>jcmd help
Error parsing arguments: No command specified
Usage: jcmd <pid | main class> <command …|PerfCounter.print|-f file>
or: jcmd -l
or: jcmd -h
command must be a valid jcmd command for the selected jvm.
Use the command “help” to see which commands are available.
If the pid is 0, commands will be sent to all Java processes.
The main class argument will be used to match (either partially
or fully) the class used to start Java.
If no options are given, lists Java processes (same as -p).
PerfCounter.print display the counters exposed by this process
-f read and execute commands from the file
-l list JVM processes on the local machine
-h this help
7140是一个java应用的进程编号
C:\Java\jdk1.8.0_261\bin>jcmd 7140 help
7140:
The following commands are available:
Compiler.CodeHeap_Analytics
Compiler.codecache
Compiler.codelist
Compiler.directives_add
Compiler.directives_clear
Compiler.directives_print
Compiler.directives_remove
Compiler.queue
GC.class_histogram
GC.finalizer_info
GC.heap_dump
GC.heap_info
GC.run
GC.run_finalization
JFR.check
JFR.configure
JFR.dump
JFR.start
JFR.stop
JVMTI.agent_load
JVMTI.data_dump
ManagementAgent.start
ManagementAgent.start_local
ManagementAgent.status
ManagementAgent.stop
Thread.print
VM.class_hierarchy
VM.classloader_stats
VM.classloaders
VM.command_line
VM.dynlibs
VM.events
VM.flags
VM.info
VM.log
VM.metaspace
VM.native_memory
VM.print_touched_methods
VM.set_flag
VM.stringtable
VM.symboltable
VM.system_properties
VM.systemdictionary
VM.uptime
VM.version
help
For more information about a specific command use ‘help
’.
C:\Java\jdk1.8.0_261\bin>jmap -h
Usage:
jmap [option]
(to connect to running process)
jmap [option] <executable
(to connect to a core file)
jmap [option] [server_id@]
(to connect to remote debug server)
where
to print same info as Solaris pmap -heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the “live”
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:
to dump java heap in hprof binary format dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=
dump heap to Example: jmap -dump:live,format=b,file=heap.bin
-F force. Use with -dump:
or -histo to force a heap dump or histogram when
does not respond. The “live” suboption is not supported
in this mode.
-h | -help to print this help message
-J
to pass directly to the runtime system
虽然知道了JVM中加载的哪些类,怎么知道这些类属于什么jar呢?
java <app_name> -verbose:class
从JDK9开始,可以使用如下参数:
java <app_name> -Xlog:class+load=info:classloaded.txt
这些参数都需要在进程启动中添加。
参考文档
Java Platform, Standard Edition Troubleshooting Guide
The jmap Utility
The jcmd Utility