根据之前的读书计划,我本应该阅读《Tom的设计模式》这本书。然而,由于一些原因,我不得不提前将图书馆借阅的书归还,因此我转而开始阅读《深入理解Java虚拟机》。至于设计模式,我还有一本小傅哥的书籍,我会再稍后找时间阅读。

《深入理解Java虚拟机》这本书我已经从年前开始阅读了,由于过年期间的一些琐事,到现在已经有一个多月了。这本书涉及的技术非常深入,以我目前的水平来说,我尽量记住一些我理解了的知识点。这本书有三个版本,我手上有第一版和第三版。我在单位主要阅读第一版,而家里的第三版读的较少。我主要记录第一版的知识点,其中大部分内容基于JDK7。另外,由于之前我已经读过另一本关于JVM的书籍,所以不再记录重复的知识点。

1.程序计数器的作用:为了线程切换后能恢复到正确位置,每条线程都需要一个独立的程序计数器。这块区域不会发生内存溢出

2.在Java虚拟机规范中描述:所有的对象实例以及数组都要在堆上分配,(The heap is the runtime data area from which memory for all class instances and arrays is allocated) 但是随着JIT编译器的发展和逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也就渐渐变得不是那么绝对了。

3.直接内存不受收JVM的堆大小 限制,但是会受机器总内存限制。直接内存也会溢出

4.对象访问方式有两种:句柄访问方式,直接指针方式。HotSpot是使用的直接指针方式,速度更快。

5.如果是建立过多线程的内存溢出,在不能减少线程数或者更好64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。

6.GC需要完成的三件事情:哪些内存需要回收,什么时候回收,如何回收

7.根搜索法中,GC ROOT的对象包括以下几种:虚拟机栈(栈帧中的本地变量表)中的引用的对象,方法区中的类静态属性引用的对象,方法区中的常量引用的对象,本地方法栈中JNI的引用的对象

8.再谈引用:当内存空间还足够时,则能留在内存中,如果内存在进行垃圾收集后还是非常紧张,则可以抛弃这些对象。

9.Paraled Scavenge收集器的特点是它的关注点和其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而Paralel Scavenge收集器的目标则是达到一个可控制的吞吐量。 停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户的体验。而高吞吐量则可以最高效率的利用CPU时间,尽快的完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

10.CMS(Concurrent Mark Swap)收集器是一种以获取最短回收停顿时间为目标的收集器。

11.G1将整个Java堆划分为多个大小固定的独立区域,并且跟踪这些区域里面的垃圾堆积程度,再后台维护一个优先列表,每次根据允许的时间,优先回收垃圾最多的区域

12.动态对象年龄判定,为了能更好地适应不同程序的内存状况,虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

13.除了Java堆和永久代之外,下面这些区域还会占用较多的内存,这里所有的内存总和会受到操作系统进程最大内存的限制:
Direct Memory:NIO
线程堆栈:OutOfMemoryError:unable to create new native thread(无法建立新的线程),—工作这么多年也遇到过这个错误,都是重启完事,看了书终于知道原因了
Socket缓存区: IOException:Too many open files

14.java.net.SocketException:Connection reset
远端断开连接异常 导致JVM进程崩溃。 发生Connection Reset后,时间越长就累积了越多Web服务没有调用完成,导致在等待的线程和socket连接越来越多,最终导致虚拟机的承受能力后使得虚拟机进程崩溃。将调用改成 生产者 消费者模式的消息队列实现后,系统恢复正常。

15.Class无关性,不止Java有class,其他语言也能编译成class。 Class的结构组成确实复杂,javap -verbose x.class 查看翻译后的结构

16.类从被加载到虚拟机内存中开始,直到卸载内存为止,它的整个生命周期包括了 加载Loading、验证Verfication、准备Preparation、解析Resolution、初始化Initialization、使用Using、和卸载Unloading七个阶段。

17.对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性。这句话表达通俗一些:比较两个类是否相等,只有再这两个类是同一个类加载器加载的前提之下才有意义。

18.双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此。