借助JHSDB 工具从底层深入理解运行时数据区

1.堆空间分代划分

堆被划分为新生代和老年代(Tenured),新生代又被进一步划分为 Eden 和 Survivor 区,最后 Survivor 由 From Survivor 和 To Survivor 组成。
image.png

2.GC 概念

GC- Garbage Collection 垃圾回收,在 JVM 中是自动化的垃圾回收机制,我们一般不用去关注,在 JVM 中 GC 的重要区域是堆空间。 我们也可以通过一些额外方式主动发起它,比如 System.gc(),主动发起。(项目中不需要主动调用,只是在这里分析使用)

3.JHSDB 工具

JHSDB 是一款基于服务性代理实现的进程外调试工具。服务性代理是 HotSpot 虚拟机中一组用于映射 Java 虚拟机运行信息的,主要基于 Java 语言实现的 API 集合。
JDK1.8 的开启方式
开启 HSDB 工具: Jdk1.8 启动 JHSDB 的时候必须将 sawindbg.dll(一般会在 JDK 的目录下)复制到对应目录的 jre 下(注意在 win 上安装了 JDK1.8 后往往同级目录下有一个 jre 的目录)
image.png
复制后
image.png
然后到目录:C:\Program Files\Java\jdk1.8.0_101\lib 进入命令行,执行 java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB

C:\Program Files\Java\jdk1.8.0_191\lib>java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB

对话窗出来了
image.png

JDK1.9 及以后的开启方式
进入 JDK 的 bin 目录下,我们可以在命令行中使用 jhsdb hsdb 来启动它

4.代码改造

VM 参数加入
-XX:+UseConcMarkSweepGC
image.png
-XX:-UseCompressedOops
image.png
加入以上参数,指定垃圾回收器
-Xms30m -Xmx30m -Xss1m -XX:MaxMetaspaceSize=30m -XX:+UseConcMarkSweepGC -XX:-UseCompressedOops

/**
 * @author 公众号:IT三明治
 * @date 2021/3/7
 *
 * -Xms30m -Xmx30m -Xss1m -XX:MaxMetaspaceSize=30m  -XX:+UseConcMarkSweepGC  -XX:-UseCompressedOops
 */
public class JVMObject {
    public final static String MAN_TYPE = "man";
    public final static String WOMAN_TYPE = "woman";

    public static void main(String[] args) throws InterruptedException {
        Teacher T1 = new Teacher();
        T1.setName("Sandwich");
        T1.setSexType(MAN_TYPE);
        T1.setAge(20);
        //进行15次垃圾回收
        for (int i = 0; i< 15; i++) {
            //主动发起GC
            System.gc();
        }

        Teacher T2 = new Teacher();
        T2.setName("Jack");
        T2.setSexType(MAN_TYPE);
        T2.setAge(18);

        Thread.sleep(Integer.MAX_VALUE);

    }
}

实例代码启动
image.png

因为JVM启动有一个进程,需要一个命令jps查找到对应程序的进程
image.png
在JHSDB工具中attach上去
image.png
image.png
image.png

5.JHSDB 中查看对象

查看堆参数:
image.png
image.png
上图中可以看到实际 JVM 启动过程中堆中参数的对照,可以看到,在不启动内存压缩的情况下。堆空间里面的分代划分都是连续的。

再来查看对象:
image.png
这里可以看到 JVM 中所有的对象,都是基于 class 的对象
image.png
全路径名搜索
image.png
双击出现这个Teacher类的对象,两个,就是T1和T2对象
image.png

image.png

Heap Parameters:
Gen 0:   eden [0x0000000012e00000,0x0000000012e51f18,0x0000000013600000) space capacity = 8388608, 4.001140594482422 used
  from [0x0000000013600000,0x0000000013600000,0x0000000013700000) space capacity = 1048576, 0.0 used
  to   [0x0000000013700000,0x0000000013700000,0x0000000013800000) space capacity = 1048576, 0.0 usedInvocations: 0

Gen 1: concurrent mark-sweep generation
free-list-space[ 0x0000000013800000 , 0x0000000014c00000 ) space capacity = 20971520 used(4%)= 856992 free= 20114528
Invocations: 15

对比以上堆中分代划分
T1的内存地址0x00000000138d1330 在free-list-space[ 0x0000000013800000 , 0x0000000014c00000 )范围内属于老年代
T2的内存地址0x0000000012e00000 在eden [0x0000000012e00000,0x0000000012e51f18,0x0000000013600000)范围内,属于eden

