java内存区域
java 运行时数据区域
image.png-
程序计数器
1、程序计数器是一块较小的内存,它可以看成是当前线程所执行的字节码的行号指示器;
2、它工作时就是通过改变这个值来控制选取下一条需要执行的字节码指令、循环、跳转、异常处理等;
3、它是唯一一块在虚拟机中没有规定人和oom的区域
4、线程私有的 -
java虚拟机栈
1、线程私有的,生命周期和线程同步
2、可以理解为栈就是java虚拟机的局部变量表,局部变量表储存了各种基本数据类型(byte,short,int,long,float,double,char,boolean)和对象引用 -
本地方法栈
1、本地方法栈和java虚拟机栈的特点类似
2、java虚拟机栈为java方法服务,而本地方法栈是为本地方法(native方法)服务 -
java堆
1、对于大部分应用而言,java虚拟机中的堆内存是内存分配最大的一块
2、堆内存是所有线程共享的一块区域,在虚拟机启动的时候创建
3、此内存唯一的储存对象是对象实例
4、java 堆是垃圾回收机管理的主要区域 -
方法区
1、方法区和堆一样是所有线程共享的
2、它用储存已被虚拟机加载的类信息,常量,静态变量,即使编译器编译后的代码等数据 -
运行时常量池
1、它是方法区的一部分,用于储存编译期生成的各种字面量和符号引用,这类内容将在类加载后进入方法去的运行时常量池存放 -
直接内存
1、直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域;
2、比如;在jdk 1.4以后引入了nio 引入了一种基于channel与缓冲区buffer的io方式,他可以是用native函数库直接分队堆外内存,然后通过储存在java堆中的directbytebuffer对象作用这块内存的引用进行操作
hotspot 虚拟机对象探秘
虚拟机的内部探秘其实无非就包含实例的创建和事例的储存以及访问(每个储存都不一样,以对象和堆为例)
-
对象的创建
1、虚拟机在遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,而且检查这个符号引用代表的类是否已被加载,解析,和初始化,如果没有,那必须先执行相应的类加载的过程;
2、指针碰撞-如果堆内存是规整的,分配内存其实就是指针想空闲区移动(指针移动可能出现线程间的线程不安全,虚拟机解决有两种(cas和每个线程的区域不同))
空闲列表-如果堆内存不是规整的,那么里面哪些用了哪些没有将有表来记录
3、选用那种分配方式由java堆的是否规整来决定,java堆的是否规整又由所采用的垃圾回收器是否带有压缩整理功能决定
4、对象在执行new 后 会执行init 方法(程序员意愿进行初始化) -
对象的内存布局
1、在hotSpot虚拟机中,对象在内存中储存的布局可以分为3块区域:对象头(2部分:储存对象自身的运行时数据和类型指针,通过类型指针来确定是哪个类的实例),实例数据(程序代码中定义的各种类型的字段内容),对齐填充(不重要,只是占位符) -
对象的访问定位
1、通过句柄访问对象
2、通过直接指针来访问对象
java内存溢出(oom)
-
java堆溢出
1、先判断是内存泄露还是内存溢出
如果是内存泄露,用专门的工具检测出对象的引用和代码地方,判断出垃圾回收器为什么没有进行回收;
如果是内存溢出,也就是那些对象确实有用,那就通过调整虚拟机参数来增大内存 -
虚拟机栈和本地方法栈溢出
1、两种异常(如果线程请求的栈深度大于虚拟机所允许的最大深度,则抛出 stackoverflowerror ,如果虚拟机在扩展栈是无法申请到足够的内存空间,则抛出oom) -
方法区和运行时常量池溢出
1、方法区溢出也是一种常见的内存溢出异常,一个类要被垃圾回收器回收掉,判定条件是比较苛刻的
- 本机直接内存溢出
网友评论