《深入理解Java虚拟机》读书小册
阅读完《深入理解Java虚拟机》之后总结的一些精要,方便没时间看大头书的同学快速学习
问而知
向Java提问,探寻代码内含的意蕴
展开
-
十五:运行时栈帧结构
栈帧( Stack frame) 用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈(Virtual Machine Stack)s的栈元素。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。 在编译程序代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈...原创 2019-06-08 19:12:06 · 311 阅读 · 0 评论 -
十四:类加载的过程
加载->验证->准备->解析->初始化 1.加载 比如运行时计算生成,这种场景使用得最多的就是动态代理技术,在java.lang.reflect.Proxy中,就是用了ProxyGenerator.generateProxyClass来为特定接口生成形式为“*$Proxy”的代理类的二进制字节流。 加载阶段与连接阶段的部分内容(如一部分字节码文件格式验...原创 2019-06-07 18:28:19 · 174 阅读 · 0 评论 -
十三:类加载的时机
类的生命周期: 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括: 加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中验证、准备、解析3个部分统称为连接(Linking) 解析阶段的特殊性: 加载、...原创 2019-06-07 18:27:48 · 149 阅读 · 0 评论 -
十二:Class文件常量池
Java代码在进行Javac编译的时候,并不像C和C++那样有“连接”这一步骤,而是在虚拟机加载 Class文件的时候进行动态连接 也就是说,在 Class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用 当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的...原创 2019-06-07 18:27:22 · 178 阅读 · 0 评论 -
十一:堆外内存导致的溢出错误
问题导入: 某项目运行在内存4GB的32位Windows机器上,运行Jetty服务器,划分了1.6GBA给堆内存,但是依旧不时会抛出内存溢出异常 原因: 操作系统对每个进程能管理的内存是有限制的,这台服务器使用的32 位 Windows平台的限制是2GB,其中划了16GB给Java堆,而 Direct Memory内存并不算入1.6GB的堆之内,因此它最大也只能在剩余的0.4GB空...原创 2019-06-07 18:27:02 · 300 阅读 · 0 评论 -
九:内存分配与回收策略
1.对象优先在新生代的Eden区进行分配 大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次 Minor GC。 2.大对象直接进入老年代 3.长期存活的对象将进入到老年代(虚拟机设置值,默认阈值为15) 为了能够识别哪些对象存在新生代,哪些老年代,虚拟机给每个对象定义 了一个对象年龄(Age)计数器。如果对象在Eden出生并经过第一次 Min...原创 2019-06-07 18:26:37 · 165 阅读 · 0 评论 -
八:垃圾回收相关参数
-verbose:gc 显示gc详细信息转载 2019-06-07 18:25:44 · 200 阅读 · 0 评论 -
七:垃圾回收器
1.Serial收集器 (-XX:+UseSerialGC 复制算法) 1.是一个单线程收集器,只会使用一个CPU或一条收集线程去完成垃圾收集工作 2.进行垃圾收集时,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(“Stop The World”) 3.是HotSpot虚拟机运行在Client模式下的默认的新生代收集器 4.与其他收集器的单线程相比更加简单高效,...原创 2019-05-13 20:21:55 · 166 阅读 · 0 评论 -
六:HotSpot对象存活判定和垃圾回收算法的实现(是如何发起内存回收的)
首先需要明确 如果逐个检查可以作为GC Roots节点的引用的话,是非常耗时的(很多应用一个方法区就几百兆) 需要保证在分析的过程中对象的引用关系不能发生改变,否则就不能够保证结果的正确性。因此在GC过程中,必须要停顿(枚举根节点是必须要停顿的) 枚举根节点 因此HotSpot中通过使用一组OopMap的数据结构来得知哪些地方存放有对象的引用,在OopMap的协助下,HotSpot能...原创 2019-05-12 16:14:53 · 150 阅读 · 0 评论 -
五:对象的内存布局是什么样的?
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding) 注:下面的都是在HotSpot中的实现 对象头包括两部分信息,Mark Word和类型指针 对象头的结构: Mark Word 第一部分用于存储Mark Word,即对象自身的运行时数据。 它的长度在32位和64位的...原创 2019-05-12 16:13:58 · 295 阅读 · 0 评论 -
四:虚拟机是如何为对象分配内存空间的?
“指针碰撞”(Bump the Pointer) && “空闲列表”(Free List) 假设Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”(Bump the Pointer)。 如果Java堆中...原创 2019-05-12 16:13:27 · 674 阅读 · 0 评论 -
三:虚拟机是如何定位到需要访问的对象的?
一、使用句柄访问 使用句柄访问的话,那么Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息 二、使用直接指针进行访问 使用直接指针访问,那么Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址 使用句柄来访问的最大好处就是refere...原创 2019-05-12 16:13:04 · 687 阅读 · 0 评论 -
二:关于直接内存的溢出问题
DirectMemory容量可通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java 堆最大值(-Xmx指定)一样 由DirectMemory导致的内存溢出,一个明显的特征是在Heap Dump文件中不会看见明显的异常,如果读者发现OOM之后Dump文件很小,而程序中又直接或间接使用了NIO,那就可以考虑检查一下是不是这方面的原因。 ...原创 2019-05-12 16:12:14 · 205 阅读 · 0 评论 -
一:说说对象创建过程?
一、虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过(如果没有,那必须先执行相应的类加载过程) 二、类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定,为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。 附: 虚拟机是如何为对象...原创 2019-05-12 16:11:48 · 263 阅读 · 0 评论