本地库接口是操作系统实现的,对应的栈就是本地方法栈
方法区
- 方法区被所有线程共享
- 存储已被虚拟机加载的类信息、常量(final)、静态变量(static)、(构造方法、接口信息)等数据
- 垃圾收集行为在这个区域比较少出现,回收目标主要是针对常量池的回收和对类型的卸载
- 运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容在类加载后存放到运行时常量池。
PC Register 程序计数器
每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个要执行的指令代码)
本地方法栈
Native方法的栈
八字箴言:栈管运行,堆管存储
虚拟机栈
当一个方法被调用时就产生了一个栈帧,并被压入到栈中
- 线程私有
- 生命周期和线程相同
- 基本类型变量(boolean,byte,char,int....)和对象的引用变量(引用指针或句柄) 在栈内存中分配(简单理解就是在方法里定义的各种局部变量,自定义类的变量只有指针)
- 栈中存储的是栈帧(对应一个方法), 栈帧保存了 :
1). 本地变量(输入/输出参数,方法内定义的局部变量)
2). 栈操作(记录出栈、入栈的操作)(以及动态链接、方法出口) - 局部变量所需要的内存在编译期间完成分配
堆内存
堆内存示意图
实例化对象的产生到消亡发生在新生区
新生区又分为两部分:
- Eden Space, 所有的新生对象在这里产生
- 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
说明JVM对永久代设置的内存不够。一般出现这种情况,都是程序启动需要加载大量的第三方Jar包。
JAVA7永久代 === JAVA8 元空间
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。