JVM认知(二)

方法区
在这里插入图片描述
还是这个示意图,方法区有什么作用?方法区就是存放常量、静态变量、类信息的地方。
我们的Java代码,运行之后,通过类装载子系统装载到运行时数据区,其实主要就是加载到方法区中,这也就是类信息。然后再进行一系列操作,而这一切字节码的执行,都是由字节码执行引擎完成的。
常量和静态变量就不用过多解释。
在上一篇中的代码:

package com.hpu.dong;

public class test {
    public static final int m = 100;
    public static User user = new User();

    public test() {
    }

    public int add() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        test t = new test();
        t.add();
        System.out.println("test");
    }
}

可以看到user是个静态变量,那么它是怎么存储的?我们知道,对象是存放到堆中,那么方法区和堆之间有什么关系?
在这里插入图片描述
user存放在堆中,是有具体位置的,而方法区的内存空间中存放的则是指向堆中的user地址的指针。不仅方法区如此,栈其实也是如此,都是存放的堆内存中内容的地址。大概示意图就是这样:
在这里插入图片描述
反正就是栈和方法区都指向堆。
本地方法栈
先来看个代码:

new Thread().start();

点进start方法,再点进this.start0();可以看到:

private native void start0();

这就是一个本地方法。它最终的实现不是由Java代码完成的,而是由C语言代码完成的。可以简单理解为调用别的语言的方法。

我们来看一下堆的结构示意图:
在这里插入图片描述

堆内各部分内存是如何分配的?从图中可以看到,可以分为老年代和年轻代,这两个部分占据了堆的所有内存,并且两者内存按照一比二的比例进行分配,而年轻代中可以分为Eden区、From区、To区等,这些是按照8:1:1的比例进行分配。当然了,这些比例是可以再分配的。
我们知道,对象new出来之后都是放到堆的Eden区的,当Eden区放满之后,会进行minor gc,也就是由字节码执行引擎开启一个垃圾收集线程,收集Eden区的垃圾对象。minor gc是怎么处理垃圾的?需要先了解一个概念,gc root。
GC Roots
GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等。
比如之前代码中,类名test,对象user等都可以作为GC Roots.
栈以及方法区都引用了堆中的对象,所以栈和方法区中的GC Roots都指向了堆中的部分对象,如果堆中被指向的对象还指向了别的对象,那么虚拟机会顺藤摸瓜找到呗指向的对象,但是如果栈和方法区中的不是GC Roots,那么就会清除掉这些垃圾。GC Roots 会被放到Survivor区的from区或者To区。这也是可达性分析算法的过程。
在这里插入图片描述
分代年龄
minor gc将有用的对象分配到Survivor区的一个小分区,并将其分代年龄置为1,当再一次进行minor gc时,除了Eden区,Survivor区的对象也需要进行处理,如果还有用,那么就移到Survivor区的另一个小区,并将分代年龄+1。如果在minor gc期间,对象已经没有用,那么就当作垃圾清理掉。当Survivor区的对象的分代年龄达到15的时候,移到老年代

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值