JDK-8323557 : 4.10.1: clarify distinction between types and classes
  • Type: Bug
  • Component: specification
  • Sub-Component: vm
  • Affected Version: 21
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2024-01-11
  • Updated: 2025-06-11
  • Resolved: 2025-06-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 25
25Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
The verification spec speaks of *classes*, which are loaded entities (without a precise specified representation, per 4.10.1), *class names*, which are strings acting as lookup keys used to find classes, and *types*, which sometimes mention class or interface names (of the form 'class(N, L)'), and at other times may be other structures like array types (of the form 'arrayOf(T)').

Unfortunately, the verification rules sometimes blur these three concepts. In particular:

- The type of a field or method reference may be an *array type*, and so must be encoded with a full type, not a name; this saves some effort later on (e.g., in the 'getfield' rules) to construct a class type using the name

- The 'classInterfaces' predicate should be renamed 'classInterfaceNames' to clarify that the result is a list of strings (it appears this doesn't actually get used anywhere currently)

- Use of 'superclassChain' is made unnecessarily complex by operating on a list of types rather than loaded classes

- 'currentClassLoader' unnecessarily creates, and then deconstructs, a type, rather than working directly with the current loaded class

- The 'thisClass' predicate is really 'thisType' and should be renamed; often, an actual 'thisClass' predicate (that produces a class) would be more useful

Comments
The 'instanceMethodInitialThisType' predicate is defined in terms of 'superclassChain', or 'loadedSuperclasses' after the above revisions. This is overkill—all we really need is to ensure that the current class *has* a superclass (i.e., is not Object). Simplified revision: instanceMethodInitialThisType(Class, Method, uninitializedThis) :- isSubclassInstanceInit(Class, Method). instanceMethodInitialThisType(Class, Method, class(ClassName, L)) :- \+ isSubclassInstanceInit(Class, Method), classClassName(Class, ClassName), classDefiningLoader(Class, L). isSubclassInstanceInit(Class, Method) :- methodName(Method, '&init;'), classSuperClassName(Class, _). (Note that 'classSuperClassName' is also how 'superclassChain' and 'loadedSuperclasses' test that they have not reached the 'Object' class.)
20-05-2025

Adjustment to the second 'putfield' rule: checking 'isInit(CurrentMethod)' is unnecessary—we already check that there is an 'uninitializedThis' on the stack. These only exist in <init> methods. Revised edits: instructionIsTypeSafe(putfield(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :- CP = field(~~FieldClassName~~ **FieldClassType**, FieldName, FieldDescriptor), parseFieldDescriptor(FieldDescriptor, FieldType), ~~Environment = environment(CurrentClass, CurrentMethod, _, _, _, _),~~ ~~CurrentClass = class(FieldClassName, _),~~ ~~isInit(CurrentMethod),~~ **thisType(Environment, FieldClassType),** **thisClass(Environment, CurrentClass),** classDeclaresMember(CurrentClass, FieldName, FieldDescriptor), canPop(StackFrame, [FieldType, uninitializedThis], NextStackFrame), exceptionStackFrame(StackFrame, ExceptionStackFrame).
28-02-2025

Conformance testing: I'd suggest some tests that validate the behavior of Fieldrefs and Methodrefs that refer to array types. These should always be allowed by the verifier and usually produce resolution errors (NoSuchFieldError, NoSuchMethodError). A Fieldref to a 'length' field, in particular, should produce a NoSuchFieldError.
14-02-2025

This change reverts JDK-8056119, which claimed to prohibit getfield/putfield on array types. In practice, longstanding HotSpot behavior is for the bytecode to pass verification, eventually throwing a NoSuchFieldError at resolution time.
12-02-2025

Additional bug fix: the 'classesInOtherPkgWithProtectedMember' predicate fails to handle the case in which the next superclass in the list *doesn't* match the MemberClassName. (There is a base case for an empty list, but no "doesn't match, keep going" case.) To add: classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, [Super | Tail], T) :- classClassName(Super, SuperClassName), SuperClassName \= MemberClassName, classesInOtherPkgWithProtectedMember( Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
12-02-2025

Proposed changes are attached, and can be found at https://cr.openjdk.org/~dlsmith/8323557/8323557-20240111/specs/verification-classes-jvms.html
12-01-2024