转载

[Java]Java内存模型

[Java]Java内存模型

本地库接口是操作系统实现的,对应的栈就是本地方法栈

方法区

  • 方法区被所有线程共享
  • 存储已被虚拟机加载的 类信息常量 (final)、 静态变量 (static)、(构造方法、接口信息)等数据
  • 垃圾收集行为在这个区域比较少出现,回收目标主要是针对常量池的回收和对类型的卸载
  • 运行时常量池 是方法区的一部分,用于存放 编译期 生成的各种 字面量和符号引用 ,这部分内容在 类加载后 存放到运行时常量池。

PC Register 程序计数器

每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个要执行的指令代码)

本地方法栈

Native方法的栈

八字箴言:栈管运行,堆管存储

虚拟机栈

当一个方法被调用时就产生了一个栈帧,并被压入到栈中

  • 线程私有
  • 生命周期和线程相同
  • 基本类型变量 (boolean,byte,char,int....)和 对象的引用变量 (引用指针或句柄) 在栈内存中分配(简单理解就是在方法里定义的各种局部变量,自定义类的变量只有指针)
  • 栈中存储的是栈帧(对应一个方法), 栈帧保存了 :
    1). 本地变量 (输入/输出参数,方法内定义的局部变量)
    2). 栈操作(记录出栈、入栈的操作)(以及动态链接、方法出口)
  • 局部变量所需要的内存在 编译期间 完成分配

堆内存

堆内存示意图

[Java]Java内存模型

实例化对象的产生到消亡发生在新生区

新生区又分为两部分:

  1. Eden Space, 所有的新生对象在这里产生
  2. Survivor 0 , Survior 1;
  • 当Eden Space 用完的时候,程序又需要创建新对象,JVM 垃圾回收器将对Eden Space 进行 Minor GC :将 不再被其他对象引用的对象销毁 ,然后将Eden中 剩余的对象移动到 Survior 0 中。
  • 如果Survior 0 也满了, 再对该区进行垃圾回收,然后移动到Survior 1区
  • 同样的,如果Survior 1 区也满了,将会把剩余的对象移到老年代。 如果老年代也满了 ,则会发生 Major GC (Full GC) ,对老年代的内存进行清理。如果老年代经过GC后仍无法保存对象,就会产生OOM。

注:

如果出现 OOM :Java heap space的错误,说明JVM的堆内存不够,原因有两点:

(1).堆内存设置的不够大,默认最大是机器内存的1/4,可以通过参数-Xms(初始内存), -Xmx(最大内存)

(2). 代码中创建了大量的大对象,并长时间不能被垃圾收集器收集

可以new出一个很大的对象,这个对象大小需要小于机器最大内存,并调整JVM参数

老年代

用于保存从新生代筛选出的Java对象,一般池对象(如jdbc连接池)都在这个区域活跃,很少发生GC

永久代

  • 没有垃圾回收,关闭JVM才会释放所占用的内存
  • 常驻内存
  • 用于存放JDK自身所携带的Class,Interface的元数据(或者说是存储的是运行环境所必须的类信息)

如果出现 OOM:PermGen space

JAVA7永久代 === JAVA8 元空间

原文  https://segmentfault.com/a/1190000022353721
正文到此结束
Loading...