一、背景
先来一段官方的语言:java虚拟机是java运行的必不可少的平台,java所谓的号称跨平台,都是基于这个JVM来实现的,java的并不是真正的跨平台,而是jvm可以把对应的class字节码转换成对应的机器码来执行,而这个操作就是由jvm来实现的。同时,每个不同的平台jvm也不同,比如window和linux的jvm是不一样的,需要安装不同的jvm。下面来看下这个JVM的体系接口
二、JVM体系结构
JVM的的功能主要包含以下几大块:类加载器 class loader +执行引擎+运行数据区域,起核心的图主要是以下几个方面
jvm通过类加载器把编译好的字节码文件.class加载到内存汇中,这里的类加载器主要分为三类,bootstrap classloader,Extension classloader,Application Classloader 当然还有用户自定义的文件。这里主要讨论的是jvm的内存模型,而执行引擎主要是执行本地方法。这里主要讲的是java的内存模型,其中分为5大部分,当然最近又被分成6大部分,其中方法区中又划分出来运行常量池等。如上图所示,主要的区域是:栈(stack)、堆(heap)、程序计数器(pc register)、方法区(Method Area)、本地方法栈(Native Method Stack)、还有一个运行常量池(Local Param Array)。这是jvm的主要几个核心区域。下面简单的来介绍一下各个模块是干啥的:
栈(stack):这个是每个线程私有的,与线程同时创建,它的生命周期和线程相同,每一个方法执行的时候都会创建一个栈帧,用于存储局部变量表,这里的比如基本类型int,byte等,还有引用类型,还有操作数栈、动态链接、方法出口等。每个方法从开始调用,到执行完成的过程就对应着一个栈帧从入栈到出栈的过程。
本地方法栈(Native Method Stack):类似于Stack,但是该栈的功能用来服务虚拟机调用的本地方法。
程序计数器(PC register):这个也是每个线程私有的,用来存储线程的执行指令,位置,下一步需要执行的指令等。因为每 个线程都是共享轮流获取cpu的,必然存在执行一段时间之后,失去cpu,进入等待状态,此时它的状态就需要进行保存起来。如果当前执行的是native方法,则为null。
方法区(method Area) : 该区域也是线程共享的,用来存储每个类的结构信息、成员变量、和方法和数据、接口类型。比如类的访问修饰符 private,public等。方法区也是通常所说的用久区。
运行时常量池(Local Param Array) : 从方法区中分配出来的一块区域,用来存放类中的固定常量信息、方法和域信息。
堆(heap):这个java内存中使用的最大一块内存区域,是所有线程共享的区域。用来存放所有创建出来的实例对象和数组值的 区域,java中所有通过new创建的对象都在该区域分配,该区域分为新生代和老年代,也是垃圾回收的主要区域。
三、小结
以上只是java虚拟机的一部分结构,整体java虚拟机包含了类加载器、java内存模型、垃圾回收等等,这里主要对学习java虚拟机做一个简单的总结。那么在使用java虚拟机的过程中,会产生大量的对象,如果全部放在堆里面,那么内存会直接溢出,需要有一个垃圾回收机制,把不需要使用的对象来进行回收掉,那么是如何进行回收的呢?后面会专门去了解一下jvm的垃圾回收算法等。
四、垃圾回收机制
既然写到这里,后面干脆把垃圾回收的相关知识点加上,这里就花了几个图,做了一些小的总结。具体的如下所示:
经过上面的总结之后,总算对垃圾的回收算法有了一些清晰的认识,主要就是这么几种垃圾回收算法,那么回收的区域是怎么样的呢?在接着看下一下垃圾回收的内存区域是如何分配的。java对内存的分配其实是主要分为新生代New Generation 和老年代Old Generation,而大部分创建的对象都存储在新生代,其中又分为Eden和Survivor两个区域,主要用户解决生命周期较短的对象,进行垃圾回收。具体的注释看下面的备注。
参考的文章链接:https://www.cnblogs.com/java-my-life/archive/2012/08/01/2615221.html
https://segmentfault.com/a/1190000002579346
http://jayfeng.com/2016/03/11/%E7%90%86%E8%A7%A3Java%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6/