- 浏览: 3015497 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
一般我们写Java源码,用Java编译器编译出.class文件,是不会碰到校验失败的状况的,因为正常的Java编译器都会小心对待生成的代码。所以,想要看到校验失败的状况,很容易的一个办法就是自己生成不合法的字节码。
这里我用了ObjectWeb的ASM来生成字节码。可以从官网下载asm-3.1.jar,并保证其在编译和运行下面这个程序时在classpath上。
(本来是很想顺便试试Charles O. Nutter写的bitescript库,不过惰性上来了,懒得去下载……下次吧,下次)
运行该程序后,得到的是TestVerification.class文件,其内容是:
可以看到,foo()里代码先把float类型的常量0.0压到求值栈上(fconst_0),然后将它弹出并保存到局部存储区的第一格(fstore_0)。接下来从局部存储区的第一格取出一个int类型的值压到求值栈上(iload_0),再将其弹出并再次保存到局部存储区的第一格(istore_0)。
要是硬要用Java来表示这个.class文件里的逻辑,大概类似这样:
很明显这没办法用Java表达出来……
上面代码中,局部存储区的第一格就在同一个方法里前后用于保存了float和int类型的值,破坏了类型安全。JVM为了保证类型安全,要求局部存储区里每格在上一次store与下一次load之间只能保存固定类型的值,load/store与对应的格的类型必须匹配;上一次load与下一次store的类型则并不要求一致。
运行这个程序会导致校验错误:
于是JVM的类加载器先抱怨校验失败,然后拒绝加载这个main()方法,后面就连锁抱怨找不到main类。
用JDK8的话在通不过bytecode verification时JVM会报出更详细的错误。可以下载现在的试用版来试试
http://openjdk.java.net/jeps/136
好的,我试试。这样会很方便,哈哈!
用JDK8的话在通不过bytecode verification时JVM会报出更详细的错误。可以下载现在的试用版来试试
http://openjdk.java.net/jeps/136
这里我用了ObjectWeb的ASM来生成字节码。可以从官网下载asm-3.1.jar,并保证其在编译和运行下面这个程序时在classpath上。
(本来是很想顺便试试Charles O. Nutter写的bitescript库,不过惰性上来了,懒得去下载……下次吧,下次)
import java.io.FileOutputStream; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class TestASM implements Opcodes { public static void main(String[] args) throws Exception { ClassWriter cw = new ClassWriter(0); cw.visit( V1_5, // class format version ACC_PUBLIC, // class modifiers "TestVerification", // class name fully qualified name null, // generic signature "java/lang/Object", // super class fully qualified name new String[] { } // implemented interfaces ); MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, // access modifiers "foo", // method name "()V", // method descriptor null, // generic signature null // exceptions ); mv.visitCode(); mv.visitInsn(FCONST_0); mv.visitVarInsn(FSTORE, 1); mv.visitVarInsn(ILOAD, 1); mv.visitVarInsn(ISTORE, 1); mv.visitInsn(RETURN); mv.visitMaxs(1, 2); mv.visitEnd(); // end method cw.visitEnd(); // end class byte[] clz = cw.toByteArray(); FileOutputStream out = new FileOutputStream("TestVerification.class"); out.write(clz); out.close(); } }
运行该程序后,得到的是TestVerification.class文件,其内容是:
public class TestVerification extends java.lang.Object minor version: 0 major version: 49 Constant pool: const #1 = Asciz TestVerification; const #2 = class #1; // TestVerification const #3 = Asciz java/lang/Object; const #4 = class #3; // java/lang/Object const #5 = Asciz foo; const #6 = Asciz ()V; const #7 = Asciz Code; { public void foo(); Code: Stack=1, Locals=2, Args_size=1 0: fconst_0 1: fstore_0 2: iload_0 3: istore_0 4: return }
可以看到,foo()里代码先把float类型的常量0.0压到求值栈上(fconst_0),然后将它弹出并保存到局部存储区的第一格(fstore_0)。接下来从局部存储区的第一格取出一个int类型的值压到求值栈上(iload_0),再将其弹出并再次保存到局部存储区的第一格(istore_0)。
要是硬要用Java来表示这个.class文件里的逻辑,大概类似这样:
public class TestVerification { public void foo() { float a = 0; ((int) a) = a; } }
很明显这没办法用Java表达出来……
上面代码中,局部存储区的第一格就在同一个方法里前后用于保存了float和int类型的值,破坏了类型安全。JVM为了保证类型安全,要求局部存储区里每格在上一次store与下一次load之间只能保存固定类型的值,load/store与对应的格的类型必须匹配;上一次load与下一次store的类型则并不要求一致。
运行这个程序会导致校验错误:
D:\temp_code>java TestVerification Exception in thread "main" java.lang.VerifyError: (class: TestVerification, method: foo signature: ()V) Register 1 contains wrong type Could not find the main class: TestVerification. Program will exit.
于是JVM的类加载器先抱怨校验失败,然后拒绝加载这个main()方法,后面就连锁抱怨找不到main类。
评论
5 楼
changcheng
2013-05-31
RednaxelaFX 写道
changcheng 写道
问题找到了:
23: iload_1 应该使用 aload_1
23: iload_1 应该使用 aload_1
用JDK8的话在通不过bytecode verification时JVM会报出更详细的错误。可以下载现在的试用版来试试
http://openjdk.java.net/jeps/136
好的,我试试。这样会很方便,哈哈!
4 楼
RednaxelaFX
2013-05-23
changcheng 写道
问题找到了:
23: iload_1 应该使用 aload_1
23: iload_1 应该使用 aload_1
用JDK8的话在通不过bytecode verification时JVM会报出更详细的错误。可以下载现在的试用版来试试
http://openjdk.java.net/jeps/136
3 楼
changcheng
2013-05-23
问题找到了:
23: iload_1 应该使用 aload_1
23: iload_1 应该使用 aload_1
2 楼
changcheng
2013-05-23
//==== 补充 javap -c
public void setHSFContainer(java.lang.Object);
Code:
0: ldc #2; //class com/taobao/hsf/log/impl/CallbackComponent
2: ldc #51; //String setHSFContainer
4: ldc #52; //String (Ljava/lang/Object;)V
6: invokestatic #56; //Method com/tb/xman/common/hook/XManMethodCallBack.needHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)Z
9: istore_2
10: iload_2
11: ifeq 29
14: ldc #57; //int 1
16: anewarray #4; //class java/lang/Object
19: astore_3
20: aload_3
21: ldc #58; //int 0
23: iload_1
24: aastore
25: aload_3
26: invokestatic #61; //Method com/tb/xman/common/hook/XManMethodCallBack.beforeMethod:([Ljava/lang/Object;)V
29: aload_0
30: aload_1
31: putfield #20; //Field container:Ljava/lang/Object;
34: invokestatic #23; //Method com/tb/xman/common/hook/XManMethodCallBack.beforeReturn:()V
37: return
public void setHSFContainer(java.lang.Object);
Code:
0: ldc #2; //class com/taobao/hsf/log/impl/CallbackComponent
2: ldc #51; //String setHSFContainer
4: ldc #52; //String (Ljava/lang/Object;)V
6: invokestatic #56; //Method com/tb/xman/common/hook/XManMethodCallBack.needHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)Z
9: istore_2
10: iload_2
11: ifeq 29
14: ldc #57; //int 1
16: anewarray #4; //class java/lang/Object
19: astore_3
20: aload_3
21: ldc #58; //int 0
23: iload_1
24: aastore
25: aload_3
26: invokestatic #61; //Method com/tb/xman/common/hook/XManMethodCallBack.beforeMethod:([Ljava/lang/Object;)V
29: aload_0
30: aload_1
31: putfield #20; //Field container:Ljava/lang/Object;
34: invokestatic #23; //Method com/tb/xman/common/hook/XManMethodCallBack.beforeReturn:()V
37: return
1 楼
changcheng
2013-05-23
//====== asm 生成的代码
public void setHSFContainer(Object container)
{
boolean flag = XManMethodCallBack.needHook(com/tb/hsf/log/impl/CallbackComponent, "setHSFContainer", "(Ljava/lang/Object;)V");
if(flag)
{
Object aobj[] = new Object[1];
aobj[0] = container;
XManMethodCallBack.beforeMethod(aobj);
}
this.container = container;
XManMethodCallBack.beforeReturn();
}
//====== exception:
Exception in thread "main" java.lang.VerifyError: (class: com/tb/hsf/log/impl/CallbackComponent, method: setHSFContainer signature: (Ljava/lang/Object;)V) Register 1 contains wrong type
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
at java.lang.Class.getConstructor0(Class.java:2699)
at java.lang.Class.newInstance0(Class.java:326)
at java.lang.Class.newInstance(Class.java:308)
at com.tb.hsf.container.HSFContainer.initCallbackService(HSFContainer.java:242)
at com.tb.hsf.container.HSFContainer.start(HSFContainer.java:208)
at runjettyrun.Bootstrap.main(Bootstrap.java:220)
这个是什么原因呢?
public void setHSFContainer(Object container)
{
boolean flag = XManMethodCallBack.needHook(com/tb/hsf/log/impl/CallbackComponent, "setHSFContainer", "(Ljava/lang/Object;)V");
if(flag)
{
Object aobj[] = new Object[1];
aobj[0] = container;
XManMethodCallBack.beforeMethod(aobj);
}
this.container = container;
XManMethodCallBack.beforeReturn();
}
//====== exception:
Exception in thread "main" java.lang.VerifyError: (class: com/tb/hsf/log/impl/CallbackComponent, method: setHSFContainer signature: (Ljava/lang/Object;)V) Register 1 contains wrong type
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
at java.lang.Class.getConstructor0(Class.java:2699)
at java.lang.Class.newInstance0(Class.java:326)
at java.lang.Class.newInstance(Class.java:308)
at com.tb.hsf.container.HSFContainer.initCallbackService(HSFContainer.java:242)
at com.tb.hsf.container.HSFContainer.start(HSFContainer.java:208)
at runjettyrun.Bootstrap.main(Bootstrap.java:220)
这个是什么原因呢?
发表评论
-
The Prehistory of Java, HotSpot and Train
2014-06-02 08:18 0http://cs.gmu.edu/cne/itcore/vi ... -
MSJVM and Sun 1.0.x/1.1.x
2014-05-20 18:50 0当年的survey paper: http://www.sym ... -
Sun JDK1.4.2_28有TieredCompilation
2014-05-12 08:48 0原来以前Sun的JDK 1.4.2 update 28就已经有 ... -
IBM JVM notes (2014 ver)
2014-05-11 07:16 0Sovereign JIT http://publib.bou ... -
class data sharing by Apple
2014-03-28 05:17 0class data sharing is implement ... -
Java 8与静态工具类
2014-03-19 08:43 16138以前要在Java里实现所谓“静态工具类”(static uti ... -
Java 8的default method与method resolution
2014-03-19 02:23 10332先看看下面这个代码例子, interface IFoo { ... -
HotSpot Server VM与Server Class Machine
2014-02-18 13:21 0HotSpot VM历来有Client VM与Server V ... -
Java 8的lambda表达式在OpenJDK8中的实现
2014-02-04 12:08 0三月份JDK8就要发布首发了,现在JDK8 release c ... -
GC stack map与deopt stack map的异同
2014-01-08 09:56 0两者之间不并存在包含关系。它们有交集,但也各自有特别的地方。 ... -
HotSpot Server Compiler与data-flow analysis
2014-01-07 17:41 0http://en.wikipedia.org/wiki/Da ... -
字符串的一般封装方式的内存布局 (1): 元数据与字符串内容,整体还是分离?
2013-11-07 17:44 22250(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
关于string,内存布局,C++ std::string,CoW
2013-10-30 20:45 0(Disclaimer:未经许可请 ... -
对C语义的for循环的基本代码生成模式
2013-10-19 23:12 21738之前有同学在做龙书(第二版)题目,做到8.4的练习,跟我对答案 ... -
Java的instanceof是如何实现的
2013-09-22 16:57 0Java语言规范,Java SE 7版 http://docs ... -
oop、klass、handle的关系
2013-07-30 17:34 0oopDesc及其子类的实例 oop : oopDesc* ... -
Nashorn各种笔记
2013-07-15 17:03 0http://bits.netbeans.org/netbea ... -
《深入理解Java虚拟机(第二版)》书评
2013-07-08 19:19 0值得推荐的中文Java虚拟机入门书 感谢作者赠与的样书,以下 ... -
豆列:从表到里学习JVM实现
2013-06-13 14:13 48109刚写了个学习JVM用的豆列跟大家分享。 豆列地址:http: ...
相关推荐
= 保镖 = 字节码校验器 = ByteCode Verifier = 翻译 = 解释执行器 = Interfreter 2:安全 健壮 电力 电信 银行 都会有限考虑使用java实现 3:免费 开源 4:简单 语法简单:c++-- (取其精华 去其糟粕) ...
9.2 字节码校验 9.3 安全管理器与访问权限 9.3.1 Java 平台安全性 9.3.2 安全策略文件 9.3.3 定制权限 9.3.4 实现权限类 9.4 用户认证 9.4.1 JAAS 登录模块 9.5 数字签名 9.5.1 消息摘要 9.5.2 消息签名 9.5.3 X.509...
使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法,截至2016-11-28号,5.3.1是最新版本 新的特性如下: 避免与库类混淆的名称冲突。 带有内部类的泛型签名的固定处理。 固定处理的通用...
如前所述,我是一个狮子座男人,一度我认为学习Java会使我看起来与众不同,可是几个月以后我放弃了这个选择,我看了论坛里关于这两种语言孰优孰劣的讨论,最终选择了C#,请不要问我为何做出这样的选择,很多人认为...
Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...
Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...
/\s+java\s+/ //匹配字符串"java" ,并且该串前后可以有一个或多个空格. /[^"] * / //匹配零个或多个非引号字符. 正则表达式的复制字符 字符 含义 ________________________________________________________...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. ...
在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 ...