java内存工作原理学习笔记(一):概述

java虚拟内存


jvm逻辑内存

1.程序计数器: 每个线程都有自己的一个计数器(因为线程切换时,需要计数器记录执行的位置,这样才能在线程恢复时回到正确的执行位置),记录线程执行的字节码的行号指示器。分支,循环,跳转,异常处理以及线程恢复等都需要这个计数器 。此区域是线程私有区域
2.虚拟机栈:也是线程私有的空间。生命周期跟线程相同。它描述的是方法的内存模型。当线程调用方法时,会创建 栈帧 。栈帧,是用于存放 局部变量表 (老马说的栈内存,是存放编译期间可知的基本类型和对象引用), 方法返回出口 操作栈 动态链接 。在方法被执行时会创建栈帧,并将起放入虚拟机栈,直到方法执行结束后出栈。
补充: 除64位的long和double会占用两个局部空间,其他的基础类型只占用一个, 在Java 虚拟机规范中,对这个区域规定了两种异常状况:如果 线程请求的栈深度 大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;如果虚拟机栈可以动态扩展(当前大部分的Java 虚拟机都可动态扩展,只不过Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError 异常。
3.本地方法栈: 只为native方法服务,与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError 和OutOfMemoryError异常
4.java堆: 各个线程共享的区域,GC垃圾收集管理的的主要区域,如果在堆中没有内存分配实例空间,并且堆的内存无发扩张时,会抛出OutOfMemoryError异常
新生代
老年代(标记清除,标记整理算法)
还细分为:Eden空间,from Survivor空间,to Survivor空间(复制算法)
分配缓冲区TLAB

5.方法区(非堆,也有人称为永久代): 也是各个线程共享的区域, 内存回收目标:针对常量池的回收及类型的卸载,相对而言垃圾收集行为比较少 ,当方法区内存无法满足分配需求是,也会抛出OutOfMemoryError异常
存放:类信息、常量、静态变量和即时编译器编译的代码

5.1运行时常量池(是方法区的一部分): 保存Class文件中描述的符号常量,也会保存翻译后的直接引用。String.intern()方法,可以在运行时将常量放到运行时常量池中

java逻辑内存的关联关系
举例说明:假设在方法里面有一条语句 Object obj = new Object();
java虚拟机栈:在局部变量表中会存放 引用类型 Object obj
引用定位对象的方式有两种:使用句柄或直接引用
方式一:使用句柄(句柄池),reference存储的是句柄池的地址信息

方式二:直接引用(对象地址), reference存储的是对象地址

★★两种方式对比
使用句柄:在对象被移动时(垃圾回收),只会影响句柄池中实例对象的指针
直接引用:直接指向对象实例,少一次寻址的过程


java堆:会为new Object()新创建的对象分配内存空间,同时还必须要 保存查找此对象数据类型的 地址信息 (对象类型、父类、接口、实现的方法等)
java方法区:存储对象类型、父类、接口、实现方法的的 数据



猜你喜欢

转载自blog.csdn.net/hh1sdfsf56456/article/details/80534901