一篇文章总结JVM

本文详细总结了JVM的工作原理,涵盖了类加载的全过程,包括加载、验证、准备、解析、初始化和卸载。探讨了类加载器的分类,如启动类加载器、拓展类加载器和应用程序类加载器,并解析了双亲委派机制及其优点。同时,介绍了JVM内存模型,包括栈、本地方法栈、堆和元空间等。此外,还列举了若干用于监控和诊断JVM的命令,如jps、jmap、jstack、jinfo和jstat。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一文总结JVM

java类加载过程

类从被加载到JVM到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段
在这里插入图片描述

类加载器分类

  • 启动类加载器/Bootstrap ClassLoader
    在HotSpot虚拟机中,Bootstrap ClassLoader用C++语言编写并嵌入JVM内部,主要负载加载JAVA_HOME/lib目录中的所有类,或者加载由选项-Xbootcalsspath指定的路径下的类;

  • 拓展类加载器/ExtClassLoader
    负载加载JAVA_HOME/lib/ext目录中的所有类型,或者由参数-Xbootclasspath指定路径中的所有类型;

  • 应用程序类加载器/AppClassLoader
    负责加载用户类路径ClassPath下的所有类型,一般情况下为程序的默认类加载器;
    ExtClassLoader和AppClassLoader的父类都是ClassLoader

  • 自定义加载器
    Java虚拟机规范将所有继承抽象类java.lang.ClassLoader的类加载器,定义为自定义类加载器;

双亲委派

  • 双亲委派模型
    在这里插入图片描述

  • 双亲委派过程
    当一个类加载器收到类加载任务时,立即将任务委派给它的父类(并不是java含义中的父类)加载器去执行,直至委派给最顶层的启动类加载器为止。如果父类加载器无法加载委派给它的类时,将类加载任务退回给它的下一级加载器去执行;
    除了启动类加载器以外,每个类加载器拥有一个父类加载器,用户的自定义类加载器的父类加载器是AppClassLoader;

  • 双亲委派优点

  1. 避免类的重复加载
    双亲委派模型可以保证全限名指定的类,只被加载一次;
  2. 沙箱安全机制
    自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改
    双亲委派模型不具有强制性约束,是Java设计者推荐的类加载器实现方式;

打破双亲委派机制

JVM内存模型

  • jvm的主要组成部分
    jvm主要由类装载子系统、执行引擎,运行时数据区组成

在这里插入图片描述


  • 可以理解为由很多个线程栈所组成的内存区域,JVM会给每个单独的线程开辟一个独立的栈空间
  • 栈帧
    栈帧用于存储局部变量、操作数栈,动态链接,方法出口,一个方法对应特定的栈帧内存区域,这也是为什么递归调用场景,如果没有出口将会导致栈内存溢出
  • 本地方法栈
    带有native关键字的方法的方法栈

  • 堆分为年轻代(edem区,S0,S1),老年代
  • 垃圾回收
    minor GC,full GC
  • 元空间
    存放类信息

常用命令

jps

查看进程
在这里插入图片描述

jmap

