Sun의 javac에서 생성 된 이상한 예외 테이블 항목
이 프로그램에서 :
class Test {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (NullPointerException npe) {
System.out.println("In catch");
} finally {
System.out.println("In finally");
}
}
}
Sun javac
(v 1.6.0_24)은 다음 바이트 코드를 생성합니다.
public static void main(java.lang.String[]);
// Instantiate / throw NPE
0: new #2; // class NullPointerException
3: dup
4: invokespecial #3; // Method NullPointerException."<init>":()V
7: athrow
// Start of catch clause
8: astore_1
9: getstatic #4; // Field System.out
12: ldc #5; // "In catch"
14: invokevirtual #6; // Method PrintStream.println
17: getstatic #4; // Field System.out
// Inlined finally block
20: ldc #7; // String In finally
22: invokevirtual #6; // Method PrintStream.println
25: goto 39
// Finally block
// store "incomming" exception(?)
28: astore_2
29: getstatic #4; // Field System.out
32: ldc #7; // "In finally"
34: invokevirtual #6; // Method PrintStream.println
// rethrow "incomming" exception
37: aload_2
38: athrow
39: return
다음 예외 테이블이 있습니다.
Exception table:
from to target type
0 8 8 Class NullPointerException
0 17 28 any
28 29 28 any
내 질문은 : 왜 도대체 예외 테이블의 마지막 항목을 포함합니까?!
내가 알고있는 것처럼, 그것은 기본적으로 "라는 (가) 경우 astore_2
예외가 발생, 그것을 잡을와 동일한 명령을 다시 시도하십시오 ."
이러한 항목은 다음과 같은 빈 try / catch / finally 절을 사용해도 생성됩니다.
try {} catch (NullPointerException npe) {} finally {}
일부 관찰
- Eclipse 컴파일러는 이러한 예외 테이블 항목을 생성하지 않습니다.
- JVM은 스펙에 대한 런타임 예외 문서화하지 않는 명령을 .
astore
- I know that it is legal for the JVM to throw
VirtualMachineError
for any instruction. I guess the peculiar entry prevents any such errors from propagating out from that instruction.
There are only two possible explanations: the compiler contains a bug or it's placing a kind of watermark for obscure reasons.
That entry is certainly bogus because any exception thrown by a finally block itself must send execution flow to outer exception handler or finally block, but never "run again" the same finally block.
Also, a good evidence that it's a bug/watermark, is the fact that Eclipse (and perhaps other Java compilers) are not generating such entry, and even so Eclipse-generated classes work fine on Sun's JVM.
That said, this post is interesting because it seems that the class file is valid and verified. If I were a JVM implementor, I would ignore that entry and fill a bug for Sun/Oracle!
Looking at the OpenJDK 7 source code, I would venture to guess the reason for that last 28 29 28 any
exception table entry is because the code that handles the astore
bytecode (see code starting at line 1871) can throw an java.lang.LinkageError
exception if the popped value from the operand stack is not a returnAddress
or reference
type (see the Java Virtual Machine Specification for astore) and they want this error condition to show up on the stack trace.
In the event that there is a bad operand type on the operand stack, the JVM will clear the operand stack (getting rid of that bad operand), put a LinkageError
on the operand stack, and execute the astore
bytecode again, this time successfully executing the astore
bytecode using a JVM provided LinkageError
object reference. See the athrow documentation for more information.
I would greatly suspect the root cause of throwing a LinkageError
during astore
processing is due to the complexities JSR/RET subroutines introduce into bytecode verification (OpenJDK changes 6878713, 6932496 and 7020373 are recent evidence of JSR
's continued complexity; I'm sure Sun/Oracle has other closed source tests that we're not seeing in OpenJDK). The OpenJDK 7020373 change uses LinkageError
to validate/invalidate test results.
My understanding is that the second exception table entry is the implicit catch everything clause added by the compiler to cover any exceptions/errors thrown in the body or the catch handlers and the third entry is the guard on that implicit catch to force the flow through the finally execution.
참고URL : https://stackoverflow.com/questions/6386917/strange-exception-table-entry-produced-by-suns-javac
'developer tip' 카테고리의 다른 글
iframe 콘텐츠 높이를 설정하여 동적으로 자동 크기 조정 (0) | 2020.12.13 |
---|---|
Android AccountManager는 앱 / UID 단위로 OAuth 토큰을 저장하면 안 되나요? (0) | 2020.12.13 |
Google Cloud Endpoints에 대한 커스텀 인증 (OAuth2 대신) (0) | 2020.12.13 |
그렇게 오래 걸리는 Symfony 방화벽은 무엇입니까? (0) | 2020.12.13 |
div 아래 / 뒤의 콘텐츠를 흐리게 할 수 있습니까? (0) | 2020.12.13 |