1.简介
JVM全拼Java Virtual Machine(Java虚拟机),是虚构的计算机,是一种用于计算机设备的规范。Java有一个特点就是与平台无关,而JVM就是实现这一特点的关键。
一般高级语言要在不同的平台上运行,至少需要生成不同的目标代码。但是引入Java虚拟机之后,Java语言在不同的平台上运行时不需要重新编译。————原因:JAVA语言使用JVM屏蔽了与具体平台相关的信息,使得Java语言编译程序只需要生成在java虚拟机上运行的目标代码(字节码),就可以在不同的平台上不加修改的运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行,这就是Java能够“一次编译,多次运行”的 结果。
JVM包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。
2.JRE、JDK、JVM的关系
(1)JRE(Java Runtime Environment,Java运行环境)
也就是指Java平台。所有的Java程序都要在JRE下才能运行。
(2)JDK(Java Development Kit,Java开发工具包)
是程序开发者用来编译、调试Java程序用的开发工具包。JDK的工具也是Java程序,也需要JRE才能运行。为了保证JDK的独立性和完整性,在JDK安装过程中,JRE也是安装的一部分。所以,在JDK的安装目录下有一个名为JRE的目录,用于存放JRE文件。
(3)JVM(Java Virtual Machine,Java虚拟机)
JVM也是JRE的一部分,是虚构出来的虚拟机,是通过在实际的计算机上仿真模拟各种计算机功能而实现的。JVM有自己完善的硬件架构,如:处理器、堆栈、寄存器等,还有相应的指令系统。JVM的作用就是实现了Java语言跨平台运行。
3.JVM原理
JVM是Java的核心和基础,在Java编译器和操作系统平台之间的虚拟处理器。Java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件编译成字节码程序,通过JVM将每一条指令翻译成不同的平台机器码,通过特定的平台运行。
4.JVM执行过程
(1)加载.class文件
(2)管理并分配内存
(3)执行垃圾收集
JVM在整个JDK中处于最底层,负责操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境。操作系统装入JVM是通过JDK中的Java.exe来完成的,通过以下4步来完成JVM环境:
<1>创建JVM装载环境和配置
<2>装载JVM.dll
<3>初始化JVM.dll,并挂界到JNIENV(JNI调用接口)实例
<4>调用JNIENV实例装载并处理class类
5.JVM的生命周期
(1)JVM实例对应一个独立运行的Java程序,它是进程级别
启动:启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(string[] args)函数的class都可以作为JVM实例运行的起点;
运行:main()作为该程序初始线程的起点,任何其它线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程。main()属于非守护线程,守护线程由JVM自己使用,Java程序也可以自己声明自己创建的线程是守护线程。
消亡:当程序中的所有非守护线程都终止时,JVM才退出。若安全管理器允许,程序也可以使用Runtime类或System.exit()退出。
(2)JVM执行引擎实例则对应了属于用户运行程序的线程
6.JVM体系结构
(1)类加载去:用来装载.class文件
(2)执行引擎:执行字节码,或执行本地方法
(3)运行时数据区:方法区、堆、Java栈、PC寄存器、本地方法栈
7.JVM运行时数据区
(1)PC寄存器
PC寄存器用来存储每个线程下一步将执行的JVM指令。如:该方法是native的,则PC寄存器中不存储任何信息。
(2)JVM栈
JVM栈是线程私有的。每个线程创建的同时都会创建JVM栈。JVM栈中存放的为当前线程中局部基本类型的变量(Java的八种基本类型)、部分的返回结果和stack frame,非基本类型对象在JVM栈上仅存放一个指向堆上的地址。
(3)堆(heap)
JVM用来存储对象实例及数组值得区域。Java中通过new创建的对象的内存都分配在此。堆中的对象的内存需要等待GC进行回收。
《1》堆是JVM中所有线程共享的。因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的。
《2》为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本是一样高效的。但如果对象过大的话则仍然是直接使用堆空间分配。
《3》TLAB仅作用于新生代的Eden space,因此在编写Java程序时,通常多个小的对象大的对象分配起来更加高效。
《4》所有新创建的object都将会存储在新生代Young Generation中。如果Young Generation的数据在一次或者多次GC后存活下来,那么将被转移到old Generation。新的object总是创建在Eden space。
(4)JVM方法区
《1》在Sun JDK 中这块区域对应的为Permanet Generation(持久代)。
《2》方法区域存放了所加载类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的field信息、类中的方法信息,当开发人员在程序中通过class对象中的getName、isInterface等方法来获取信息时,这些数据都源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
(5)运行时常量池
存放的为类中的固定的常量信息、方法和Field的引用信息等,其空间从方法区域中分配。
(6)本地方法栈
JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。
8.JVM垃圾回收
GC (Garbage Collection)的基本原理:将内存中不再被使用的对象进行回收,GC中用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征进行分析后,按照新生代、旧生代的方式来对对象进行收集,以尽可能的缩短GC对应用造成的暂停
(1)对新生代的对象的收集称为minor GC;
(2)对旧生代的对象的收集称为Full GC;
(3)程序中主动调用System.gc()强制执行的GC为Full GC。
不同的对象引用类型, GC会采用不同的方法进行回收,JVM对象的引用分为了四种类型:
(1)强引用:默认情况下,对象采用的均为强引用(这个对象的实例没有其他对象引用,GC时才会被回收)
(2)软引用:软引用是Java中提供的一种比较适合于缓存场景的应用(只有在内存不够用的情况下才会被GC)
(3)弱引用:在GC时一定会被GC回收
(4)虚引用:由于虚引用只是用来得知对象是否被GC
JVM学习笔记
最新推荐文章于 2024-08-14 14:41:54 发布