###JVM初体验
基本概念:JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和 一个存储方法域。JVM 是运行在操作系统之上的,它与硬件没有直接的交互。
JVM大致可分为三部分
1.Java代码的执行
代码执行也可以分为三个过程
- 代码编译为class,命令javac
- 转载class,命令ClassLoader
- 执行class,亦可分为解释执行与编译执行两部分,编译执行可分为client complier与server compiler
2.内存管理
内存管理大致分为四个部分
-
内存空间:包含方法区、堆,本地方法栈、pc寄存器
-
内存分配:有堆上分配、TLAB分配、栈上分配
-
内存回收:1.用到的算法有:Copy、Mark-Sweep、Mark-Compact,2.sun jdk的分代回收可分为:新生代可用的GC、Minor GC触发机制以及日志格式、旧生代可用的GC、Full Gc触发机制以及日志格式
-
内存状况分析:jconsole、visualvm、jstat、jmap、MAT
3.线程资源同步与交互机制 -
线程资源同步:可分为线程资源执行机制和线程资源同步机制,线程资源同步机制:Sychronized的实现机制,lock/unlock实现机制
-
线程交互机制:Object.wait/notify/notifyall-double check pattem
-
线程状态及分析方法:jstack/TDA
###运行过程:
学过Java基础的都知道 Java 源文件,是通过编译器,能够生产相应的.Class 文件,也就是字节码文件,而字节码文件又通过 Java 虚拟机中的解释器,编译成特定机器上的机器码 。
也就是:java源文件——>.class文件——>机器码
从上面我们大致可以知道Java为什么能跨平台了:
什么是跨平台:
跨平台概念是软件开发中一个重要的概念,即不依赖于操作系统,也不依赖硬件环境。一个操作系统下开发的应用,放到另一个操作系统下依然可以运行。相对而言如果某种计算机语言不用修改代码即可做到高度跨平台,那么此语言就越抽象,硬件控制力就越低,只适合开发高度抽象的模型系统。诸如java,delphi和易语言,都已做到了跨平台。它们将可以在多种系统下开发,运行和维护。
每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是 Java 为什么能够跨平台的原因了 ,当一个程序从开始运行,这时虚拟机就开始实例化了,多个程序启动就会存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享。
JAVA运行时数据区域
java在执行java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域,这些区域都有各自的用途,和它创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建和销毁。
-
1.程序计数器
程序计数器是一块较小的内存空间,它可以看做是当前先后才能所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是改变这个计数器的值来选取下体条需要执行的字节码指令,分支、循环、跳转、异常处理、线程回复邓基础功能都需要这个计数器完成
正在执行 java 方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是 Native 方法,则为空。这个内存区域是唯一一个在虚拟机中没有规定任何 OutOfMemoryError 情况的区域 -
2.JAVA虚拟机栈
与程序计数器一样,Java虚拟机栈也是线程私有的,它的声明周期与先后才能相同。虚拟机栈描述的是java方法执行的内存模型;每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一方法从调用直至完成的过程,就对应一个栈帧在虚拟机栈中入栈到出栈的过程。 -
3.本地方法栈
本地方法栈与虚拟机所发挥的作用是非常相似的,他们的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则作为虚拟机使用到的Native方法服务。 -
4.Java堆
对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块,Java堆是被所有先后才能所共享的一块内存区域,在虚拟机启动的时候创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都是在镇里分配内存。 -
5.方法区
方法区与堆一样,是各个线程共享的内存区域,它用来存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
运行时常量池是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息时常量池,用于存放编译期生成的各种字面量和符号引用。
线程
这里所说的线程指程序执行过程中的一个线程实体。JVM 允许一个应用并发执行多个线程。Hotspot JVM 中的 Java 线程与原生操作系统线程有直接的映射关系。当线程本地存储、缓冲区分配、同步对象、栈、程序计数器等准备好以后,就会创建一个操作系统原生线程。Java 线程结束,原生线程随之被回收。操作系统负责调度所有线程,并把它们分配到任何可用的 CPU 上。当原生线程初始化完毕,就会调用 Java 线程的 run() 方法。当线程结束时,会释放原生线程和 Java 线程的所有资源。
参考书籍《深入了解Java虚拟机》