Java基础:Java虚拟机JVM
Java是一种跨平台语言,主要是基于Java虚拟机(JVM)。JVM是每位Java程序员都应该了解和学习的,这里做一个简单的总结。
Java内存模型
JMM:JVM定义了不同运行时数据区,他们是用来执行应用程序的。某些区域随着JVM启动及销毁,另外一些区域的数据是线程性独立的,随着线程创建和销毁。JVM在执行Java程序时,会把它管理的内存划分为若干个的区域,每个区域都有自己的用途和创建 销毁时间。
方法区和堆对是所有线程共享的内存区域;而java栈、本地方法栈和程序员计数器是运行是线程私有 的内存区域。
Java堆(Heap),是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内 存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实 例都在这里分配内存。
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数 据。
程序计数器(Program Counter Register),是一块 较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。
JVM栈(JVM Stacks),与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是 线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方 法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态 链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机 栈中从入栈到出栈的过程。
本地方法栈(Native Method Stacks),与虚拟机栈所发 挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
HotSpot
HotSpot虚拟机包括一个解释器和两个编译器(client 和 server,二选一的),解释与编译混合执行模式,默认启动解释执行。
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字 节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特 性。
JVM组成
JVM包含两个子系统和两个组件,分别为 Class loader(类装载子系统) Execution engine(执行引擎子系统); Runtime data area(运行时数据区组件) Native Interface(本地接口组件)。
「Class loader(类装载):」 根据给定的全限定名类名(如:java.lang.Object)来装载class文件到运行时数据区的方法区中。
「Execution engine(执行引擎)」:执行class的指令。
「Native Interface(本地接口):」 与native lib交互,是其它编程语言交互的接口。
「Runtime data area(运行时数据区域)」:即我们常说的JVM的内存。
首先通过编译器把 Java源代码转换成字节码,Class loader(类装载)再把字节码加载到内存 中,将其放在运行时数据区的方法区内,而字节码文件只是 JVM 的一套指令集规范,并不能直 接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将 字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库 接口(Native Interface)来实现整个程序的功能。
JVM加载class文件的原理机制
JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。
当Java程序需要使用某个类时, JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class文 件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的 Class对象。
加载完成后,Class对象还不完整,所以此时的类还不可用。
当类被加载后就进入连接 阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用 替换为直接引用)三个步骤。
最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个 类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语 句。
类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器 (Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子 类)。
从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了 Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个 父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加 载。JVM不会向Java程序提供对Bootstrap的引用。