第一点可以非常灵活,Class文件可以从ZIP压缩包中读取——JAR,WAR的基础。从网络中获取。运行时动态计算生成。
从加密文件获取
数组对象不通过Class文件生成,由JVM自动生生成。若是引用类型如String[]则通过类加载器加载元素类。若是基本数据类型int[],内置于JVM中,在JVM运行时生成。而非数组类则通过ClassLoader处理。
普通对象的内存分配通过JVM的堆内存进行,JVM在堆上为对象分配内存,并将对象引用保存在栈上或其他对象字段中
数组对象同样在堆中分配内存,多出了一个数字长度字段且在空间上是连续的,有利于快速访问。
目的:确保Class文件中的内容符合《Java虚拟机规范》,这些代码运行后不会危机虚拟机自身的安危。
如是否以魔数开头,主次版本号是否被接收,指向常量池的索引值中是否会指向不存在的常量或不符合类型的常量。。。。
对字节码进行语义分析如这个类是否有父类除(Object),有无继承final修饰的类,非抽象类是否实现了父类或接口中要求实现的方法。。。
重要概念StackMapTable,JDK6后新增存在于Code属性中
StackMapTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_entries;
stack_map_frame entries[number_of_entries];
}
stack_map_frame表示一个栈帧,它有多个变体,常见的栈帧类型包括:
SameFrame:当前帧与前一个帧的局部变量表和操作数栈相同。
SameLocals1StackItemFrame:局部变量表未变化,但操作数栈有一个新的项。
ChopFrame:局部变量表缩短了一些项。
AppendFrame:局部变量表增加了一些项。
它记录了方法执行时,在特定字节码指令的栈帧位置,以便JVM可以快速验证字节码的正确性。
验证原理:在字节码的执行过程中,虚拟机会根据字节码操作调整栈帧的状态,例如iload会从局部变量表加载一个int值并压入操作数栈;iadd操作会从操作数栈弹出两个int值并执行加法运算。
在这其中StackMapTable保证不会将int值当作float来操作,不能将null引用当作对象来操作。通过它,字节码验证器可以跳过详细的计算,直接从中获取栈帧信息,确保操作正确。大大优化了验证流程。
我们打破沙锅问到底。所以StackMapTable中的数据是从哪里来的?什么时候生成的?
其实猜也能猜出来,毕竟现在从一个java文件到真正运行起来也就执行了几步,距离真正运行还差很远。我们的编译器在生成字节码文件时,会进行控制流分析,确定代码执行路径。如if-else,循环,异常处理,方法调用。
发生在虚拟机将符号引用转化为直接引用的时候。这个动作发生在解析连接的第三阶段——解析阶段。符号引用包括:类符号java/lang/Object,字段符号name:Ljava/lang/string;表示字段name类型时string,方法符号methodName(I)V表示一个方法methodName参数类型为Int,返回类型为Void
验证能否通过字符串描述的全限定名找到对应的类。在指定类中是否存在符合方法的字段描述符及简单名称所描述的方法和字段 。符号引用中的类,方法,字段的可访性(privaet/protect/public/<package>)是否可被当前类访问。
常见的验证失败:类不存在:符号引用指向的类在类路径中无法找到,导致ClassNotFoundException
。字段不存在::符号引用中的字段名称或字段描述符不匹配,例如符号引用指向一个int
类型的字段,而类中实际字段类型是String
,则会抛NoSuchFieldError
。
方法不存在:符号引用中的方法名称或方法描述符不匹配,例如符号引用描述的是methodName(int)
方法,但类中实际方法签名是methodName(String)
,则会抛出NoSuchMethodError
将静态变量(static)分配内存并设置类变量初始值。设0,设null。如果被final修饰,在编译时就会直接赋值。
将常量池中的符号引用转化为直接引用的过程。
除了动态invokedynamic指令外,其他的指令在进行符号进行解析请求时,保证如果一个符号引用已经被成功解析过来,那么后面的请求同样要成功,而如果失败了那其他解析请求同样失败。虚拟机会将第一次解析结果进行缓存。
类加载的最后一个阶段。直接来说就是执行类构造器<clinit>方法()的过程。他是javac编译器自动生成的,收集了类中所有类变量的复制动作和静态语句。JVM保证子类的<clinit>执行器父类的<clinit>执行完毕。它不是必要的,如果一个类没有静态语句块和对变量的复制操作,可以不生成。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。