很多大佬们在推荐深入理解jvm这本书,奈何时间不够用来博客上简单的取取经记录一下,再此立个flag,明天去图书馆还书的时候一定一定要泡一整天,墙裂建议学校开个通宵自习室!!!我去买咖啡@.@
1、 什么是JVM?
JVM是Java Virtual Machine(Java虚拟机)的缩写,是一种用于计算设备的规范,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。Java语言的一个非常重要的特点就是与平台的无关性。Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。
2、JVM原理?
Java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。
3、JVM的体系结构?
(1)java栈内存, 栈的内存地址是不连续的, 每个线程都拥有自己的栈。线程私有的,与线程生命周期相同,用于存储局部变量表,操作栈,方法返回值。局部变量表放着基本数据类型,还有对象的引用。
(2) Java堆,所有线程共享的一块内存区域,对象实例几乎都在这分配内存。用一句话通俗解释:所有new出来的对象全部放在这里。是用来存放对象信息的。栈是运行时单位,解决程序该如何执行的问题,而堆是存储的单位, 解决数据存储的问题。Heap是伴随着JVM的启动而创建,负责存储所有对象实例和数组的。堆的存储空间和栈一样是不需要连续的。
(3)程序计数寄存器,程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
由于Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。如果线程正在执行的是一个Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie 方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java 虚拟机规范中没有规定任何OutOfMemoryError 情况的区域。
(4)方法区域(Method Area),存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
(5)运行时常量池(Runtime Constant Pool),代表运行时每个class文件中的常量表。存放的为类中的固定的常量信息、方法和Field的引用信息等,其空间从方法区域中分配。
(6)本地方法堆栈(Native Method Stacks),JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。