
Java程序的运行机制可以分为以下几个步骤:
编写Java源代码:首先,程序员需要使用Java编程语言编写源代码。Java源代码是以java为扩展名的文本文件,包含了Java程序的逻辑和功能。
编译Java源代码:Java源代码需要通过Java编译器进行编译,生成字节码文件。字节码文件是以class为扩展名的二进制文件,包含了Java程序的指令、变量和方法。
解释执行字节码文件:Java虚拟机(JVM)负责解释执行字节码文件。JVM是一个虚拟的计算机,它模拟了实际计算机的硬件和 *** 作系统,能够运行字节码文件。
类加载:当Java程序被执行时,JVM会根据需要动态加载所需的类。Java类库和自定义类都会被加载到内存中。
执行Java程序:JVM会按照程序的逻辑和功能执行Java程序。程序员可以在程序中使用Java类库和自定义类提供的方法和变量。
垃圾回收:JVM还负责垃圾回收,它会自动回收不再使用的内存空间,防止程序出现内存泄漏等问题。
总的来说,Java程序的运行机制可以概括为:编写源代码 -> 编译生成字节码文件 -> 解释执行字节码文件 -> 加载所需类 -> 执行Java程序 -> 垃圾回收。
loadClass() 方法是加载目标类的入口,它首先会查找当前 ClassLoader 以及它的双亲里面是否已经加载了目标类,如果没有找到就会让双亲尝试加载,如果双亲都加载不了,就会调用 findClass() 让自定义加载器自己来加载目标类。ClassLoader 的 findClass() 方法是需要子类来覆盖的,不同的加载器将使用不同的逻辑来获取目标类的字节码。拿到这个字节码之后再调用 defineClass() 方法将字节码转换成 Class 对象。
自定义类加载器不易破坏双亲委派规则,不要轻易覆盖 loadClass 方法。否则可能会导致自定义加载器无法加载内置的核心类库。在使用自定义加载器时,要明确好它的父加载器是谁,将父加载器通过子类的构造器传入。如果父类加载器是 null,那就表示父加载器是「根加载器」。
先得到对象的类字节码Class对象,通过Class对象再得到类型,而后进行判断是不原始类型方法可能是isPrimitive或数组isArray()。
爪哇是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaEE, JavaME, JavaSE)的总称。
Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。在全球云计算和移动互联网的产业环境下,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文件即字节码。
字节码怎么解读?
上图是编译好的字节码文件,即一堆16进制的字节,如果使用IDE去打开,也许看到的是已经被反编译的我们所熟悉的java代码,但这才是纯正的字节码
这里只介绍字节码由哪些部分组成, 具体的意思自行百度或者看文尾的连接, 有较为详细的讲解
上图即字节码文件的组成部分, Class文件的结构不像XML等描述语言那样松散自由。由于它没有任何分隔符号,
所以,以上数据项无论是顺序还是数量都是被严格限定的。哪个字节代表什么含义,长度是多少,先后顺序如何,都不允许改变, 如上图左侧即每一部分规定的长度
魔数(Magic Number)
魔数是用来区分文件类型的一种标志,一般都是用文件的前几个字节来表示。
比如0XCAFE BABE表示的是class文件,那么有人会问,文件类型可以通过文件名后缀来判断啊?是的,但是文件名是可以修改的(包括后缀),那么为了保证文件的安全性,将文件类型写在文件内部来保证不被篡改。
至于为什么是CAFE BABE估计大家也能猜到, 程序员与咖啡的不解之缘
版本号(Version)
版本号含主版本号和次版本号,都是各占2个字节。在此Demo种为0X0000 0033。其中前面的0000是次版本号,后面的0033是主版本号。通过进制转换得到的是次版本号为0,主版本号为51。高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件,即使文件格式未发生任何变化 这就是target参数的用处,可以在使用JDK 17编译时指定-target 15
常量池(Constant Pool)
常量池是Class文件中的资源仓库, 量池中主要存储2大类常量:字面量和符号引用。字面量如文本字符串,java中声明为final的常量值等等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符。常量池是一个表结构,在表的内容前有一个类型的计数器,表示常量池的长度
上面的表中描述了11中数据类型的结构,其实在jdk17之后又增加了3种(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。这样算起来一共是14种
访问标志(Access_Flag)
访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。通过上面的源代码,我们知道该文件是类并且是public。
0x 00 21:是0×0020和0×0001的并集。其中0×0020这个标志值涉及到字节码指令
类索引(This Class Name)
类索引用于确定类的全限定名
0×00 03 表示引用第3个常量,同时第3个常量引用第19个常量,查找得”com/demo/Demo”。#3#19
父类索引(Super Class Name)
0×00 04 同理:#4#20(java/lang/Object)
接口索引(Interfaces)
通过上边字节码图可以看到,这个接口有2+n个字节,前两个字节表示的是接口数量,后面跟着就是接口的表。我们这个类没有任何接口,所以应该是0000。果不其然,查找字节码文件得到的就是0000。
字段表集合(fields)
字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的局部变量。接下来就是2+n个字段属性。我们只有一个属性a,所以应该是0001。查找文件果不其然是0001。
该区域含有字段的访问标志, 访问权限, 字段的名称索引, 字段的描述符索引, 属性表
描述符的作用就是用来描述字段的数据类型、方法的参数列表和返回值。而属性表就是为字段表和方法表提供额外信息的表结构。对于字段来说,此处如果将字段声明为一个static final msg = "aaa"的常量,则字段后就会跟着一个属性表,其中存在一项名为ConstantValue,指向常量池中的一个常量,值为的"aaa"。
方法(methods)
包含访问标志表, 方法名索引 , 方法描述符索引, 属性表数量,等
Attribute
0×0001 :同样的,表示有1个Attributes了。
0x000f : #15(“SourceFile”)
0×0000 0002 attribute_length=2
0×0010 : sourcefile_index = #16(“Demojava”)
SourceFile属性用来记录生成该Class文件的源码文件名称。
第一种:通过forName()方法;
第二种:类class;
第三种:对象getClass()。
举例如下:
package
test;
public class Demo{
public static void
main(){
Class<> c1 = null;
Class<> c2 =
null;
Class<> c3 =
null;
//三种反射用实例化方式
try{
//最常用的一种形式
c1 =
ClassforName("testX");
}catch(ClassNotFoundException
e){
eprintStackTrace();
}
//通过Object类中的方法实例化
c2
= new X()getClass();
//通过类class实例化
c3 =
Xclass;
Systemoutprintln("类名:" + c1getName());
//得到类名
Systemoutprintln("类名:" + c2getName());
//得到类名
Systemoutprintln("类名:" + c3getName());
//得到类名
}
}
java编程开发是目前市场上使用范围非常广泛的一种编程开发语言。今天我们就一起来了解一下,在java编程中关于字节码的一些指令的编译与执行方法。
java文件编译后的class文件,java跨平台的中间层,JVM通过对字节码的解释执行(执行模式,还有JIT编译执行,下面讲解),屏蔽对 *** 作系统的依赖。一个字节(8位)可以储存256中不同的指令,这样的指令就是字节码,java所有指令有200个左右,这些指令组成了字节码文件(class)。
一、字节码的主要指令:
class文件里面的十六进制文件,其中CAFEBABE是标志这个文件为java的编译后的文件,00000034代表版本号,01670700一个字节(8位)就是一个字节指令,由于数值指令太难看懂,我们可以用javap将指令翻译为助记指令。
1、加载或储存指令
在栈帧中,通过指令 *** 作数据在局部变量表与 *** 作栈间传递。
ILOAD、ALOAD:将int、对象引用类型从局部变量表压入 *** 作栈顶;
ISTORE、ASTORE:将int、对象引用类型从 *** 作栈顶储存到局部变量表里;
ICONST、BIPUSH、SIPUSH、LDC:将常亮加载到 *** 作栈顶。
2、运算指令
对 *** 作栈上的值进行运算,并把结果写入 *** 作栈顶,如IADD、IMUL。
3、类型转换指令
I2L、D2F
4、对象创建与访问指令
NEW
除了字节码指令外,北京电脑培训认为还包括像LINENUMBER储存字节码与源码对应,方便调试定位;LOCALVARIABLE储存当前方法使用到的局部表量表。
二、java源码文件转化为字节码(class)文件的过程
JAVA源文件---------->词法解析---------->语法解析---------->语义分析--------->生成字节码--------->字节码文件
词法分析:根据空格分割出单词、 *** 作符等,形成token信息流;
语法分析:根据token流和java语法规范生成语法树;
语义分析:检查关键字、类型匹配是否正确;
以上就是关于Java程序的运行机制是怎么样的全部的内容,包括:Java程序的运行机制是怎么样的、java无法读取parent字段因为它是空、java怎么判断一个数据是什么类型等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)