
JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机 .
虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。
常见的虚拟机:JVM、VMwave、Virtual Box .
JVM 和其他两个虚拟机的区别:
- VMwave与VirtualBox是通过软件模拟物理CPU的指令集,物理系统中会有很多的寄存器;
- JVM则是通过软件模拟Java字节码的指令集,JVM中只是主要保留了PC寄存器,其他的寄存器都进
行了裁剪 .
JVM 是一台被定制过的现实当中不存在的计算机 .
不管是现在仍在广泛使用JDK6,还是使用比较多的JDK8中,默认的虚拟机都是HotSpot;Sun/Oracle JDK和OpenJDK的默认虚拟机。从服务器、桌面到移动端、嵌入式都有应用。
我们主要会介绍有关JVM的以下三方面内容 :

java进程启动的时候 , 就会从操作系统这里申请来一大块内存 , 进行装修 , 会把场地划分成多个区域 , 每个区域又有不同的功能 !

堆的作用:程序中创建的所有对象都在保存在堆中.堆是最重要的区域,也是占地面积最大的区域.

用来存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据.

误区辨析 :



占地最小的区域,只是单纯保存当前代码执行到哪个指令了(存储下一个要执行的指令地址).
写好的代码 , 是被加载到内存里的 , 既然在内存里 , 每个指令都有对应的"地址" , 程序计数器就记录了当前执行到哪条指令了 , 相当于一个"书签" .


开发中可能会遇到这样的问题 :
编译生成的.class文件在硬盘里,Java进程启动(JVM启动),需要把.class文件从硬盘读到内存中,并构造出类对象,这就是类加载.

在Java Language and Virtual Machine Specifications文档中的这个章节 , 就详细介绍了.class文件的格式 :

类加载中最典型的面试题:双亲委派模型,描述的是类加载中的"加载阶段",去那些目录里找.class文件.
类加载器是JVM中特殊的模块,功能就是负责把类加载起来(完成类加载的工作) .



如果这一圈下来都没找到 , 就会抛出ClassNotFoundException !
为什么要按照这个双亲委派模型的规则来进行工作呢 ? 目的就是为了防止程序猿自己写了一个特殊的类 , 把标准库里的类给覆盖了 . 那么 , 如果自己写个类加载器器 , 是否仍然要遵守双亲委派模型呢 ? 答案是可以遵守 , 也可以不遵守 , 如Tomcat里加载一些webapps里的类时就有自己的类加载器 , 且并未遵守双亲委派模型 .
在C语言中, malloc动态申请内存 , 除非手动释放 , 否则就要等到程序结束时才会释放 . 在C中 , 内存释放全靠程序猿手动来保证 , 这是极其不靠谱的 . 合适的做法 , 是让机器自动保证 , 由机器自动负责回收不再使用的内存 , 这件事就是"垃圾回收机制" , 即GC .(garbage collection) .
那些内存才需要被回收呢 ?
注意 : 垃圾回收的基本单位是"对象" , 不是"字节" .


就是使用额外的计数器,记录某个对象,有多少个引用指向它.

可以把对象想象成 , 小旅馆的一个房间 . 引用就是房间的房卡 . 如果客人手里有房卡 , 则房间是正在使用的状态 , 如果客人手里没有房卡 , 则房间就应该被回收了 .
这个方案确实可以解决问题 , 但是也有缺陷 :

正由于这些缺陷 , java中没有采用这种方式 , 而是使用了"可达性分析" .
以代码中一些特殊的变量作为起点 , 然后从起点出发 , 看看那些对象能够被访问到 , 如果对象被访问到了 , 就标记成"可达" . 当完成一圈标记之后 , 剩下的就是"不可达" , 也就是"垃圾"了 .
什么样的变量可以被称为"起点"呢 ?
GCRoot :
优势 : 可达性分析相比于引用计数来说 , 不会占用额外的内存空间 ; 也不会涉及到循环引用的问题 .






这里涉及到几个经验规律 :
- 伊甸区中的对象绝大多数活不过一轮GC ;
- 如果一个对象生命周期比较短 , 很快就没了 ; 如果一个对象经历了几轮GC还没事 , 大概率其生命周期就很长了 .
一个小例外 : 如果当前有一个特别大的对象 , 不经历上述分代过程 , 直接进入老年代!!!因为大对象在复制算法中是很不友好的 .
以上就是四种基本的垃圾回收 . 算法实际上JVM具体是通过"垃圾回收器"来实现的上述算法 , 不同的垃圾回收器,其实针对上述算法的实现,还有一些具体的差异 . 面试中主要考的是垃圾回收算法,而不是回收器 !
本节内容到此结束 !!!