JVM初识二


前言

提示:


一、类的加载ClassLoader

1. 主动加载的方式有四种

  • Student s = new Student();
  • 反射,Clone
  • 初始化子类的时候,父类也会被初始化
  • 调用一个静态的方法

2.类加载的过程

  • 加载Loader

    • 通过类的全路径名,获取类的二进制的数据流
    • 解析流,将类的信息存放于方法区中
    • 创建这个Class类的实例
  • 验证
    验证加载的这个字节码是不是合法(格式,语义,符号引用等)

  • 准备
    虚拟机为这个类分配相应的内存空间

  • 解析
    将符号引用转化为直接引用

  • 初始化
    到该阶段,表示该类已经成功被加载到了系统中,这时候类才会执行java字节码文件

二、JMM

1.程序计数器

  • 具有一个较小的内存空间
  • 正常的非native方法:看做是当前线程锁执行的字节码的行号指示器(分支,循环,跳转,异常处理和线程恢复等基础功能都需要依赖计数器来完成)
    • native的方法: undefined
  • 内存是私有的
  • 唯一的一个没有规定任何OutOfMemoryError情况的区域

2.本地方法栈

  • 主要是为了native方法服务的,与虚拟机栈功能类型

3.虚拟机栈

  • 线程私有得
  • 描述方法执行的内存模型
  • 方法开始执行—> 结束执行。(对应的)栈帧的入栈---->出栈
  • 存放的是方法本身和方法变量,比如int,short

4.方法区/永久代/元空间

  • 共有的
  • 方法区(逻辑概念)
    • 逻辑上的概念
    • 加载类的定义信息,常量,静态变量,方法数据,代码等…
  • 永久代(JDK7以及以前)(方法区的一个实现)
    • 内存中不会被GC的一块永久区域
    • 加载了类信息和元数据的信息
    • 如果空间被加载的类信息占满了,那么就会发生OOM的异常
  • 元空间(JDK8之后)
    • 永久代就被彻底的移除了。被元空间所代替
    • 直接使用了本地的内存
    • HopSpot,JRockit

5.堆

  • 共有的
  • 创建对象或者数组保存的地方(Java堆处于物理不连续的内存空间中,只要是逻辑上连续即可)
  • GC发生的区域
  • 新生代(Eden,S0,S1)和老年代

垃圾回收

GC ROOTS

  • 那些可以被称为GC Roots作为根节点:
    • 虚拟机栈(栈帧中的本地变量表)中引用的对象
    • 本地方法栈中JNI(即一般说的Native方法)引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象

作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(栈帧中的本地变量)中,虚拟机,本地方法栈这都是局部变量,某个方法执行完毕之后,某些局部使用的对象可以被回收

1. 标记对象是否是可回收

  • 可触及性:确定一个对象是不是可以被回收了
  • 从根节点开始,访问某个对象,如果能够被访问到,说明该对象是可以使用的,反之,不能使用。
  • 可触及 ----> 可复活 ----> 不可触及
public class DieAliveObject {
    private static DieAliveObject dieAliveObject;
    public static void main(String[] args) {
        dieAliveObject = new DieAliveObject();
        for (int i = 0; i < 1; i++) {
            dieAliveObject = null;
            System.gc();//通知JVM可以执行GC
            try {
                //等待GC执行
                Thread.sleep(100);
            }catch (Exception e) {
                e.printStackTrace();
            }
            if (dieAliveObject == null) {
                System.out.println("dieAliveObject 为空");
            }else {
                System.out.println("dieAliveObject 不为空");
            }
        }
    }
    /**
     * 只会被调用一次,给对象唯一一次重生的机会
     * @throws Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        dieAliveObject = this; //使对象重生
    }
}

如果没有显式的重写finalize()方法,是不会产生复活效果

2.引用级别

  • 强引用

    程序中的引用,Student s = new Student();

  • 软引用

    堆空间不足的时候才会被回收

  • 弱引用

    当GC发生的时候,只要发现是弱引用,无论空间是否足够,都会被回收

  • 虚引用

    和没有引用一样

3.槽位复用

4.对象分配

1. 栈上分配

  • 逃逸技术
Student student = new Student();
public void G1(){
	//Student student = new Student();
	Gc1();
	System.gc();
}
  • 标量替换
    • 标量

    不可进一步分解的量。(主要是基本数据类型int,long)

    • 聚合量

    可以被进一步分解的量

    • 替换
      • 通过逃逸技术,确定这个对象不会被外部访问
      • 会对这个对象进一步分解(若干个变量所替代。用标量去替代聚合量)

5.TLAB分配

TLAB:(Thread Local Allocation Buffer)线程本地分配缓存区

  • 作用:避免多线程之间的冲突

TLAB:内存空间比较小(默认情况下,只占Eden的1%)。大的对象,是不能分配到这里的

6. 堆上分配

绝大多数对象的分配方式

总结

提示:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值