Java(JVM)中的验证
在 JVM 中的类装入器装入的字节码后。字节码首先被验证器检查有效性,这个过程被称为验证。验证器在链接时执行尽可能多的检查,以便消除解释器在运行时执行的昂贵操作。它提高了翻译的性能。
验证者执行的一些检查:
- 未初始化的变量
- 不违反私有数据和方法的访问规则。
- 方法调用与对象引用匹配。
- 没有操作数堆栈溢出或下溢。
- 所有 Java 虚拟机指令的参数都是有效的类型。
- 确保最终类不被子类化,并且最终方法不被覆盖
- 检查所有字段引用和方法引用是否具有有效的名称、有效的类和有效的类型描述符。(来源)
如果这些检查中的任何一个失败,JVM 都会抛出一个“java.lang.VerifyError”错误。但是,我们可以使用禁用这些检查
java -noverify VerifyGeekFile
人们可能会想,既然编译器在生成之前会检查上述验证,那么程序是如何被操作的。类文件。但是类文件在 JVM 加载之前很容易被更改。类文件中使用的字节码被很好地记录了下来,对十六进制有一些了解的人可以在。类文件从而改变程序的行为。 例如:网络浏览器中的小程序不下载源代码,而是下载预编译的类文件。您计算机上的浏览器决定了这个类文件是否值得运行,或者该文件是否被“恶意编译器”利用。
考虑这个简单的程序
// A Java program to demonstrate working
// of the verification process
class VerifyGeekFile
{
// your initial bank bal
private float bal;
// Method to deposit money
float depositBalance(int bal)
{
int myBal = bal;
this.bal += myBal;
return this.bal;
}
// Driver Method
public static void main(String[] args)
{
VerifyGeekFile obj = new VerifyGeekFile();
System.out.println(obj.depositBalance(4000));
}
}
Output
4000.0
然后在命令行中执行该命令,以助记符的形式查看字节码:-
javap -c VerifyGeekFile
输出:
float depositBalance(int);
Code:
0: iload_1
1: istore_2
2: aload_0
3: dup
4: getfield #2 // Field bal:F
7: iload_2
8: i2f
9: fadd
10: putfield #2 // Field bal:F
13: aload_0
14: getfield #2 // Field bal:F
17: freturn
在这里,如果我们使用十六进制编辑器更改 myBal 的初始值或保持其未初始化,将返回意外的结果。Java 验证过程保护我们免受所有这些陷阱。
参考文献: http://www.informit.com/articles/article.aspx?p=1187967&seqNum = 2 https://docs . Oracle . com/javase/specs/JVMs/se7/html/JVMs-4 . html # JVMs-4.10
版权属于:月萌API www.moonapi.com,转载请注明出处