1.JVM之创建对象源码分析
2.jvm基本常识
3.JVM详解之:HotSpot VM中的源码m源Intrinsic methods
4.Java虚拟机(Java Virtual Machine,简称JVM)
5.JDK、代码JRE、源码m源JVM,代码是源码m源什么关系?
6.什么是Java字节码?
JVM之创建对象源码分析
欢迎探索我的技术分享:《半栈工程师》 对于Java对象的创建,我过去只是代码双号源码编写停留在理论层面,但最近研究HotSpot虚拟机时,源码m源我深入剖析了JVM创建Java对象的代码底层机制。Java对象创建流程详解
首先,源码m源我们从一个简单的代码实例开始,看看如何通过代码创建一个Dog对象: 代码中new Dog()在编译成字节码后,源码m源会变成new #2,代码这里的源码m源new是实例化对象的关键字,#2则指向常量池中的代码Dog类索引。常量池是源码m源类编译后的存储区域,包含了各种符号引用和常量。new指令源码剖析
接下来,我们将深入new指令的源码。虽然涉及汇编代码,但无需立即深入,先了解一下《JVM之模板解释器》会有所帮助。新指令的运行过程如下:从指令中获取类在常量池的索引,存入rdx寄存器,并记录当前指令地址。
获取常量池地址和元素类型数组_tags,用于后续类型检查。
检查元素类型是否为JVM_CONSTANT_Class,如果不是,进入慢速分配。
获取并入栈类的运行时数据结构InstanceKlass,即类的内存地址。
判断类是否已解析,未解析则执行慢速分配,asm.jar源码解析过的进入快速分配。
计算类实例大小并分配内存,首先尝试TLAB区,失败则在Eden区分配。
初始化对象实例数据和对象头。
如果类未解析,执行慢速分配过程。
总结
至此,我们了解了Java对象从创建到初始化的全过程。虽然使用了模板解释器,但理解字节码解释器中的相关方法也是个不错的选择。如果你对HotSpot源码感兴趣,欢迎加入讨论,我的****是wechat:wang_atbeijing。jvm基本常识
JVM基本常识程序的执行方式、字节码和机器码的区别
字节码在JVM中执行,而机器码由硬件直接执行。JVM将源代码编译为字节码,然后解释执行,而机器码直接由处理器执行。
1)如果是sun/oracle JDK 显示信息为:
说明:这表示使用的是由Oracle开发并维护的Java开发工具包。
2)如果OpenJDK, 显示信息为:
说明:这表示使用的是Java开源版本,由SUN和Java社区提供支持。Oracle在年收购SUN后,成为Java的主要维护者。
Java由SUN公司发明,年开源成为OpenJDK。之后Oracle收购SUN,Oracle JDK基于OpenJDK开发,两者在技术上差异不大,Oracle JDK共享大量相同的lua源码分析github代码。
Oracle JDK的来历
Oracle JDK在Oracle收购SUN公司前称为SUN JDK。Oracle收购后,将其命名为Oracle JDK。Oracle JDK基于OpenJDK源代码构建。
Oracle JDK与OpenJDK的区别
Oracle JDK与OpenJDK在技术实现上相似,共享大量相同代码。两者之间的主要区别在于许可证。
JVM和Java的关系
JVM是Java虚拟机规范的实现,用于解释执行字节码。Java语言与JVM紧密相关,Java编译器将源代码转换为字节码,JVM解释执行字节码。
JVM的运行模式
JVM有两种运行模式:Server模式与Client模式。Server模式适合资源密集型应用,Client模式适合轻量级应用。
JVM详解之:HotSpot VM中的Intrinsic methods
内置方法是编译器内置的方法实现,它们在给定编程语言中使用,由编译器专门处理。内置方法通常在程序请求优化时才启用,以提高效率。因为内置方法是在编译器内部实现的,所以不同的虚拟机,其内置方法是不一样的。内置方法可以在Java源代码级别看起来与非内置方法一样,但它们的区别在于JVM的实现。有些方法在普通Java代码中无法实现,如sun.misc.Unsafe.compareAndSwapInt(),只能通过JNI或内置方法来实现,实现对Java语义的扩展。在Hotspot VM中,内置方法通常在src/share/vm/classfile/vmSymbols.hpp类中。通过参数查看代码中调用的知识闯关游戏源码方法是否为内置方法,或者通过底层汇编语言查看。内置方法大部分都是内联方法,通过减少函数调用开销的技术实现。内置方法的实现由三种编译器完成:javac将Java源代码编译成为字节码,在这一层只有数学方法和bootstrapping的MethodHandle实现;JIT的Client Compiler (C1);JIT的Server Compiler (C2)。例如,java.lang.System.currentTimeMillis()方法在Interpreter级别没有intrinsified,因为它是一个native方法,通过JNI调用底层的C++实现。而在C1和C2级别使用intrinsified,直接调用os::javaTimeMillis(),减少JNI的使用,提升效率。内置方法的实现可以通过修改底层的JVM实现完成。Graal是一个用Java编写的JIT编译器,可以使用Java来实现Intrinsic方法,对于不熟悉C++的开发者来说非常友好。通过Graal,内置方法的实现变得简单且容易操作。内置方法是JVM中非常有用的特性,能够显著提高程序效率,是编程时值得考虑的技术之一。
Java虚拟机(Java Virtual Machine,简称JVM)
Java虚拟机(JVM)是Java语言的基础,负责执行Java字节码。它实现跨平台性,使Java程序能在不同硬件和操作系统上运行,无需修改代码。编写的Java源代码生成字节码,JVM加载并执行。提供内存管理、垃圾回收、小白广告制作源码安全性、线程管理等功能,确保程序稳定、安全、兼容。JVM适用于Windows、Linux、macOS等系统,实现代码一次编写,到处运行。
核心功能包括:解释或编译字节码为本地机器代码,实现程序执行;提供丰富的内存管理、安全性和多线程支持,保障程序可靠性和安全性;确保跨平台兼容性,无需针对特定平台修改代码。字节码与不同系统的JVM结合,构成Java语言“一次编译,随处运行”的独特优势。
综上所述,JVM作为Java程序运行的核心,其功能强大,确保了Java语言的跨平台性、稳定性和安全性。它将字节码转换为本地代码,执行程序。通过内存管理、垃圾回收、安全机制和线程管理,确保程序在各种环境下运行顺畅。字节码与不同操作系统上的JVM协同工作,实现了Java程序的“一次编写,到处运行”。
Java虚拟机(JVM)作为Java程序执行的关键,实现跨平台性,确保程序在不同系统上稳定运行。它执行字节码,提供内存管理、垃圾回收、安全和线程支持,保障Java程序的可靠性和兼容性。通过将字节码转换为本地代码,JVM使Java程序能够在Windows、Linux、macOS等操作系统上运行,实现“一次编译,到处运行”的优势。
JDK、JRE、JVM,是什么关系?
在 Java 技术栈中,JDK、JRE、JVM 三者的关系如同金字塔一般,层层相扣,构成了 Java 应用程序运行的基础。
JDK(Java Development Kit)是 Java 开发工具包,包含了 JRE 以及各种开发工具,如编译器、调试器等,用于构建和运行 Java 应用程序。
JRE(Java Runtime Environment)是 Java 运行环境,它包括了 JVM、Java 核心类库以及 Java 标准类库,使得 Java 应用程序可以在没有源代码的情况下在任何支持 JRE 的平台上运行。
JVM(Java Virtual Machine)则是 Java 虚拟机,是 Java 应用程序执行的核心,它将 Java 字节码解释为机器语言,使得 Java 程序可以在不同的硬件和操作系统上运行,实现“一次编写,到处运行”的目标。
谢飞机在面试中对这三个概念的了解显然不够深入,这提醒我们在学习 Java 技术栈时,不仅要了解各组件的基本功能,更要深入理解它们之间的关系和作用机制。
学习 Java 技术栈是一个不断探索和深入的过程,从 JDK、JRE、JVM 的关系入手,可以逐渐建立起对 Java 技术栈的全面理解。同时,学习如何使用这些工具和概念,以及它们在实际开发中的应用,也是提升 Java 开发能力的关键。
什么是Java字节码?
它是程序的一种低级表示,可以运行于Java虚拟机上。将程序抽象成字节码可以保证Java程序在各种设备上的运行
Java号称是一门“一次编译到处运行”的语言,从我们写的java文件到通过编译器编译成java字节码文件(.class文件),这个过程是java编译过程;而我们的java虚拟机执行的就是字节码文件。不论该字节码文件来自何方,由哪种编译器编译,甚至是手写字节码文件,只要符合java虚拟机的规范,那么它就能够执行该字节码文件。
JAVA程序的运行
因为Java具有跨平台特性,为了实现这个特性Java执行在一台虚拟机上,这台虚拟机也就是JVM,Java通过JVM屏蔽了不同平台之间的差异,从而做到一次编译到处执行。JVM位于Java编译器和OS平台之间,Java编译器只需面向JVM,生成JVM能理解的代码,这个代码即字节码,JVM再将字节码翻译成真实机器所能理解的二进制机器码。
字节码是怎么产生的?
我们所编写的程序都是.java格式,通常在执行的时候也许点击一下eclipse的运行键就可以在控制台看到运行结果,但是也可以更酷一些,如果你装了JDK,那就可以直接在以命令行的方式编译运行你的.java文件,编译后会形成.class文件,这个.class文件即字节码。
字节码怎么解读?
上图是编译好的字节码文件,即一堆进制的字节,如果使用IDE去打开,也许看到的是已经被反编译的我们所熟悉的java代码,但这才是纯正的字节码
这里只介绍字节码由哪些部分组成, 具体的意思自行百度或者看文尾的连接, 有较为详细的讲解
上图即字节码文件的组成部分, Class文件的结构不像XML等描述语言那样松散自由。由于它没有任何分隔符号,
所以,以上数据项无论是顺序还是数量都是被严格限定的。哪个字节代表什么含义,长度是多少,先后顺序如何,都不允许改变, 如上图左侧即每一部分规定的长度
魔数(Magic Number)
魔数是用来区分文件类型的一种标志,一般都是用文件的前几个字节来表示。
比如0XCAFE BABE表示的是class文件,那么有人会问,文件类型可以通过文件名后缀来判断啊?是的,但是文件名是可以修改的(包括后缀),那么为了保证文件的安全性,将文件类型写在文件内部来保证不被篡改。
至于为什么是CAFE BABE估计大家也能猜到, 程序员与咖啡的不解之缘
版本号(Version)
版本号含主版本号和次版本号,都是各占2个字节。在此Demo种为0X 。其中前面的是次版本号,后面的是主版本号。通过进制转换得到的是次版本号为0,主版本号为。高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件,即使文件格式未发生任何变化. 这就是target参数的用处,可以在使用JDK 1.7编译时指定-target 1.5
常量池(Constant Pool)
常量池是Class文件中的资源仓库, 量池中主要存储2大类常量:字面量和符号引用。字面量如文本字符串,java中声明为final的常量值等等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符。常量池是一个表结构,在表的内容前有一个类型的计数器,表示常量池的长度
上面的表中描述了中数据类型的结构,其实在jdk1.7之后又增加了3种(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。这样算起来一共是种
访问标志(Access_Flag)
访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。通过上面的源代码,我们知道该文件是类并且是public。
0x :是0×和0×的并集。其中0×这个标志值涉及到字节码指令
类索引(This Class Name)
类索引用于确定类的全限定名
0× 表示引用第3个常量,同时第3个常量引用第个常量,查找得”com/demo/Demo”。#3.#
父类索引(Super Class Name)
0× 同理:#4.#(java/lang/Object)
接口索引(Interfaces)
通过上边字节码图可以看到,这个接口有2+n个字节,前两个字节表示的是接口数量,后面跟着就是接口的表。我们这个类没有任何接口,所以应该是。果不其然,查找字节码文件得到的就是。
字段表集合(fields)
字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的局部变量。接下来就是2+n个字段属性。我们只有一个属性a,所以应该是。查找文件果不其然是。
该区域含有字段的访问标志, 访问权限, 字段的名称索引, 字段的描述符索引, 属性表
描述符的作用就是用来描述字段的数据类型、方法的参数列表和返回值。而属性表就是为字段表和方法表提供额外信息的表结构。对于字段来说,此处如果将字段声明为一个static final msg = "aaa"的常量,则字段后就会跟着一个属性表,其中存在一项名为ConstantValue,指向常量池中的一个常量,值为的"aaa"。
方法(methods)
包含访问标志表, 方法名索引 , 方法描述符索引, 属性表数量,等
Attribute
0× :同样的,表示有1个Attributes了。
0xf : #(“SourceFile”)
0× attribute_length=2
0× : sourcefile_index = #(“Demo.java”)
SourceFile属性用来记录生成该Class文件的源码文件名称。