jmap -histo

  • jmap -histo 25124
    查看25124进程对应的内存信息,实例个数和所占用的内存
    
     num     #instances         #bytes  class name
    ----------------------------------------------
       1:        232314       52764168  [B
       2:        360321       47344648  [C
       3:         25177       31904624  [I
       4:        165861        3980664  java.lang.String
       5:         38558        3393104  java.lang.reflect.Method
       6:         50254        3046304  [Ljava.lang.Object;
       7:        105103        2238208  [Ljava.lang.Class;
       8:         18531        1476256  [S
       9:         16513        1343104  [Ljava.util.HashMap$Node;
      10:         27392        1314816  java.util.HashMap
      11:         34464        1102848  java.util.HashMap$Node
      12:          9614        1075616  java.lang.Class
      13:         29226         935232  java.util.concurrent.ConcurrentHashMap$Node
      14:         38277         918648  java.lang.StringBuilder
      15:         18214         728560  java.util.LinkedHashMap$Entry
      16:         18896         604672  java.lang.ref.WeakReference
      17:          9621         538776  java.util.LinkedHashMap
      18:         10492         450368  [Ljava.lang.reflect.Method;
      19:          6193         445896  java.lang.reflect.Field
      20:           231         379696  [Ljava.util.concurrent.ConcurrentHashMap$Node;
      21:         22519         360304  java.util.HashSet
      22:         14480         347520  java.util.ArrayList
      23:         10298         329536  java.util.ArrayList$Itr
      24:          9050         309152  [Ljava.lang.String;
      25:          6996         279840  java.lang.ref.SoftReference
      26:         11947         276592  [Ljava.lang.reflect.Type;
    

jmap -heap

  • jmap -heap 25124
    查看堆信息

    Attaching to process ID 25124, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.152-b16
    
    using thread-local object allocation.
    Parallel GC with 4 thread(s)
    
    Heap Configuration:
       MinHeapFreeRatio         = 0
       MaxHeapFreeRatio         = 100
       MaxHeapSize              = 2116026368 (2018.0MB)
       NewSize                  = 44564480 (42.5MB)
       MaxNewSize               = 705167360 (672.5MB)
       OldSize                  = 89653248 (85.5MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 21807104 (20.796875MB)
       CompressedClassSpaceSize = 1073741824 (1024.0MB)
       MaxMetaspaceSize         = 17592186044415 MB
       G1HeapRegionSize         = 0 (0.0MB)
    
    Heap Usage:
    PS Young Generation
    Eden Space:
       capacity = 246939648 (235.5MB)
       used     = 136945832 (130.60172271728516MB)
       free     = 109993816 (104.89827728271484MB)
       55.45720709863489% used
    From Space:
       capacity = 10485760 (10.0MB)
       used     = 10297888 (9.820831298828125MB)
       free     = 187872 (0.179168701171875MB)
       98.20831298828125% used
    To Space:
       capacity = 16252928 (15.5MB)
       used     = 0 (0.0MB)
       free     = 16252928 (15.5MB)
       0.0% used
    PS Old Generation
       capacity = 94371840 (90.0MB)
       used     = 23666896 (22.570510864257812MB)
       free     = 70704944 (67.42948913574219MB)
       25.078345404730904% used
    
    24858 interned Strings occupying 3011960 bytes.
    
    

jmap -dump:format=b,file=example.hprof 25124

  • dump堆内存
    jmap -dump:format=b,file=example.hprof 25124

    -XX:+HeapDumpOnOutOfMemoryError //设置内存溢出自动导出dump文件
    -XX:HeapDumpPath=d:example.hprof //设置路径
    在这里插入图片描述

  • dump文件的查看
    cmd->jvisualvm->文件->装入->选择文件
    在这里插入图片描述

  • 效果
    在这里插入图片描述

jstack

  • jstack
    打印进程中正在运行的线程的信息
    分析死锁
    jstack 6736 >deadlock.txt
2021-04-28 13:31:29
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.152-b16 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000002f87000 nid=0x6b20 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #12 prio=5 os_prio=0 tid=0x00000000197af800 nid=0x7300 waiting for monitor entry [0x000000001a50f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.ljb.springboot.DeadLockThread.run(DeadLock.java:48)
	- waiting to lock <0x00000000d6343f08> (a java.lang.Object)
	- locked <0x00000000d6343f18> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)

"Thread-0" #11 prio=5 os_prio=0 tid=0x00000000197bb000 nid=0x72e0 waiting for monitor entry [0x000000001a40e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.ljb.springboot.DeadLockThread.run(DeadLock.java:35)
	- waiting to lock <0x00000000d6343f18> (a java.lang.Object)
	- locked <0x00000000d6343f08> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000019751000 nid=0x3e60 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x00000000196b9800 nid=0x62d0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x00000000192c3000 nid=0x3f20 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x00000000195cf000 nid=0x72b4 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000019640000 nid=0xaa4 runnable [0x0000000019e0e000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	- locked <0x00000000d63abc60> (a java.io.InputStreamReader)
	at java.io.InputStreamReader.read(InputStreamReader.java:184)
	at java.io.BufferedReader.fill(BufferedReader.java:161)
	at java.io.BufferedReader.readLine(BufferedReader.java:324)
	- locked <0x00000000d63abc60> (a java.io.InputStreamReader)
	at java.io.BufferedReader.readLine(BufferedReader.java:389)
	at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:47)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000018f52800 nid=0x6d58 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000017bb7000 nid=0x610c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000017b90000 nid=0x3374 in Object.wait() [0x0000000018f0e000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000d5f88ec8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
	- locked <0x00000000d5f88ec8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000017b68800 nid=0x6be8 in Object.wait() [0x0000000018e0f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000d5f86b68> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	- locked <0x00000000d5f86b68> (a java.lang.ref.Reference$Lock)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x0000000017b67800 nid=0x5384 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002f9d000 nid=0x6d1c runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002f9e800 nid=0x3b4c runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002fa0000 nid=0x4f08 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002fa1800 nid=0x68f4 runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x00000000197a7800 nid=0x5408 waiting on condition 

JNI global references: 13


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000017b6e168 (object 0x00000000d6343f08, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x0000000017b6f608 (object 0x00000000d6343f18, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at com.ljb.springboot.DeadLockThread.run(DeadLock.java:48)
	- waiting to lock <0x00000000d6343f08> (a java.lang.Object)
	- locked <0x00000000d6343f18> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)
"Thread-0":
	at com.ljb.springboot.DeadLockThread.run(DeadLock.java:35)
	- waiting to lock <0x00000000d6343f18> (a java.lang.Object)
	- locked <0x00000000d6343f08> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

cpu使用率飙升原因分析

top->top -p ->shift+h->jstack

jinfo

jinfo
jinfo -flags

jstat

jstat -gc 29560

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
512.0  512.0   0.0    0.0   24064.0  16363.7   87552.0     1166.5   4864.0 3356.5 512.0  350.2     528    0.297   0      0.000    0.297
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值