社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
这是JVM学习笔记,内容主要来自 周志明编写的《深入理解Java虚拟机 JVM高级特性与最佳实践》(第2版)一书,相当于是此书的读书笔记,还有一些内容引用自公众号内容
答:JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。在Java编程语言和环境中,即时编译器(JIT compiler,just-in-time compiler)是一个把Java的字节码(包括需要被解释的指令的程序)转换成可以直接发送给处理器的指令的程序。
答:JRE(JavaRuntimeEnvironment,Java运行环境),也就是Java平台。所有的Java 程序都要在JRE下才能运行。普通用户只需要运行已开发好的java程序,安装JRE即可。
**JVM(JavaVirtualMachine,Java虚拟机)是JRE的一部分。**它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。
**JDK(Java Development Kit,Java开发工具)**是程序开发者用来来编译、调试java程序用的开发工具包。JDK的工具也是Java程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的安装过程中,JRE也是安装的一部分。所以,在JDK的安装目录下有一个名为jre的目录,用于存放JRE文件。
延伸:J2EE、J2SE、J2ME
J2EE:Java 2 Platform Enterprise Edition 企业版,用于企业应用,支持分布式部署。
J2SE:Java 2 Platform Standard Edition 标准版,用于桌面应用,,也是J2EE的基础。
J2ME:Java 2 Platform Micro Edition 移动版用于小型设备(移动端开发、机顶盒),是J2SE的一个子集。
说明:
J2SE包含于J2EE中,J2ME包含了J2SE的核心类,但新添加了一些专有类 。
J2SE包含那些构成Java语言核心的类,比如数据库连接、接口定义、输入/输出、网络编程。笼统的讲扩充它,再加些EJB等企业应用方面就是J2EE,压缩它再加些CLDC等方面特性就是J2ME
在Java语言中,可作为GC Roots的对象包括以下几种:
延伸:引用种类(4种)
JDK1.2之后Java对引用进行扩充:强引用(Strong Reference)> 软引用(Soft Reference) > 弱引用(Weak Reference) > 虚引用(Phantom Reference)
强引用:只要强引用(类似Object object = new Object()这类的)还存在,垃圾回收器就永远不会回收
软引用:描述一些有用但是非必需的对象。对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列入回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
弱引用:描述非必需对象,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论内存是否足够,都会回收掉只被弱引用关联的对象。
虚引用:最弱放入一种引用关系,一个对象是否有徐引用的存在完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的唯一目的是能在这个对象被收集器回收时收到一个系统通知。
即使在可达性分析算法中不可达对象,也并非是“非死不可”的,这时候他们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经过两次标记过程
具体过程:如果对象在进行可达性分析后发现没有与GC Roots相连的引用链,那么它会被第一次标记并且进行一次筛选,筛选条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法(因为如果覆盖了finalize()方法那么该方法要等被调用,没有覆盖说明已经被自动调用过了)或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都是为“没有必要执行”。如果整个对象被判定为有必要执行finalize()方法,那么这个对象将会放到一个叫F-Queue队列中。finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()方法中成功拯救自己,即只要重新与引用链上的任何一个对象建立关联即可,比如把自己,也就是this关键字赋值给某一个类变量或者对象的成员变量那么在第二次标记时他会被清除出“即将回收”的集合;如果对象整个时候还没有逃脱那么基本上它就真的被回收了。
注意:对象自救的机会只有一次,因为任何一个对象的finalize()方法最多只会被系统自动调用一次。一旦对象变为finalized就再怎么也不会回到F-Queue中去了,当然也就没有机会去执行finalize()方法(这时候就会被判定为没有必要执行,就要面临下一次回收)
算法思想:分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象(详见如何回收对象)
不足:
应用场景: 针对老年代的CMS收集器;
算法思想: 将可用内存按容量大小分为相等的两块,每次只是用其中一块。当这块内存用完了就将还存活的对象复制到另一块的上面然后再把已使用的内存空间一次性清理掉
不足:
说明:如果不想浪费50%的空间就需要额外的空间进行分配担保,以应对被使用内存中所有对象都100%存活的极端情况,所以该算法可用于回收新生代(因为新生代每次收集时都有大批对象死去,只有少量存活,复制效率当然大于对象存活率高的老年代),不可用于回收老年代
过程:标记过程同上,但是后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
Java中对一般分为新生代和老年代,分代收集算法根据存活周期的不同将内存分为几块,根据各个年代的特点采用适合的收集算法。
新生代:复制算法
老年代:标记-清除算法或标记-整理算法
未完待续…
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!