JAVA虚拟机-图解内存结构

版权声明:欢迎转载,标明出处 https://blog.csdn.net/mz4138/article/details/81940663

总览图

本节讨论一下内容的结构
1. 堆
2. 栈
3. 方法区

定义: 随线程创建而生,线程销毁而灭.

存放内容:
1. 方法内定义的局部变量(基本类型存内容,引用类型存引用。不存引用类型的具体内容)
2. 方法参数

栈总览图

JVM 规定栈的内容:

  1. JAVA虚拟机栈 (所有非native方法的栈)
  2. 本地方法栈(所有native方法的栈)
  3. 程序计数器(程序运行的字节码行号指示器,可以理解为DEBUG 断点时,当前的行号)

JAVA虚拟机栈

栈是一种数据结构,具有先进后出的特性。JAVA虚拟机栈就是一个栈结构的一块数据区

搞清楚JAVA虚拟机栈 push和pop 的内容是什么,也就理解了JAVA虚拟机栈

方法被调用时,栈帧入栈. 方法返回时,栈帧出栈

栈帧是什么呢? 存放了什么东西
1. 局部变量表(可以理解为 定义的局部变量)
2. 操作数栈(执行指令的参数)
3. 动态链接(运行时常量池的方法引用. 可以理解为java.lang.Method 对象)
4. 返回地址(return)

这些概念还是很拗口,很难理解。 接下来通过例子来加深对栈帧的理解

举例说明:

public class JvmStack {
    public static void main(String[] args) {
        methodA();
    }

    public static void methodA() {
        int a = 1;
        methodB(a);
    }

    public static int methodB(int param) {
        return param;
    }
}

这里省略了main方法栈帧入栈出栈图

methodA方法被调用时, methodA 栈帧入栈
methodA方法被调用
methodB方法被调用时, methodB 栈帧入栈
methodB方法被调用
methodB 调用结束后.栈帧恢复为 methodA方法被调用 的形态

methodA 调用结束后.栈帧恢复为 main方法被调用 的形态

堆是JAVA内存结构中,最复杂的部分,垃圾收集也主要是针对这一块区域

定义:
堆的主要作用就是进行对象内容的分配.

存放内容: new对象的实际占用空间

堆的划分

JAVA堆被划分为两块区域
1. 新生代
2. 老年代
他们是物理隔离的两块区域(G1收集器时除外)

java堆

堆为什么要划分为新生代,老年代?

由于JAVA分配对象的特性,98%的对象都是朝生夕死的, 将堆划分为两块区域是
为了采用不同的垃圾收集算法收集相应的区域。

新生代对象分配

划分新生代之后,分配对象时,内存是绝对规整的,可以用拨动指针的方式分配对象
新生代分配对象

假设从 0x46F03000的位置开始分配对象
1. 第一个对象:0x46F03000, 大小为1MB
2. 第二个对象: (0x46F03000+1MB), 大小为13KB
2. 第三个对象起始地址: (0x46F03000+1MB+13KB),大小为105KB

对象的大小只要是 8 的整数倍就行.(否则会加入对齐填充)

老年代对象分配

老年代的内存并不是绝对规整的
老年代分配对象
如图。 即将被回收的对象回收后。 这个缝隙只能容得下新对象A

新对象B分配时要找可以容纳自己的位置

堆内存总结

堆将区域划分为多块的目的: 为了更高效的垃圾收集

方法区

存放内容:
1. 类的Class对象
2. 运行时常量池(可以理解为定义的常量)

JDK1.8 之后将PermGen 改为 Metaspace。 也叫做元数据区

猜你喜欢

转载自blog.csdn.net/mz4138/article/details/81940663