如果你这辈子只甘心做一个平庸的Java码农,那么你完全没有必要去学习JVM相关的知识,学习JVM对于一个Java程序员的好处大概可以概括为下几点:
- 1)你能够明白为什么Java最早期被称为解释型语言,而后来为什么又被大家叫做解释与编译并存的语言(了解JVM中解释器以及即时编译器就可以回答这个问题);
- 2)你能够理解动态编译与静态编译的区别,以及动态编译相对于静态编译到底有什么好处(JVM JIT);
- 3)你能够利用一些工具,jmap, jvisualvm, jstat, jconsole等工具可以辅助你观察Java应用在运行时堆的布局情况,由此你可以通过调整JVM相关参数提高Java应用的性能;
- 4)可以清楚知道Java程序是如何执行的;
- 5)可以明白为什么Java等高级语言具有可移植性强的特性。
JVM是Java Virtual Machine(Java虚拟机)的缩写;
可以将.class文件转换为01010这样的机器能够看懂的二进制数据。
Java跨平台特性:一次编译到处运行,只是开发者写的代码运行的时候跨平台,Java虚拟机是有平台的区别的,在不同的环境下需要安装不同环境的jdk;
jvm运行时数据区:(总体分为数据和指令两个部分)
程序计数器:指向当前线程正在执行的字节码指令的地址行号,是单个线程独有的;
虚拟机栈:存储当前线程运行方法时所需的数据、指令、返回地址;(为jvm执行Java方法服务)
本地方法栈:底层是通过c或者c++代码实现的方法,使用native修饰的方法;(为jvm执行native方法服务)
方法区:JVM运行时类信息、常量、静态变量、JIT(运行时产生的数据,比如说运行时多态)
heap:存放对象的实例,是GC管理的主要区域;
直接内存:在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
虚拟机栈:
局部变量表
操作数栈
动态链接
出口
一个方法一个栈帧、栈的数据结构是先进后出的结构。
jvm内存模型
jvm运行时栈帧结构
局部变量表
局部变量使用的时候必须要赋初始值。
局部变量的存储:long、double类型在局部变量表中需要占用2个槽位。其他类型如int、float、chart、byte等引用类型需要占用1个槽位。
slot的复用,当前字节码PC计算器的值大于slot的作用域的时候,slot是可以复用的,但是垃圾收集器是不会回收。只有当局部变量表进行了读写之后,slot才能被回收(当对象使用完毕之后,要及时指向为空。)
操作数栈
就是执行字节码的指令的区域
动态链接
栈帧中有一块区域,指向该栈帧所属的方法的引用。
方法返回地址和附加信息
方法调用时,通过一个指向方法的指针指向方法的地址,方法返回时将回归到调用处,那个地方是返回地址。