image.png

6.JHSDB 中查看栈

image.png

image.png
从上图中可以验证栈内存,同时也可以验证到虚拟机栈和本地方法栈在 Hotspot 中是合二为一的实现了。
确认Thread.sleep()是本地方法
image.png

当我们通过 Java 运行以上代码时,JVM 的整个处理过程如下:

  1. JVM 向操作系统申请内存,JVM 第一步就是通过配置参数或者默认配置参数向操作系统申请内存空间。
  2. JVM 获得内存空间后,会根据配置参数分配堆、栈以及方法区的内存大小。
  3. 完成上一个步骤后, JVM 首先会执行构造器,编译器会在.java 文件被编译成.class 文件时,收集所有类的初始化代码,包括静态变量赋值语句、 静态代码块、静态方法,静态变量和常量放入方法区
  4. 执行方法。启动 main 线程,执行 main 方法,开始执行第一行代码。此时堆内存中会创建一个 Teacher 对象,对象引用 T 就存放在栈中。 执行其他方法时,具体的操作:栈帧执行对内存区域的影响。栈帧执行对内存区域的影响

7.从底层深入理解运行时数据区(总结)

深入辨析堆和栈

功能
⇒ \Rightarrow 以栈帧的方式存储方法调用的过程,并存储方法调用过程中基本数据类型的变量(int、short、long、byte、float、double、boolean、char 等)以 及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放;
⇒ \Rightarrow 而堆内存用来存储 Java 中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中;
线程独享还是共享
⇒ \Rightarrow 栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
⇒ \Rightarrow 堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
空间大小
栈的内存要远远小于堆内存

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程简介 JVMJava 程序的运行环境,学习 JVM,方能了解 Java 程序是如何被执行的,为进一步深入底层原理乃至程序性能调优打好基础。通过学习这门课程,你将掌握:1. JVM 内存结构的组成、各部分功能作用,学会利用内存诊断工具排查内存相关问题;2. JVM 的招牌功能-垃圾回收机制是如何工作的,如何进行垃圾回收调优;3. Java 程序从编译为字节码到加载到运行的全流程,各个阶段的优化处理;4. 了解 Java 内存模型相关知识,见识多线程并发读写共享数据时的问题和 Java 的解决方案。 适应人群 有一定的Java基础,希望提升 Java 内功的人群。 课程亮点 * 系统地学习 JVM 内存结构,垃圾回收、字节码与类加载技术。 * 在内存结构章节,能够学习掌握 JVM内存溢出现象,堆栈内存结构,利用内存诊断工具排查问题。彻底分析 StringTable的相关知识与性能优化,掌握直接内存分配原理和释放手段。 * 在垃圾回收章节,不仅会介绍垃圾回收算法、分代垃圾回收机制,还会重点介绍 G1 垃圾回收器,辨析 Full GC 发生条件,jdk8以来对垃圾回收的优化,以及垃圾回收的调优法则。 * 在字节码与类加载技术章节,会从一个 class 文件开始分析其每一字节的含义。学习字节码指令的的运行流程,字节码指令与常量池、方法的关系。掌握条件分支、循环控制、异常处理、构造方法在字节码级别的实现原理,利用HSDB工具理解多态原理。还会涉及从编译期的语法糖处理,到类加载的各个阶段,直至运行期的各项优化的详细讲解。最后不要错过方法反射优化的底层分析。 * 最后的加餐环节是带着你理解 Java 内存模型:见识多线程读写共享数据的原子性、可见性、有序性,以及很多人解释不清楚的 happens-before 规则。当然还不能少了 CAS 和 synchronized 优化。 主讲内容 第一章:引言 1. 什么是 JVM ? 2. 学习 JVM 有什么用 ? 3. 常见的 JVM 4. 学习路线 第二章:内存结构 1. 程序计数器 2. 虚拟机栈 3. 本地方法栈 4. 堆 5. 方法 6. 直接内存 第三章:垃圾回收 1. 如何判断对象可以回收 2. 垃圾回收算法 3. 分代垃圾回收 4. 垃圾回收器 5. 垃圾回收调优 第四章:类加载与字节码技术 1. 类文件结构 2. 字节码指令 3. 编译期处理 4. 类加载阶段 5. 类加载器 6. 运行期优化 第五章:内存模型 1. Java 内存模型 2. 可见性 3. 有序性 4. CAS 与原子类 5. synchronized 优化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT三明治

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值