JVM(Java虚拟机)知识体系(更新中...)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了JVM(Java虚拟机)知识体系(更新中...),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6621字,纯文字阅读大概需要10分钟。
内容图文
![JVM(Java虚拟机)知识体系(更新中...)](/upload/InfoBanner/zyjiaocheng/591/f23139ef87a84678b2b3a6076c0734f6.jpg)
文章目录
一、认识JVM
1.JVM概述
JVM(Java虚拟机)是指软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的计算机系统。JVM是软件来模拟Java字节码的指令集,是Java程序的运行环境。
2.JVM主要功能
- 通过ClassLoader寻找和装载class文件。
- 解释字节码成为指令并执行,提供class文件的运行环境。
- 进行运行期间的内存分配和垃圾回收。
- 提供与硬件的交互平台。
3.虚拟机是Java平台无关的保障
4.JVM规范作用
- JVM虚拟机规范为不同的硬件平台提供了一种编译Java技术代码的规范
- 该规范使Java软件独立于平台,因为编译是针对作为虚拟机的“一般机器”而做
- 这个机器可用软件模拟并运行于各种现存的计算机系统,也可以用硬件来实现
5.JVM规范定义的主要内容
- 字节码指令集(相当于中央处理器CPU)
- Class文件的格式
- 数据类型和值
- 运行时数据区
- 栈帧
- 特殊方法的实现
- 类库
- 异常
- 虚拟机的启动、加载、链接和初始化
- 虚拟机官方文档
- 链接:Java8虚拟机规范.pdf
提取码:b1nw
特殊方法:
<init>
:实例初始化方法,通过JVM的invokespecial指令来调用
<clinit>
: 类或接口的初始化方法,不包含参数,返回void
类库:
Java虚拟机必须要对一些Java类库提供支持,否则这些类根本无法实现,比如:反射、加载和创建类或接口,如ClassLoad、连接和初始化类和接口的类、底层安全比如security、多线程、若引用
6.Class字节码解释
(1)Class文件格式
Class文件是JVM的输入,Java虚拟机规范中定义了 Class 文件的结构。Class文件是JVM实现平台无关、技术无关的基础。
- Class文件是一组以8字节为单位的字节流,各个数据项目按序紧凑排列
- 对于占用空间大于8字节的数据项,按照高位在前的方式分割成多个8字节进行存储
- Class文件格式里面只有两种类型:无符号数、表
无符号数:基本数据类型,以u1、u2、u4、u8来代表几个字节的无符号数
表:由多个无符号和其他表构成的符合数据类型,通常以 "_info"结尾
(2)Class文件格式说明
- constant_pool_count:是从1开始的
- 不同的常量类型,用tag来区分,它后面对应的 info 结构是不一样的
- L表示对象,[ 表示数组、V表示void
- stack:方法执行时,操作栈的深度
- Locals:局部变量所需的储存空间,单位是 slot
- slot是虚拟机为局部变量分配内存所使用的最小单位
- args_size:参数个数,为1的话,因实例方法默认会传入 this,locals 也会预留一个slot来存放
7.ASM开发
- ASM是一个Java字节码的操纵框架,它能被用来动态生成类或增强既有类的功能。
- ASM可以直接产生二进制class文件,也可以在类被加载入虚拟机之前动态改变类行为,ASM从类文件中读取信息后,能够改变类行为,分析类信息,甚至根据类的要求产生新类。目前许多框架如 cglib、Spring 都直接或间接得使用ASM操作字节码。
(1)ASM编程模型
- Core API:提供了基于事件形式的编程模型。该模型不需要一次性将整个类的结构读取到内存中,因此这种方式更快,需要的内存更少,但这种编程方式难度较大。
- Tree API:提供了基于树型的编程模型。该模型需要一次性将一个类的完整结构全部读取到内存中,所以这种方法需要更多的内存,这种编程方式较简单。
(2)ASM的Core API
- ASM Core ApI 中操纵字节码的功能基于 ClassVisitor 接口。这个接口中的每个方法对应了 class 文件中的每一项
- ASM 提供了三个基于 ClassVisitor 接口的类来实现 class 文件的生成和转换
ClassReader:ClassReader 解析一个类的 class 字节码
ClassAdapter:ClassAdapter 是 ClassVisitor 的实现类,实现要变化的功能
ClassWriter:ClassWriter 也是 ClassVisitro 的实现类,可以用来输出变化后的字节码 - ASM 给我们提供了 ASMifier 工具来帮助开发,可使用ASMifier 工具生成 ASM 结构来对比
二、类加载、连接和初始化
1.概述
类从被加载到JVM开始,到卸载出内存,整个声生命周期如图:
-
加载:查找并加载类文件的二进制数据
-
连接:将已经读入内存的类的二进制数据合并到JVM运行时环境中去,包含以下步骤:
- 验证:确保被加载类的正确性;
- 准备:为 类的 静态变量 分配内存,并初始化它们;
- 解析:将常量池中的符号引用转换成直接引用。
-
初始化:为类的静态变量赋初始值
2.类加载要完成的功能
- 通过类的全限定名来获取该类的二进制字节流
- 把二进制字节流转化为方法区的运行时数据结构
- 在堆上创建一个 java.lang.Class 对象,用来封装类在方法区内的数据结构,并向外提供了访问方法区内数据结构的接口
3.加载类的方式
- 最常见的方式:本地文件系统中加载、从jar等归档文件中加载
- 动态的方式:将 java 源文件动态编译成 class
- 其他方式:网络下载、从专有数据库中加载等等
4.类加载器
- Java 虚拟机自带的加载器包括以下几种:
- 启动类加载器(BootstrapClassLoader)
- 平台类加载器(PlatformClassLoader) JDK8:扩展类加载器(ExtensionClassLoader)
- 应用程序类加载器(AppClassLoader)
- 用户自定义的加载器:是 java.lang.ClassLoader 的子类,用户可以定制类的加载方式;只不过自定义类加载器其加载的顺序是在所有系统类加载器的最后
5.类加载器的关系
6.类加载器的说明
- 启动类加载器:用于加载启动的基础模块类,比如:java.base、java.management、java.xmlden等等
- 平台类加载器:用于加载一些平台相关的模块,比如:java.scripting、java.compiler、java.corba等等
- 应用程序类加载器:用于加载应用级别的模块,比如:jak.compiler、jdk.jartool、jdk.jshell 等等;还加载 classpath 路径中的所有类库
public class ClassLoaderStudy {
public static void main(String[] args) throws Exception {
String str = "Hello Class Loader";
System.out.println("str class loader == "+str.getClass().getClassLoader());
Class driver = Class.forName("java.sql.Driver");
System.out.println("driver class loader="+driver.getClassLoader().getParent());
ClassLoaderStudy t = new ClassLoaderStudy();
System.out.println("t class loader="+t.getClass().getClassLoader());
}
}
- JDK8:启动类加载器:负责将<JAVA_HOME>/lib,或者 -Xbootclasspath 参数指定的路径中的,且是虚拟机识别的类库加载到内存中(按照名字识别,比如 rt.jar,对于不能识别的文件不予装载)
- JDK8:扩展类加载器:负责加载 <JRE_HOME>/lib/ext,或者 java.ext.dirs 系统变量所指定路径中的所有类库
- JDK8:应用程序类加载器:负责加载 classpath 路径中的所有类库
- Java 程序不能直接引用启动类加载器,直接设置 classLoader 为 null,默认就使用启动类加载器
- 类加载器并不需要等到某个类“首次主动使用”的时候才加载它,JVM规范允许类加载器在预料到某个类将要被使用的时候就预先加载它
- 如果在加载的时候 .class 文件缺失,会在该类首次主动使用时报告 LinkageError 错误,如果一直没有被使用,就不会报错
7.双亲委派模型
- JVM中的 ClassLoader 通常采用双亲委派模型,要求除了启动类加载器外,其余的类加载器都应该有自己的父级加载器。这里的父子关系是组合而不是继承,工作过程如下:
- 一个类加载器接收到类加载请求后,首先搜索它的内建加载器定义的所有“具名模块”
- 如果找到了合适的模块定义,将会使用该加载器来加载
- 如果 class 没有在这些加载器定义的具名模块中找到,那么将委托给父级加载器,直到启动类加载器
- 如果父级加载器反馈它不能完成加载请求,比如在它的搜索路径下找不到这个类,那子的类加载器才自己来加载
- 在类路径下找到的类将成为这些加载器的无名模块
- 双亲委派模型对于保证 Java 程序的稳定运作很重要,可以避免一个类被加载多次
- 实现双亲委派的代码在 java.lang.ClassLoader 的 loadClass() 方法中,如果自定义类加载器的话,推荐覆盖实现 findClass() 方法
- 如果有一个类加载器能加载某个类,称为 定义类加载器,所有能成功返回该类的 Class 的类加载器 都被称为初始类加载器
8.类连接和初始化
内容总结
以上是互联网集市为您收集整理的JVM(Java虚拟机)知识体系(更新中...)全部内容,希望文章能够帮你解决JVM(Java虚拟机)知识体系(更新中...)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。