Java에서 무엇을 던질 수 있습니까?
기존의 통념에 따르면 ThrowableJava로 확장 되는 객체 만 던질 수 있지만 바이트 코드 검증기를 비활성화하고 Java가 임의의 객체 또는 기본 요소를 던지는 코드를 컴파일하고 실행하도록 할 수 있습니까?
JVM을 찾아 athrow보면 피연산자 스택에 첫 번째 objref가 표시됩니다. 그러나 Throwable런타임에 참조가 a 를 가리키는 지 확인 합니까?
JVM 구현에 따라 다릅니다. Java VM 사양에 따르면 객체가 Throwable.
objectref 는 참조 형식 이어야 하며 Throwable 클래스 또는 Throwable 하위 클래스의 인스턴스 인 개체를 참조해야합니다.
에서 6.1 절, " '에서 꼭'의 의미" :
명령 설명의 일부 제약 ( "반드시"또는 "안됨")이 런타임에 충족되지 않으면 Java 가상 머신의 동작이 정의되지 않습니다.
나는 Jasmin 어셈블러 를 사용하여 테스트 프로그램을 작성했습니다 throw new Object(). Java HotSpot Server VM은 VerifyError다음을 발생 시킵니다 .
# cat Athrow.j
.source Athrow.j
.class public Athrow
.super java/lang/Object
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.end method
.method public static main([Ljava/lang/String;)V
.limit stack 2
new java/lang/Object
dup
invokenonvirtual java/lang/Object/<init>()V
athrow
return
.end method
# java -jar jasmin.jar Athrow.j
Generated: Athrow.class
# java Athrow
Exception in thread "main" java.lang.VerifyError: (class: Athrow, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
바이트 코드 검증기를 비활성화하면를 athrow실행할 수 있으며 JVM이 예외의 세부 정보를 인쇄하려고 할 때 충돌하는 것처럼 보입니다. 이 두 프로그램을 비교하십시오. 첫 번째는를 던지고 Exception두 번째는 Object. 인쇄물 중간에 어떻게 나오는지 확인하십시오.
# java -Xverify:none examples/Uncaught
Exception in thread "main" java.lang.Exception
at examples.Uncaught.main(Uncaught.j)
# java -Xverify:none Athrow
Exception in thread "main" #
물론, 바이트 코드 검증기를 비활성화하는 것은 위험합니다. 적절한 VM은 바이트 코드 확인이 수행되었다고 가정하도록 작성되었으므로 명령어 피연산자를 유형 검사 할 필요가 없습니다. 주의 : 바이트 코드 검증을 우회 할 때 호출하는 정의되지 않은 동작은 C 프로그램의 정의되지 않은 동작과 매우 유사합니다. 코에서 날아 오는 악마를 포함하여 모든 일이 일어날 수 있습니다.
John의 답변에서 언급했듯이 확인을 비활성화하고 (bootclasspath에 클래스를 배치하면 작동해야 함) 비 Throwable클래스를 성공적으로 던지는 클래스를로드하고 실행할 수 있습니다.
놀랍게도 이것이 반드시 충돌로 이어지지는 않습니다!
Throwable암시 적으로 또는 명시 적으로 메서드를 호출하지 않는 한 모든 것이 완벽하게 작동합니다.
.source ThrowObject.j
.class public ThrowObject
.super java/lang/Object
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.end method
.method public static main([Ljava/lang/String;)V
new java/lang/Object
dup
invokenonvirtual java/lang/Object/<init>()V
BeforeThrow:
athrow
AfterThrow:
return
CatchThrow:
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Thrown and catched Object successfully!"
invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V
return
.catch all from BeforeThrow to AfterThrow using CatchThrow
.end method
결과:
% java -Xverify:none ThrowObject
Thrown and catched Object successfully!
[...] disable the bytecode verifier [...]
The bytecode verification is part of the JVM spec, so if you disable this (or tamper with the JVM in other ways), you can, depending on implementation, do just about anything (including throwing primitives etc) I would assume.
Quote from the JVM specification:
The objectref must be of type reference and must refer to an object that is an instance of class Throwable or of a subclass of Throwable.
I.e., your question can be interpreted as "If a JVM deviates from the specification, can it do weird stuff such as throwing primitivs" and the answer is of course, yes.
참고URL : https://stackoverflow.com/questions/5749898/what-can-you-throw-in-java
'Program Club' 카테고리의 다른 글
| y 축 matplotlib에서만 마이너 틱을 켜는 방법 (0) | 2020.12.01 |
|---|---|
| [=]는 모든 지역 변수가 복사된다는 것을 의미합니까? (0) | 2020.12.01 |
| System.DirectoryServices를 사용할 때 언로드 된 appdomain에 액세스하려고했습니다. (0) | 2020.12.01 |
| 파이썬에서 모듈과 라이브러리의 차이점은 무엇입니까? (0) | 2020.12.01 |
| 빌드 경로 Eclipse에 "Maven Managed Dependencies"라이브러리를 추가하는 방법은 무엇입니까? (0) | 2020.11.30 |