source

주석 누락으로 인해 실행 시 ClassNotFoundException이 발생하지 않는 이유는 무엇입니까?

factcode 2022. 9. 4. 14:26
반응형

주석 누락으로 인해 실행 시 ClassNotFoundException이 발생하지 않는 이유는 무엇입니까?

다음 코드를 고려합니다.

A.java:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@interface A{}

C.java:

import java.util.*;

@A public class C {
        public static void main(String[] args){
                System.out.println(Arrays.toString(C.class.getAnnotations()));
        }
}

컴파일 및 실행은 예상대로 작동합니다.

$ javac *.java
$ java -cp . C
[@A()]

하지만 다음 사항을 고려하십시오.

$ rm A.class
$ java -cp . C
[]

던질 줄 ClassNotFoundException부터, syslog@A 하다 묵묵히 을 떨어뜨립니다.대신 주석을 자동으로 삭제합니다.

이 동작은 JLS 어딘가에 문서화되어 있습니까?아니면 Sun의 JVM의 장난입니까?그 근거는 무엇입니까?

게 것 같아요.javax.annotation.Nonnull)@Retention(CLASS)다른 많은 주석의 경우 런타임에 여러 가지 나쁜 일이 발생할 수 있습니다.

JSR-175(주석)에 대한 이전의 공개 초안에서는, 사용법과 주석 선언 사이에 보다 느슨한 결합을 제공하기 위해 컴파일러와 런타임이 알려지지 않은 주석을 무시해야 하는지에 대해 논의되었다.구체적인 예는 EJB에서 애플리케이션 서버별 주석을 사용하여 배치 구성을 제어하는 것입니다.같은 bean을 다른 애플리케이션서버에 전개할 필요가 있는 경우는, NoClassDefFoundError 를 기동하는 대신에, 런타임에 미지의 주석을 무시하기만 하면 편리합니다.

표현이 조금 애매하더라도 JLS 13.5.7에 기재되어 있을 것입니다.주석 삭제는 Java 프로그래밍 언어의 프로그램 바이너리 표현에 대한 올바른 링크에는 영향을 주지 않습니다.나는 이것을 마치 주석이 제거된 것처럼 해석한다(실행시에 사용할 수 없음). 프로그램은 여전히 링크되고 실행되어야 하며, 이것은 알 수 없는 주석이 반사를 통해 접근했을 때 단순히 무시된다는 것을 의미한다.

Sun의 JDK 5의 첫 번째 릴리스에서는 올바르게 구현되지 않았지만 1.5.0_06에서 수정되었습니다.관련된 버그 6322301은 버그 데이터베이스에서 찾을 수 있지만 "JSR-175 스펙 리드선에 따르면 알 수 없는 주석은 getAnnotations에 의해 무시되어야 한다"는 주장 외에는 어떤 사양도 가리키지 않습니다.

JLS 견적:

9.6.1.2 보존 주석은 소스코드에만 존재할 수도 있고 클래스 또는 인터페이스의 이진 형식으로 존재할 수도 있다.바이너리에 있는 주석은 Java 플랫폼의 반사 라이브러리를 통해 런타임에 사용할 수도 있고 사용할 수도 없습니다.

주석 유형 주석입니다.보존은 위의 가능성 중 하나를 선택하기 위해 사용됩니다.주석 a가 유형 T에 대응하고 T에 주석 m에 대응하는 (메타) 주석 m이 있는 경우.유지, 즉:

  • m에 값이 주석인 요소가 있는 경우.Retention Policy(유지 정책)SOURCE를 사용하면 Java 컴파일러는 가 표시되는 클래스 또는 인터페이스의 바이너리 표현에 가 존재하지 않는지 확인해야 합니다.
  • m에 값이 주석인 요소가 있는 경우.Retention Policy(유지 정책)CLASS 또는 주석.Retention Policy(유지 정책)런타임 Java 컴파일러는 m이 로컬 변수 선언에 주석을 달지 않는 한 a가 나타나는 클래스 또는 인터페이스의 바이너리 표현으로 표현되어야 합니다.로컬 변수 선언에 대한 주석은 이진 표현에 유지되지 않습니다.

T에 주석에 해당하는 (메타) 주석 m이 없는 경우.유지, 그러면 Java 컴파일러는 값이 주석인 요소를 가진 메타 주석 m이 있는 것처럼 T를 취급해야 합니다.Retention Policy(유지 정책)학급.

즉, Retention Policy 입니다.RUNTIME은 주석을 바이너리로 컴파일하지만 바이너리에 있는 주석을 런타임에 사용할 수 있어야 할 필요는 없습니다.

실제로 @A라고 쓰여져 있는 코드가 있고, 그 코드에는 클래스 A에 의존하며 ClassNotFoundException이 느려집니다.

그렇지 않은 경우, 즉 @A에 대해 특별히 신경을 쓰는 코드가 없다면 @A는 그다지 중요하지 않다는 것은 논쟁의 여지가 있습니다.

언급URL : https://stackoverflow.com/questions/3567413/why-doesnt-a-missing-annotation-cause-a-classnotfoundexception-at-runtime

반응형