java内存总结

Java虚拟机管理的内存的区域可由下面这张图表示
java内存总结_第1张图片
2012101820014328.jpg

这些内存区域可以划分为线程私有和线程共享两类:

  • 线程私有即是指该内存区域与线程同生共死,且该区域仅对该线程可见.
  • 线程共享则是指该内存区域随虚拟机启动而开辟,随虚拟机关闭而释放,且该区域对所有线程可见.

线程私有

  • 程序计数器:
    一块小的内存区域,是当前线程所执行的字节码的行号指示器.
    当实行java方法时,值为虚拟机字节码指令地址;执行native方法时,值为空.
  • 虚拟机栈:
    从对应关系来看,一个线程对应一个虚拟机栈,而线程的一个方法对应虚拟机栈中的一个栈帧.可表现为下图:


    java内存总结_第2张图片
    无标题.png

    一个栈帧中储存了一个方法的局部变量表,操作数栈,动态链接,方法出口等.
    线程调用一个方法即是一个栈帧入栈,结束一个方法即是一个栈帧出栈.

  • 本地方法栈:
    与虚拟机栈的结构,作用类似,不同的是虚拟机栈执行的是java方法,本地方法栈执行的是native方法.
    注:有的虚拟机将二者合二为一.

线程共享

  • java堆:
    用于存放对象实例和数组.
  • 方法区:
    用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据.
    方法区中包含运行时常量池,Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
  • 直接内存:
    并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域.(堆外内存)


    java内存总结_第3张图片
    无标题.png

一个实例对象被创建的过程如下图所示:

java内存总结_第4张图片
IMG_20170720_132011.JPG

对象的内存布局

  • 对象头
    对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码 (HashCode),GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等.
    对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
    另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中却无法确定数组的大小。
  • 实例数据
    实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内存。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
  • 对齐填充
    对象的大小必须是8字节的整数倍,当不符合时,由占位符填充来保证.

对象的访问定位

引用有两种:

  • 句柄:
    句柄包含了对象实例指针和对象类型指针


    java内存总结_第5张图片
    927608-20160702110103187-956075011.png
  • 直接指针:
    对象头中有对象类型指针


    java内存总结_第6张图片
    927608-20160702110119593-1353417498.png

你可能感兴趣的:(java内存总结)