JVM 体系结构详解
jvm 是一种抽象的计算机,基于堆栈架构,它有自己的指令集和内存管理,是 java 跨平台的依据,jvm解释执行字节码,或将字节码编译成本地代码执行。java 虚拟机体系结构如下:
class file
class file 是平台无关的二进制文件,包含着能被jvm执行的字节码,其中多字节采用大端序,字符使用一种改进的utf-8编码。class文件精确的描述了一个类或接口的信息,其中包括:
- 常量池:数值和字符串字面常量,元数据如类名、方法名称、参数,以及各种符号引用
- 方法的字节码指令,参数个数,局部变量,最大操作数栈深度,异常等信息
class loader
类加载器,jvm在类首次使用时动态的加载、链接和初始化。jvm默认的加载模型是双亲委派模型,类加载器之间存在父子关系的层次结构,内部使用组合实现。此外还有其他的加载方式,比如servlet加载,它先尝试自己加载,不成功再委派上层加载器,类隔离;osgi加载器之间是一种网状的依赖关系,没有上下层的区分,比较灵活。
加载
加载就是将class文件表示的类或接口,在jvm方法区中创建一个与之对应的java.lang.class对象,像class.forname()、classloader.loadclass()、反射都能触发类加载。当触发一个类加载时,详细的过程如下:
- 检查类是否已经被加载
- 将加载请求委派给上层类加载器
- 自己尝试搜索类并加载
当classloader在classpath中未找到类文件,会抛出classnotfoundexception;当类a引用类b,类a已经成功加载,但是加载b时未找到类文件,会抛出noclassdeffounderror。jvm有以下几种类加载器:
- bootstrap classloader,启动类加载器,加载 <java_home>\jre\lib 中 java 核心类库
- extension classloader,扩展类加载器,加载 <java_home>\jre\lib\ext 中的类
- system classloader,系统类加载器,也叫应用程序类加载器(application class loader),加载 classpath 环境变量中的类
链接
- 验证:确保class文件的正确性。
- 准备:为类静态字段分配内存并初始化为默认值,不会执行任何字节码指令。
- 解析:将符号引用转为方法区(运行时常量池)直接引用
初始化
执行类初始化方法,即赋值静态字段,执行静态块,顺序按照其定义的先后。父类的静态域会先于子类静态域初始化。
至此,一个类或接口被加载到了内存中,jvm会保证整个过程是线程安全的。需要注意的是整个过程没有涉及到任何实例对象。
运行时数据区
1. method area:线程共享,存储运行时常量池、类字段和方法信息、静态变量和方法的字节码,是堆的逻辑组成部分,这部分的垃圾回收是可选的。值得一提的是hotspot jvm自jdk8之后,调整了这部分内存的内容,class meta-data的分配使用本地内存,interned string和类静态变量移动到了java堆。
2. 运行时常量池:对于jvm来说具有核心作用,基本上涉及到方法或字段,jvm就会在运行时常量池中搜索其具体的内存地址。
3. heap:线程共享,存储实例对象,实例变量以及数组,是垃圾回收的主要区域。
4. jvm stack:线程私有,用于存储栈帧,当方法被调用时会创建一个栈帧入栈,栈帧由以下几部分组成:
- 局部变量表:从0开始存储this、方法参数、局部变量。
- 操作数栈:方法的工作区,在操作数栈和局部变量之间交换数据,存储中间结果,操作数栈深度在编译时就能确定。
- 帧数据:方法返回值,异常分派,以及当前方法所在类运行时常量池的引用。
5. pc register:线程私有,保存当前指令地址,执行后指向下一条指令地址。
6. native method stack:线程私有,存储本地方法信息,c或c++栈。
执行引擎
读取、翻译、执行字节码。jvm基于栈架构,这个栈就是操作数栈,字节码指令就是通过它进行各种运算。此外还有基于寄存器的虚拟机。
- interpreter,翻译:解释字节码比较快,执行慢,缺点是每次方法调用都要重新翻译解释一遍。
- jit compiler,即时编译:找出程序中频繁调用的热点方法,将字节码编译成本地代码,提高性能。
- garbage collector,垃圾收集器:回收无效对象,判断对象是否可回收,可采用不同的垃圾回收算法。
本地方法接口和库
jni,调用本地方法,c/c++库;执行引擎所需的本地方法库。
小结
主流jvm的实现有oracle的hotspot jvm、jrockit以及ibm的jvm。说到jvm调优,默认指的就是hotspot vm,足见其流行程度。如今搞java不去了解jvm就显得有点low了-v-。
要想写出高质量代码,不仅要了解jvm,像调优,问题排查等都需要完备的计算机基础知识,其实无论用什么语言开发,都是一个构建和完善自身计算机知识体系的过程。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
上一篇: java 中模拟TCP传输的客户端和服务端实例详解
下一篇: Android编程之重力感应用法分析