Java虚拟机内存管理及对象生命周期详解

1. JVM的主要组成部分及其作用

在这里插入图片描述
JVM包含两个子系统和两个组件,两个子系统为Class Loader(类装载)、Execution Engine(执行引擎);两个组件为Runtime Data Area(运行时数据区)、Native Interface(本地接口)。

  • Class Loader(类装载)

    • 作用:根据给定的全限定名类名(如:java.lang.Object)来装载class文件到Runtime Data Area中的Method Area。
  • Execution Engine(执行引擎)

    • 作用:执行classes中的指令。
  • Native Interface(本地接口)

    • 作用:与native libraries交互,是其它编程语言交互的接口。
  • Runtime Data Area(运行时数据区域)

    • 作用:这是我们常说的JVM的内存。

JVM的主要作用是通过编译器将Java代码转换成字节码,类加载器(ClassLoader)再将字节码加载到内存中,放在运行时数据区(Runtime Data Area)的方法区内。执行引擎(Execution Engine)将字节码翻译成底层系统指令,再交由CPU去执行,并通过本地库接口(Native Interface)调用其他语言的功能。

Java程序运行机制详细说明:

  1. 利用IDE编写Java源代码,生成.java文件。
  2. 使用编译器(javac命令)将源代码编译成字节码文件,生成.class文件。
  3. 类加载器将.class文件加载到JVM中,放在运行时数据区的方法区内。
  4. 执行引擎将字节码翻译成底层系统指令,交由CPU执行。

2. 堆栈的区别

物理地址
    • 不连续的内存分配,性能相对较慢。
    • 内存分配在运行时确定,大小不固定。
    • 存储对象实例和数组。
    • 连续的内存分配,性能快。
    • 内存分配在编译时确定,大小固定。
    • 存储局部变量、操作数栈和方法返回值。

在这里插入图片描述

存放的内容
  • :存放对象的实例和数组,关注数据的存储。
  • :存放局部变量、操作数栈、返回结果,关注程序方法的执行。
内存分配
  • :对整个应用程序共享、可见,生命周期较长,适用于占用内存较大的对象。
  • :线程私有,生命周期与线程相同,适用于局部变量和方法调用。

3. 强引用、软引用、弱引用、虚引用的区别

  1. 强引用

    • 定义:直接引用对象,如Object obj = new Object();
    • 特点:不会被垃圾回收,直到没有引用指向该对象,才会被回收。
  2. 软引用

    • 定义:用来描述一些还有用但是非必须的对象,通过SoftReference类实现。
    • 特点:内存不足时会被回收,适用于缓存。
  3. 弱引用

    • 定义:用来描述非必须的对象,通过WeakReference类实现。
    • 特点:在GC时总会被回收,比软引用更易被回收,适用于内存敏感的缓存。
  4. 虚引用

    • 定义:提供一种对象被垃圾回收时收到系统通知的机制,通过PhantomReference类实现。
    • 特点:本身不影响对象生命周期,只用于跟踪对象被回收。

4. JVM类加载机制的三种特性

全盘负责

当一个类加载器负责加载某个类时,该类所依赖的和引用的其他类也将由该类加载器负责载入,除非显式地使用另外一个类加载器来载入。

示例:

  • 系统类加载器 AppClassLoader 加载入口类(含有 main 方法的类)时,会将 main 方法所依赖的类及引用的类也载入,依此类推。
  • 以上步骤只是调用了 ClassLoader.loadClass(name) 方法,并没有真正定义类。真正加载 class 字节码文件生成 Class 对象由“双亲委派”机制完成。
父类委托

“双亲委派”是指子类加载器如果没有加载过该目标类,就先委托父类加载器加载该目标类,只有在父类加载器找不到字节码文件的情况下才从自己的类路径中查找并装载目标类。

具体过程:

  1. ClassLoader 先判断该类是否已加载,如果已加载,则返回 Class 对象;如果没有则委托给父类加载器。
  2. 父类加载器判断是否加载过该类,如果已加载,则返回 Class 对象;如果没有则委托给祖父类加载器。
  3. 依此类推,直到始祖类加载器(引用类加载器)。
  4. 始祖类加载器判断是否加载过该类,如果已加载,则返回 Class 对象;如果没有则尝试从其对应的类路径下寻找 class 字节码文件并载入。如果载入成功,则返回 Class 对象;如果载入失败,则委托给始祖类加载器的子类加载器。
  5. 始祖类加载器的子类加载器尝试从其对应的类路径下寻找 class 字节码文件并载入。如果载入成功,则返回 Class 对象;如果载入失败,则委托给始祖类加载器的孙类加载器。
  6. 依此类推,直到源 ClassLoader
  7. ClassLoader 尝试从其对应的类路径下寻找 class 字节码文件并载入。如果载入成功,则返回 Class 对象;如果载入失败,源 ClassLoader 不会再委托其子类加载器,而是抛出异常。

“双亲委派”机制只是 Java 推荐的机制,并不是强制的机制。我们可以继承 java.lang.ClassLoader 类,实现自己的类加载器。如果想保持双亲委派模型,就应重写 findClass(name) 方法;如果想破坏双亲委派模型,可以重写 loadClass(name) 方法。

在这里插入图片描述

缓存机制

缓存机制将保证所有加载过的类都将在内存中缓存,当程序中需要使用某个类时,类加载器先从内存的缓存区寻找该类,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成 Class 对象,存入缓存区。这就是为什么修改了类后,必须重启 JVM,程序的修改才会生效。对于一个类加载器实例来说,相同全名的类只加载一次,即 loadClass 方法不会被重复调用。

示例代码:

protected Class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

搬砖的小熊猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值