JDK是支持Java程序开发的最小环境集,JRE是支持Java程序运行的标准环境,JRE是JDK的一部分。
Java 1.0版本诞生于1995年,其使用的虚拟机是Sun Classisc VM,这款虚拟机已经不再使用。JDK1.3时,HotSpot VM成为了默认的虚拟机。其他较为出名的Java虚拟机还包括JRockit、J9等。
JDK1.5中的java.util.concurrent包实现了一个粗粒度的并发框架,JDK1.7中的java.util.concurrent.forkjoin包则是对该框架的一次重要扩充。Fork/Join是处理并行的一个经典的方法,能够轻松地利用多个CPU,利用Fork/Join模式,我们可以顺利地过渡到多核时代。
Java 8中,将会提供对lamda的支持,函数式编程将会得到很好地支持,而函数式编程的一个重要特点就是适合并行运算。
由于指针膨胀和各种数据类型对齐补白等原因,64位的Java虚拟机的效率要比32位的Java虚拟机效率低。企业级J2EE经常需要4GB以上的内存,目前很多仍采用虚拟集群方式在32位虚拟机中运行,迫切需要64位虚拟机的支持。
Java虚拟机在运行Java程序时会将它所管理的内存划分为若干不同的区域。这些区域有着各自的用途,以及创建和销毁时间。根据《Java虚拟机规范(Java SE7版)》的规定,Java虚拟机将会把它所管理的内存划分为下面的几个区域:
我们可以看到运行时数据区中的方法区和堆是由所有的线程所共享的,其余的如虚拟机栈、本地方法栈、程序计数器都是线程间隔离的。
程序计数器,可以看做当前线程所执行的字节码的行号指示器。字节码解释器通过程序计数器中的值来选取下一条下一条需要执行的字节码指令。循环、跳转、异常都需要依赖于程序计数器来完成。
执行多线程的程序时,为了确保线程切换后能恢复到正确的执行位置,每个线程都需要一个独立的程序计数器。
此区域是唯一一个在Java虚拟机规范中没有规定OutOfMemoryError的区域。
Java虚拟机栈,Java虚拟机栈是线程私有的,它的生命周期和线程相同。Java虚拟机栈包含的信息包括:局部变量、操作数栈、动态链接、方法出口等。
Java虚拟机中针对这块内存定义了2种异常,如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出StackOverflowError异常,如果虚拟机栈无法申请到足够的内存,就会抛出OutOfMemoryError异常。
本地方法栈,本地方法栈和Java虚拟机栈的作用很相似,只是本地方法栈是为Java虚拟机的Native方法服务的。很多的虚拟机(例如HotSpot)就直接将本地方法栈和Java虚拟机栈合二为一。
Java堆,Java堆的目的是存放对象实例。Java堆是垃圾回收管理器管理的主要区域,Java堆可以分为新生代和老生代,再具体一点可以分为Eden空间、From Survivor、To Survivor等。
Java堆可以是物理上不连续的空间,只要是逻辑上连续即可。
主流Java虚拟机中的Java堆都是可变的,通过-Xmx和-Xms来控制。
Java堆上无法申请内存时也会抛出OutOfMemoryError异常。
方法区和Java堆一样,也是线程间共享的内存区域。方法区主要用于存储类信息、常量、静态变量等数据。
对应HotSpot虚拟机而言,方法区可以被看做是永生代。但并非数据进入了方法区就不会被回收,方法区的回收主要是常量池的回收和类型的卸载。
static是静态变量,在每次赋值的时候保留最后一个值·是属于类变量,通过类或者对象可以修改,而final是属于常量,赋值一次,不可以再次重新赋值。