-
Enhancement
-
Resolution: Fixed
-
P4
-
7
-
None
-
Verified
JVMS7 defines EnclosingMethod.method_index as: "If the current class is not immediately enclosed by a method or constructor, then the value of the method_index item must be zero."
The term "method" in the JVMS would usually include specially-named methods like <init> and <clinit>. It seems fair to say that a local class declared in an instance initializer or static initializer can be thought of as being "immediately enclosed" by <init> or <clinit> respectively, since instance initializers and static initializers compile to <init> and <clinit> respectively. Similarly, it seems fair to say that an anonymous class declared in an instance variable initializer or a class variable initializer can be thought of as being "immediately enclosed" by <init> or <clinit> respectively.
However, this is not the intent of method_index. The appearance of "constructor" indicates that JLS concepts are in effect. "method or constructor" means "the declaration of a method or constructor in source code". Consider the difference between initializers on the one hand and constructors/methods on the other:
- A local class declared in an instance initializer, or an anonymous class declared in an instance variable initializer, is not declared in a constructor. The JVM cannot distinguish an instance initializer or instance variable initializer from a constructor - they're mashed together in <init> - but Core Reflection wishes to distinguish local/anon-class-in-initializer (method_index==0) from local/anon-class-in-constructor (method_index==1).
- A local class declared in a static initializer, or an anonymous class declared in a class variable initializer, is not declared in a method in source terms, even though the JVM sees all static initializers/class variable initializers mashed into the <clinit> method in the class file.
It would be clearer if method_index had a positive condition based on the API spec for Class#getEnclosingMethod/Constructor: "If the current class was immediately enclosed by a type declaration, instance initializer, or static initializer in source code, then the value of the method_index item must be zero. (A class is immediately enclosed by a type declaration if the class is declared anonymously in an instance variable initializer or class variable initializer, i.e. on the right hand side of a field assignment.)"
The term "method" in the JVMS would usually include specially-named methods like <init> and <clinit>. It seems fair to say that a local class declared in an instance initializer or static initializer can be thought of as being "immediately enclosed" by <init> or <clinit> respectively, since instance initializers and static initializers compile to <init> and <clinit> respectively. Similarly, it seems fair to say that an anonymous class declared in an instance variable initializer or a class variable initializer can be thought of as being "immediately enclosed" by <init> or <clinit> respectively.
However, this is not the intent of method_index. The appearance of "constructor" indicates that JLS concepts are in effect. "method or constructor" means "the declaration of a method or constructor in source code". Consider the difference between initializers on the one hand and constructors/methods on the other:
- A local class declared in an instance initializer, or an anonymous class declared in an instance variable initializer, is not declared in a constructor. The JVM cannot distinguish an instance initializer or instance variable initializer from a constructor - they're mashed together in <init> - but Core Reflection wishes to distinguish local/anon-class-in-initializer (method_index==0) from local/anon-class-in-constructor (method_index==1).
- A local class declared in a static initializer, or an anonymous class declared in a class variable initializer, is not declared in a method in source terms, even though the JVM sees all static initializers/class variable initializers mashed into the <clinit> method in the class file.
It would be clearer if method_index had a positive condition based on the API spec for Class#getEnclosingMethod/Constructor: "If the current class was immediately enclosed by a type declaration, instance initializer, or static initializer in source code, then the value of the method_index item must be zero. (A class is immediately enclosed by a type declaration if the class is declared anonymously in an instance variable initializer or class variable initializer, i.e. on the right hand side of a field assignment.)"