Java 虚拟机简介
Java 号称 「一次编译,到处运行」的主要源于 JVM (Java Virtual Machine)。对于 Java 程序来说,只认识一个操作系统,就是 JVM,字节码文件(拓展名为 .class)就是 JVM 的可执行文件,具体和各个操作系统打交道的活则是各个系统对应的 JVM 来实现。
我们要记住两点:
-
JVM就是Java程序的操作系统,JVM的可执行文件就是.class文件。
-
Java虚拟机屏蔽了操作系统之间的差异,但是不同的系统使用的虚拟机不同。
常见的虚拟机
虚拟机有很多种,现在较为常见的为以下几种:
-
Sun HotSpot :
-
JDK3 之后的官方默认虚拟机
-
同样有准确式内存管理
-
因其热点探测技术而闻名。(知道哪一段代码经常执行,将其编译成机器代码,提高运行效率)
-
-
BEA JRockit:
-
BEA 公司研发的,对服务端高度优化的虚拟机
-
其垃圾收集机制和 MissionControl 服务套件,一直处于 Java 虚拟机的领先水平
-
Oracle 在 2008 年收购 BEA 公司,在 2009 年收购 Sun 公司。Oracle 计划从 JDK8 开始将两种虚拟机融合成一种。(JDK8 的 HotSpot 已经放弃用永久代来实现方法区,转而使用元空间)
-
-
IBM J9
- J9 虚拟机是 IBM 公司单独开发的高性能虚拟机,它并不独立出售,而是作为 IBM 公司各种产品的执行平台,IBM 把它定义为一个可以适应从嵌入式设备到大型企业级应用的、高可移植性的Java运行平台
Java 内存区域
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来
程序计数器(Program Counter Register) 也叫做 pc 计数器,由于Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。这也是虚拟机规范中唯一没有定义 OutOfMemoryError 的区域。
Java 虚拟机栈(Java Virtual Machine Stack)也是线程私有的,生命周期与线程相同。描述的是 Java 方法执行的线程内存模型:每个方法执行时,虚拟机都会穿建一个栈帧用于存储局部变量、操作数栈、动态链接等信息,一个方法从被调用到执行完毕就对应着栈帧在虚拟机栈中入栈到出栈的过程。如果线程申请栈空间不够时,会发生 OutOfMermoryError。
本地方法栈(Native Method Stack) 与虚拟机栈类似,不过是用来执行本地(Native)方法时用到,OOM 也与上类似
Java 堆(Headp) 是虚拟机管理的内存最大的一块,是所有线程共享的区域。Java 堆是垃圾回收的主要区域,也是之后我们关注的重点。由于现代垃圾回收器大部分采用分代策略,故有些名称「年轻代」「老年代」「永久代」「Eden 区域」「Survivor 区域」会在之后讲分代算法时进行介绍。Java 堆用于分配内存给对象,当内存不足以分配给新的对象时会发生 OOM 异常。
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫作“非堆”(Non-Heap),目的是与Java堆区分开来。
直接内存(Direct Memory) 并不是虚拟机运行区域的一部分,也不在虚拟机规范中定义。但是在 NIO 中大量使用直接内存,由于受限于机器的物理内存上限,这块区域也是会发生 OOM 的。
下一回讲解垃圾回收算法与垃圾回收器
网友评论