大连建站价格,信息流优化师工作内容,北京的做网站的公司,百度指数关键词工具该文章属于Java进阶部分的JVM入门#xff0c;本章讲述了JVM的历史、Java源代码到机器码的过程以及 Class字节码文件的内部结构等。 了解了这篇文章#xff0c;能让你深入地了解JVM知识#xff0c;保证在短时间内掌握JVM#xff01; JVM 入门教程#xff08;上篇#xff0… 该文章属于Java进阶部分的JVM入门本章讲述了JVM的历史、Java源代码到机器码的过程以及 Class字节码文件的内部结构等。 了解了这篇文章能让你深入地了解JVM知识保证在短时间内掌握JVM JVM 入门教程上篇
开篇为什么要学虚拟机 学习Java虚拟机能深入地理解Java这门语言 学习虚拟机是为了线上排查问题打下基础 学会垃圾回收机制等看懂Java虚拟机内存模型看懂GC日志解决线上的Java应用崩溃问题
第 1 讲 Java语言的前世今生
1. JDK 与 JRE JRE 仅包含运行Java程序的必须组件包括Java虚拟机以及Java核心类库等。 JDK 除了包含JRE外还附带了一系列开发、诊断工具。 一般来说如果只需要运行Java程序那么安装JRE即可。但如果要运行Java程序的开发那么就需要安装JDK。
2. JDK 与 J2SE Java SE 是Java三大技术体系的一个。 在1998年JDK1.2发布Java技术体系被拆分为 J2SE、J2EE、J2ME三大体系。 J2SE称之为标准版技术体系它包含了构成Java语言核心的类如数据库连接、网络编程、接口定义等。J2SE技术体系主要用于桌面应用软件的编程。 J2EE称之为企业版技术体系它除了包含J2SE中的类还包含用于开发企业级应用的类如Servle、JSP、EJB等。J2EE技术体系主要用于分布式的网络程序的开发如电子商务网站等。 J2ME称之为嵌入式技术体系它包含J2SE中的一部分类。J2ME技术体系主要用于消费电子产品的软件开发如手机、PDA、寻呼机等。
3. J2SE 与 Java SE J2SE 与 Java SE 其实它们指的是同一个东西只不过在2006年JDK 1.6 发布时讲J2SE、J2EE、J2ME的命名方式改为 Java SE 6、Java EE 6、Java ME 6。
4. Java语言的历史 在 1991 年James Gosling 博士发布了 Oak这个是 Java 语言的前身。但一直到 1995 年的时候Oak 语言才改名为 Java。 1991 年James Gosling 博士发布产品 Oak这是 Java 语言的前身。 1995 年Oak 语言改名为 Java。 1996 年JDK1.0 发布提供了纯解释执行的 Java 虚拟机实现Sun Classic VM。 1997 年JDK1.1 发布代表技术有JDBC、JavaBeans、内部类、反射。 1998 年JDK1.2 发布Java 技术体系被拆分为 J2SE、J2EE、J2ME 三大体系。 2000 年JDK1.3 发布默认的 Java 虚拟机由 Sun Classic VM 改为 HotSopt。 2002 年JDK1.4 发布Java 真正走向成熟代表技术有正则表达式、NIO等。 2004 年JDK1.5 发布对语法易用性做了很大改进新增了泛型、枚举等代表技术有并发包等。 2006 年JDK1.6 发布将 J2EE/J2SE/J2ME 的命名方式改为 Java SE 6、Java EE 6、Java ME 6。 2009 年Sun 公司因为经营不善被 Oracle 公司收购。 2011 年JDK1.7 发布。 2013 年JDK1.8 发布。 …………
5. 总结 这一部分简单地介绍了一些常见概念上地区别以及Java语言的历史让大家对Java语言的发展有一个大致的理解。
第 2 讲 Java虚拟机的历史
1. Sun Classic —— 虚拟机始祖 在 1996 年 1 月 23 日Sun 发布 JDK1.0齐总自带的虚拟机就是Classic VM。但是这款虚拟机有个特点只能使用纯解释器的方式来执行Java代码此时解释器与编译器无法共同存在。到JDK1.4正式退出历史舞台。
2. Sun Exact VM —— 无疾而终 在 JDK1.2 时发布了Exact VM 的虚拟机尝试解决 Classic VM遇到的所有问题它的执行系统解决了Classic VM 存在的编译器和解释器无法同时工作的问题还具备了一些现代高性能处理器的特性如两级即时编译等。 Exact VM 还改进了虚拟机的对象查找方式使用了准确式内存管理即虚拟机可以知道内存中某个位置的数据具体是什么类型这样就减少了查找的开销提升了执行性能。 但可惜的是虽然Exact VM发布了但是直到它退出时都没有被大规模使用过。
3. Sun HotSpot VM —— 武林盟主 HotSpot不仅仅有前面说到两款虚拟机的优点也有许多自己的新技术如热点探测技术。热点探测技术指的是通过执行计数器找出最具优化价值的代码然后通知JIT编译器一方法为单位进行深度优化编译。 从 2000 年JDK1.3发布HotSpot VM作为默认的虚拟机开始登上历史舞台。
4. BEA JRockit / IBM J9 VM —— 百家争鸣 前面说的都是 Sun 公司推出的虚拟机其他组织、公司也研发过不少的虚拟机实现。这里是最著名的。 BEA 公司的 JRockit 是一款专注于服务器硬件和服务端应用场景的虚拟机其针对服务端场景做了大量的优化因此其不太关注程序启动速度。JRockit 虚拟机内部不包含解释器实现全部代码都靠即时编译器编译后执行。此外其提供的 MissionControl 服务套件也十分强大。 IBM 公司的 J9 VM 则是一款比较通用的虚拟机其定位应用于从服务端到桌面应用再到嵌入式的多用途虚拟机。IBM 公司开发 J9 VM 的目的是将其作为 IBM 公司各种 Java 产品的执行平台。
5. 那些无名虚拟机 —— 武林外传 除了上述的这些虚拟机之外其实还有各种各样的虚拟机存在。 例如性能最强悍的并不是上面所说的虚拟机而是名为 Azul VM 和 BEA Liquid VM 的专用商业及虚拟机。这些虚拟机只运行在特定硬件平台因此要求比较高。但其性能也是非常强悍的。其可以管理至少数十个 CPU 和数百 GB 的内存资源还提供在巨大内存范围内实现可控 GC 时间的垃圾收集器等等。 此外还有许许多多其他的虚拟机存在例如Apache Harmony、Google Android Dalvik VM、Mircosoft JVM 等等。 Oracle 看了这么些历史似乎都是在说 Sun公司发布的虚拟机与 Oracle 似乎没有什么关系。但在 2010 年Oracle 公司收购了 Sun 公司这样 Oracle 就拥有了 HotSpot VM。再加上其在 2008 年收购 BEA 公司获得的 JRocket VMOracle 公司就拥有了地球上最优秀的两款虚拟机。 对于虚拟机未来的规划Oracle 宣布会将 JRockit 的优秀特性整合到 HotSpot VM 中例如移植 JRockit 的垃圾回收器和 MissionControl 服务。
第 3 讲 到底什么是虚拟机 为什么不同系统上的软件无法安装这是因为操作系统底层的实现是不一样的。对于Windows系统来说exe后缀的软件代码最终编译成Windows系统能识别的机器码。而Mac OSX 系统来说dmg后缀的软件代码最终编译成 Mac OSX 系统能识别的代码。 与其他语言不同Java语言并不直接讲代码编译成与系统有关的机器码而是编译成一种特定的语言规范这种语言规范我们称之为字节码。无论Java程序要在Windows系统还是Mac OSX系统或者是Linux系统它首先都得编译成字节码文件之后才能运行。 但即使编译成字节码文件了各个系统还是无法明白字节码文件的内容这时就需要Java虚拟机的帮助了。Java虚拟机会解析字节码文件的内容并将其翻译为各操作系统能理解的机器码。 Java虚拟机运行的是字节码文件如果你用php语言写一段代码并自己用特定编译器能生成符合字节码规范的字节码文件那么Java虚拟机也是可以运行的。 简单来说Java虚拟机就是一个字节码翻译器它将字节码文件翻译成各个系统对应的机器码确保字节码文件能在各个系统正确运行。
第 4 讲 对于Java语言从源代码到机器码发生了什么
编译器可以分为前端编译器、JIT编译器和AOT编译器
前端编译器
前端编译器源代码到字节码 对于Java虚拟机来说其实际输入的是字节码文件而不是Java文件。 怎样讲Java代码转化为字节码文件我们知道在JDK的安装目录里有一个javac工具就是它讲Java代码翻译成字节码这个工具我们叫做编译器因为是处于编译前期所以被称为前端编译器。常见的前端编译器有Sun的javacEclipse JDT的增量编译器(ECJ)。 通过javac编译器我们可以很方便地将java源文件翻译成字节码文件。javac编译器解析Java源码并生成字节码文件地过程就是使用javac编译器把Java语言规范转化为字节码语言规范。
javac编译器地处理过程可以分为下面地四个阶段
第一阶段词法、语法分析
javac编译器会对源代码地字符进行一次扫描最终生成一个抽象地语法树。
第二阶段填充符号表
对抽象地类或接口进行符号填充等到类加载阶段javac编译器会将符号替换成具体地内存地址。
第三个阶段注解处理
Java是支持注解地因此在这个阶段会对注解进行分析根据注解地作用将其还原成具体的指令集。
第四个阶段分析与字节码生成
javac编译器会根据上面几个阶段分析出来的结果进行字节码的生成最终输出为class文件。
JIT编译器(即时编译器) JIT编译器从字节码到机器码 当源代码转化为字节码后其实要运行程序有两种选择 一种是Java解释器解释执行字节码另一种则是使用JIT编译器将字节码转化为本地机器代码。 两者区别在于前者启动速度快但运行速度慢后者启动速度慢但运行速度快。 在HotSpot虚拟机内置了两个即时编译器分别为Client Compiler和Server Compiler。 这两种不同的编译器衍生出两种不同的编译模式我们分别称之为C1编译模式、C2编译模式(非官方说法)。
C1编译模式和C2编译模式的区别 C1编译模式会将字节码编译为本地代码进行简单、可靠的优化如有必要将加入性能监控的逻辑。优化相对比较保守比C2较快。 而C2编译模式也是将字节码编译为本地代码但是会启用一些编译耗时较长的优化甚至会根据性能监控信息进行一些不可靠的激进优化。C2的编译质量相对较好但耗时更长。
对于HotSpot虚拟机有三种运行模式可选 混合模式 C1和C2两种模式混合起来使用这是默认的运行模式如果想单独使用C1模式或C2模式使用 -client 或 -server 打开即可。 解释模式 所有代码都解释执行使用 -Xint 参数可以打开这个模式。 编译模式 此模式优先采用编译但是无法编译时也会解释执行使用 -Xcomp 打开这种模式。
此时我们了解了从Java源代码到字节码再从字节码到机器码的全过程可以到这里就结束了。但是Java中还有一个AOT编译器它能直接将源代码转换为机器码。
AOT编译器 AOT编译器源代码到机器码 AOT编译器的基本思想是在程序执行前生成Java方法的本地代码以便在程序运行时直接使用本地代码也就是在进入JVM之前就已经将本地机器码生成了。 优点 启动速度快减少运行时的开销 限制 由于缺乏运行时信息AOT编译质量也就是优化效果通常不如JIT编译。 Java的动态类加载等特性可能会增加AOT编译的复杂性。
总结 在JVM中有三个非常重要的编译器它们分别是前端编译器、JIT编译器、AOT编译器。 前端编译器最常见的是javac编译器将Java源代码编译为Java字节码文件。 JIT编译器(即时编译器)最常见的是HotSpot虚拟机中的Client Compiler和 Server Compiler将Java字节码编译成本地机器代码。 AOT编译器能将源代码直接编译为本地机器码。
编译速度和编译质量上的区别 编译速度上解释执行AOT编译器JIT编译器 编译质量上JIT编译器AOT编译器解释执行。
而在JVM中通过这几种不同方式的配合使得JVM的编译质量和运行速度达到最优的状态。
第 5 讲 字节码文件结构
《Java虚拟机规范》规定了Java虚拟机结构、Class类文件结构、字节码指令等内容。 字节码文件结构是一组以8位字节为基础的二进制流各数据项目严格按照顺序紧凑地排列在Class文件之中中间没有添加任何分隔符。 在字节码结构中有两种最基本的数据类型来表示字节码文件格式分别是无符号数和表。
无符号数 无符号数属于最基本的数据类型。它以u1、u2、u4、u8分别代表1个字节、2个字节、4个字节、8个字节的无符号数。 无符号数可以用来描述数字、索引引用、数量或者按照UTF-8编码构成的字符串值。
表 表是由多个无符号数或者其他表作为数据项构成的复合数据类型。
一个Class字节码文件的格式内容 magic: 魔数固定为0xCAFEBABE用于标识这是一个Java Class文件。 minor_version 和 major_version: 分别表示Class文件的次版本号和主版本号。 constant_pool_count: 常量池中常量的数量。 constant_pool: 常量池存储了类中用到的所有常量包括字符串、类名、方法名等。这里除了基本类型和UTF-8的字符串存储的是值外其他的都是存储的索引。 access_flags: 访问标志标识类或接口的访问权限和属性如public, final, abstract等。 如这个Class是类还是接口、是否定义位public类型、是否定义为abstract类型等。标志值可以通过相加来叠加。 this_class: 当前类的索引确定这个类的全限定名指向常量池中的一个项。 super_class: 父类的索引确定这个类的父类的全限定名指向常量池中的一个项。 interfaces_count 和 interfaces: 接口的数量和接口列表。Class文件中由this_class、super_class、interfaces_count这三项数据来确定这个类的继承关系。 fields_count 和 fields: 字段的数量和字段列表。 methods_count 和 methods: 方法的数量和方法列表。 attributes_count 和 attributes: 属性的数量和属性列表。