java 字节码优化,如何处理异常
java bytecode optimization, how to handle exception
考虑以下没有并发访问的 Java class。
class C{
int x;
public void m1(int y){
this.x = y;
m2(y);
}
public void m2(int y){
System.out.println("m2"); <- or anything else that does not affect this.x
}
}
+编辑
由于m1()在y上只有读写关系,那么jit编译器是否可以通过将执行顺序改成如下来优化m1()呢?它会破坏 java 模型一致性吗?
-编辑
public void m1(int y){
m2(y);
this.x = y;
}
如果m1()可以优化,如果m2()在优化后的代码中抛出异常,是否还会执行?
我不明白 javase7 规范,在这种情况下会发生什么?
oracle.com/javase/specs/jvms/se7
A Java Virtual Machine may permit a small but bounded amount of execution to occur before an asynchronous exception is thrown. This delay is permitted to allow optimized code to detect and throw these exceptions at points where it is practical to handle them while obeying the semantics of the Java programming language.
[...]
Exceptions thrown by the Java Virtual Machine are precise: when the
transfer of control takes place, all effects of the instructions
executed before the point from which the exception is thrown must
appear to have taken place. No instructions that occur after the point
from which the exception is thrown may appear to have been evaluated.
If optimized code has speculatively executed some of the instructions
which follow the point at which the exception occurs, such code must
be prepared to hide this speculative execution from the user-visible
state of the program
我了解回滚行为,但我不了解 "not executed" 指令会发生什么。从技术上讲,由于优化而没有 "executed",这是否意味着它永远不会被执行?
您将两个概念放在一起,它们唯一的共同点是您不理解它们。
重新排序是一种优化,绝不允许修改代码执行的结果。因此,问“是否允许 JVM 以破坏代码的方式重新排序此代码?”之类的问题已经过时了。当然不是。唯一可能的是,如果没有适当的同步,结果可能 看起来 以不同的顺序实现到不同的线程。
此外,你应该问问自己为什么这么想
public void m1(int y){
m2(y);
this.x = y;
}
是对
的优化
public void m1(int y){
this.x = y;
m2(y);
}
有什么改进?
您从规范中选择的另一件事是 异步异常,一个仅适用于 two scenarios:
的特殊事情
– The stop method of class Thread or ThreadGroup was invoked, or
– An internal error occurred in the Java Virtual Machine implementation
这些显然是非常特殊的条件,显然不应要求优化代码不断轮询这些条件。引用的段落描述了可以延迟此类异常的情况,但应该清楚这些限制不会解除其他现有限制,即优化可能不会改变执行结果。
换句话说,看着孤立的指令并思考是没有意义的,JVM 没有比将它们洗牌更好的事情了。优化的一般规则是它们不得改变可观察到的效果,我们无法从那个孤立的片段中分辨出您的应用程序中可观察到的内容。例如。如果变量 x
从未被读取,它可能永远不会被写入。甚至可能永远不会创建包含变量 x
的 C
实例,因为不需要它来产生打印该消息的副作用。这都是关于您不会注意到的变化......
考虑以下没有并发访问的 Java class。
class C{
int x;
public void m1(int y){
this.x = y;
m2(y);
}
public void m2(int y){
System.out.println("m2"); <- or anything else that does not affect this.x
}
}
+编辑 由于m1()在y上只有读写关系,那么jit编译器是否可以通过将执行顺序改成如下来优化m1()呢?它会破坏 java 模型一致性吗? -编辑
public void m1(int y){
m2(y);
this.x = y;
}
如果m1()可以优化,如果m2()在优化后的代码中抛出异常,是否还会执行?
我不明白 javase7 规范,在这种情况下会发生什么?
oracle.com/javase/specs/jvms/se7
A Java Virtual Machine may permit a small but bounded amount of execution to occur before an asynchronous exception is thrown. This delay is permitted to allow optimized code to detect and throw these exceptions at points where it is practical to handle them while obeying the semantics of the Java programming language.
[...] Exceptions thrown by the Java Virtual Machine are precise: when the transfer of control takes place, all effects of the instructions executed before the point from which the exception is thrown must appear to have taken place. No instructions that occur after the point from which the exception is thrown may appear to have been evaluated. If optimized code has speculatively executed some of the instructions which follow the point at which the exception occurs, such code must be prepared to hide this speculative execution from the user-visible state of the program
我了解回滚行为,但我不了解 "not executed" 指令会发生什么。从技术上讲,由于优化而没有 "executed",这是否意味着它永远不会被执行?
您将两个概念放在一起,它们唯一的共同点是您不理解它们。
重新排序是一种优化,绝不允许修改代码执行的结果。因此,问“是否允许 JVM 以破坏代码的方式重新排序此代码?”之类的问题已经过时了。当然不是。唯一可能的是,如果没有适当的同步,结果可能 看起来 以不同的顺序实现到不同的线程。
此外,你应该问问自己为什么这么想
public void m1(int y){
m2(y);
this.x = y;
}
是对
的优化public void m1(int y){
this.x = y;
m2(y);
}
有什么改进?
您从规范中选择的另一件事是 异步异常,一个仅适用于 two scenarios:
的特殊事情– The stop method of class Thread or ThreadGroup was invoked, or
– An internal error occurred in the Java Virtual Machine implementation
这些显然是非常特殊的条件,显然不应要求优化代码不断轮询这些条件。引用的段落描述了可以延迟此类异常的情况,但应该清楚这些限制不会解除其他现有限制,即优化可能不会改变执行结果。
换句话说,看着孤立的指令并思考是没有意义的,JVM 没有比将它们洗牌更好的事情了。优化的一般规则是它们不得改变可观察到的效果,我们无法从那个孤立的片段中分辨出您的应用程序中可观察到的内容。例如。如果变量 x
从未被读取,它可能永远不会被写入。甚至可能永远不会创建包含变量 x
的 C
实例,因为不需要它来产生打印该消息的副作用。这都是关于您不会注意到的变化......