Copyright © 2017 Oracle America, Inc. Legal Notice.
This document proposes changes to the Java Virtual Machine Specification to allow access to private
class members from related "nestmate" classes. See JEP 181 for an overview.
There are two major changes:
Introducing the NestMembers
and MemberOfNest
attributes, and specifying how they should be validated. Modifying the accessibility rules so that private
members within a nest can be referenced.
invokespecial
so that private
methods can be referenced outside of the current class and its supertypes. Accompanied by cleanups in the treatment of protected
members, mainly for improved presentation....
Note that superclass methods called using the invokespecial
instruction always pass this
to the invoked method as its first argument. As usual, it is received in local variable 0.
This assertion is wrong about private
methods: it has always been allowed to invoke a private
method of a different class instance (an object other than this
). Further, now a private
method of a different class can be invoked directly in the bytecode.
...
Attributes are used in the ClassFile
, field_info
, method_info
, and Code_attribute
structures of the class
file format (4.1, 4.5, 4.6, 4.7.3).
All attributes have the following general format:
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
For all attributes, the attribute_name_index
must be a valid unsigned 16-bit index into the constant pool of the class. The constant_pool
entry at attribute_name_index
must be a CONSTANT_Utf8_info
structure (4.4.7) representing the name of the attribute. The value of the attribute_length
item indicates the length of the subsequent information in bytes. The length does not include the initial six bytes that contain the attribute_name_index
and attribute_length
items.
23 25 attributes are predefined by this specification. They are listed three times, for ease of navigation:
Table 4.7-A is ordered by the attributes' section numbers in this chapter. Each attribute is accompanied by the first version of the class
file format in which it was defined, and the corresponding version of the Java SE platform. (For old class
file versions, the JDK release is used instead of the Java SE platform version).
Table 4.7-B is ordered by the first version of the class
file format in which each attribute was defined.
Table 4.7-C is ordered by the location in a class
file where each attribute is defined to appear.
Within the context of their use in this specification, that is, in the attributes
tables of the class
file structures in which they appear, the names of these predefined attributes are reserved.
Any conditions on the presence of a predefined attribute in an attributes
table are specified explicitly in the section which describes the attribute. If no conditions are specified, then the attribute may appear any number of times in an attributes
table.
The predefined attributes are categorized into three groups according to their purpose:
Five Six attributes are critical to correct interpretation of the class
file by the Java Virtual Machine:
ConstantValue
Code
StackMapTable
Exceptions
BootstrapMethods
NestMembers
MemberOfNest
In a class
file of version V, each of these attributes must be recognized and correctly read by an implementation of the Java Virtual Machine if the implementation recognizes class
files of version V, and V is at least the version where the attribute was first defined, and the attribute appears in a location where it is defined to appear.
The Exceptions
attribute merely lists the declared throws
clause of a method. This feature is specific to the Java language, and (I believe?) doesn't impact JVM behavior at all.
Twelve Thirteen attributes are critical to correct interpretation of the class
file by the class libraries of the Java SE platform:
Exceptions
InnerClasses
EnclosingMethod
Synthetic
Signature
RuntimeVisibleAnnotations
RuntimeInvisibleAnnotations
RuntimeVisibleParameterAnnotations
RuntimeInvisibleParameterAnnotations
RuntimeVisibleTypeAnnotations
RuntimeInvisibleTypeAnnotations
AnnotationDefault
MethodParameters
Each of these attributes in a class
file of version V must be recognized and correctly read by an implementation of the class libraries of the Java SE platform if the implementation recognizes class files of version V, and V is at least the version where the attribute was first defined, and the attribute appears in a location where it is defined to appear.
Six attributes are not critical to correct interpretation of the class
file by either the Java Virtual Machine or the class libraries of the Java SE platform, but are useful for tools:
SourceFile
SourceDebugExtension
LineNumberTable
LocalVariableTable
LocalVariableTypeTable
Deprecated
Use of these attributes by an implementation of the Java Virtual Machine or the class libraries of the Java SE platform is optional. An implementation may use the information that these attributes contain, or otherwise must silently ignore these attributes.
Table 4.7-A. Predefined class
file attributes (by section)
Attribute | Section | class file |
Java SE |
---|---|---|---|
ConstantValue |
4.7.2 | 45.3 | 1.0.2 |
Code |
4.7.3 | 45.3 | 1.0.2 |
StackMapTable |
4.7.4 | 50.0 | 6 |
Exceptions |
4.7.5 | 45.3 | 1.0.2 |
InnerClasses |
4.7.6 | 45.3 | 1.1 |
EnclosingMethod |
4.7.7 | 49.0 | 5.0 |
Synthetic |
4.7.8 | 45.3 | 1.1 |
Signature |
4.7.9 | 49.0 | 5.0 |
SourceFile |
4.7.10 | 45.3 | 1.0.2 |
SourceDebugExtension |
4.7.11 | 49.0 | 5.0 |
LineNumberTable |
4.7.12 | 45.3 | 1.0.2 |
LocalVariableTable |
4.7.13 | 45.3 | 1.0.2 |
LocalVariableTypeTable |
4.7.14 | 49.0 | 5.0 |
Deprecated |
4.7.15 | 45.3 | 1.1 |
RuntimeVisibleAnnotations |
4.7.16 | 49.0 | 5.0 |
RuntimeInvisibleAnnotations |
4.7.17 | 49.0 | 5.0 |
RuntimeVisibleParameterAnnotations |
4.7.18 | 49.0 | 5.0 |
RuntimeInvisibleParameterAnnotations |
4.7.19 | 49.0 | 5.0 |
RuntimeVisibleTypeAnnotations |
4.7.20 | 52.0 | 8 |
RuntimeInvisibleTypeAnnotations |
4.7.21 | 52.0 | 8 |
AnnotationDefault |
4.7.22 | 49.0 | 5.0 |
BootstrapMethods |
4.7.23 | 51.0 | 7 |
MethodParameters |
4.7.24 | 52.0 | 8 |
NestMembers |
4.7.25 | 54.0 | 10 |
MemberOfNest |
4.7.26 | 54.0 | 10 |
Table 4.7-B. Predefined class
file attributes (by class
file version)
Attribute | class file |
Java SE | Section |
---|---|---|---|
ConstantValue |
45.3 | 1.0.2 | 4.7.2 |
Code |
45.3 | 1.0.2 | 4.7.3 |
Exceptions |
45.3 | 1.0.2 | 4.7.5 |
SourceFile |
45.3 | 1.0.2 | 4.7.10 |
LineNumberTable |
45.3 | 1.0.2 | 4.7.12 |
LocalVariableTable |
45.3 | 1.0.2 | 4.7.13 |
InnerClasses |
45.3 | 1.1 | 4.7.6 |
Synthetic |
45.3 | 1.1 | 4.7.8 |
Deprecated |
45.3 | 1.1 | 4.7.15 |
EnclosingMethod |
49.0 | 5.0 | 4.7.7 |
Signature |
49.0 | 5.0 | 4.7.9 |
SourceDebugExtension |
49.0 | 5.0 | 4.7.11 |
LocalVariableTypeTable |
49.0 | 5.0 | 4.7.14 |
RuntimeVisibleAnnotations |
49.0 | 5.0 | 4.7.16 |
RuntimeInvisibleAnnotations |
49.0 | 5.0 | 4.7.17 |
RuntimeVisibleParameterAnnotations |
49.0 | 5.0 | 4.7.18 |
RuntimeInvisibleParameterAnnotations |
49.0 | 5.0 | 4.7.19 |
AnnotationDefault |
49.0 | 5.0 | 4.7.22 |
StackMapTable |
50.0 | 6 | 4.7.4 |
BootstrapMethods |
51.0 | 7 | 4.7.23 |
RuntimeVisibleTypeAnnotations |
52.0 | 8 | 4.7.20 |
RuntimeInvisibleTypeAnnotations |
52.0 | 8 | 4.7.21 |
MethodParameters |
52.0 | 8 | 4.7.24 |
NestMembers |
54.0 | 10 | 4.7.25 |
MemberOfNest |
54.0 | 10 | 4.7.26 |
Table 4.7-C. Predefined class
file attributes (by location)
Attribute | Location | class file |
---|---|---|
SourceFile |
ClassFile |
45.3 |
InnerClasses |
ClassFile |
45.3 |
EnclosingMethod |
ClassFile |
49.0 |
SourceDebugExtension |
ClassFile |
49.0 |
BootstrapMethods |
ClassFile |
51.0 |
NestMembers |
ClassFile |
54.0 |
MemberOfNest |
ClassFile |
54.0 |
ConstantValue |
field_info |
45.3 |
Code |
method_info |
45.3 |
Exceptions |
method_info |
45.3 |
RuntimeVisibleParameterAnnotations , RuntimeInvisibleParameterAnnotations |
method_info |
49.0 |
AnnotationDefault |
method_info |
49.0 |
MethodParameters |
method_info |
52.0 |
Synthetic |
ClassFile , field_info , method_info |
45.3 |
Deprecated |
ClassFile , field_info , method_info |
45.3 |
Signature |
ClassFile , field_info , method_info |
49.0 |
RuntimeVisibleAnnotations , RuntimeInvisibleAnnotations |
ClassFile , field_info , method_info |
49.0 |
LineNumberTable |
Code |
45.3 |
LocalVariableTable |
Code |
45.3 |
LocalVariableTypeTable |
Code |
49.0 |
StackMapTable |
Code |
50.0 |
RuntimeVisibleTypeAnnotations , RuntimeInvisibleTypeAnnotations |
ClassFile , field_info , method_info , Code |
52.0 |
NestMembers
AttributeThe NestMembers
attribute is a variable-length attribute in the attributes
table of a ClassFile
structure (4.1). It defines a nest, a set of classes and interfaces that share access to private
members (5.4.4). A class with a NestMembers
attribute is the host class of the nest.
There may be at most one NestMembers
attribute in the attributes
table of a ClassFile
structure.
The NestMembers
attribute has the following format:
NestMembers_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_classes;
u2 classes[number_of_classes];
}
The items of the NestMembers_attribute
structure are as follows:
attribute_name_index
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "NestMembers"
.
attribute_length
The value of the attribute_length
item indicates the length of the attribute, excluding the initial six bytes.
number_of_classes
The value of the number_of_classes
item indicates the number of entries in the classes array.
classes[]
Each value in the classes
array must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class or interface.
MemberOfNest
AttributeThe MemberOfNest
attribute is a fixed-length attribute in the attributes
table of a ClassFile
structure (4.1). A class or interface with a MemberOfNest
attribute claims membership in a nest hosted by the referenced class or interface (4.7.25).
There may be at most one MemberOfNest
attribute in the attributes
table of a ClassFile
structure.
The attributes
table of a ClassFile
structure must not contain both a MemberOfNest
attribute and a NestMembers
attribute.
If the attributes
table of a ClassFile
structure does not contain a MemberOfNest
attribute, the class is implicitly a member of its own nest (5.4.4).
The MemberOfNest
attribute has the following format:
MemberOfNest_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 host_class_index;
}
The items of the MemberOfNest_attribute
structure are as follows:
attribute_name_index
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "MemberOfNest"
.
attribute_length
The value of the attribute_length
item must be two.
host_class_index
The value of the host_class_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class or interface.
The structural constraints on the code array specify constraints on relationships between Java Virtual Machine instructions. The structural constraints are as follows:
...
Each invokespecial
instruction must name an instance initialization method (2.9), a method in the current class or interface, a method in a superclass of the current class, a method in a direct superinterface of the current class or interface, or a method in Object
.
When an instance initialization method is invoked If an invokespecial
instruction names an instance initialization method, an uninitialized class instance must be in an appropriate position on the operand stack. An instance initialization method must never be invoked on an initialized class instance.
If an invokespecial
instruction names an instance initialization method and the target reference on the operand stack is an uninitialized class instance for the current class, then invokespecial
must name an instance initialization method from the current class or its direct superclass.
If an invokespecial
instruction names an instance initialization method and the target reference on the operand stack is a class instance created by an earlier new
instruction, then invokespecial
must name an instance initialization method from the class of that class instance.
If an invokespecial
instruction names a method which is not an instance initialization method, then the type of the target reference on the operand stack must be assignment compatible with the current class (JLS 5.2).
If invokespecial
is used to invoke a non-private
, non-<init>
method, referenced via a superclass or a direct superinterface, then the type of the class instance being accessed must be assignable to the current class or interface.
These deleted assertions about invokespecial
instructions no longer apply to private
methods, so can't be asserted in general.
Like an invokevirtual
of a protected
method, we want to guarantee that any invokespecial
of a non-private
, non-<init>
method occurs via a receiver of the current class's type. There are five cases:
<init>
: the restriction does not apply.private
, and if not, test the receiver type.private
, this triggers an error (invokespecial
)....
If getfield
or putfield
is used to access a protected
field declared referenced in a superclass that is a member of a different run-time package than the current class or interface, then the type of the class instance being accessed must be the same as or a subclass of assignable to the current class or interface.
If invokevirtual
or is used to access a invokespecial
protected
method declared referenced in a superclass that is a member of a different run-time package than the current class or interface, then the type of the class instance being accessed must be the same as or a subclass of assignable to the current class or interface.
Some cleanups here for consistency with the actual verification rules:
Verification uses the referenced class name, not the declaring class of the method, to determine whether the check can be applied.
Object.clone
. (This has always been a possibility, and it's best to be explicit about it.)...
class
Files...
In both strategies, verification is mainly concerned with enforcing the static and structural constraints from 4.9 on the code
array of the Code
attribute (4.7.3). However, there are four additional checks outside the Code
attribute which must be performed during verification:
final
classes are not subclassed.final
methods are not overridden (5.4.5).Object
) has a direct superclass.MemberOfNest
attribute names a host class from the same package that has a matching NestMembers
entry.There are at least three options for checking NestMembers
and MemberOfNest
attributes:
Report an error during class loading, at the same time supertypes and superinterfaces are loaded and checked (5.3, 5.3.5).
Report an error during verification, at the same time final
subclassing is checked (5.4.1, 4.10).
Report an error during resolution when an attempted access of a private
member occurs.
We opt to use the second approach here to ensure a MemberOfNest
attribute always references a host class in its same package with a supporting NestMembers
attribute.
We opt to use the third approach when a NestMembers
attribute lists a class that does not have a supporting MemberOfNest
attribute (5.4.4): both the host class and the claimed member class will load and link without error, and an error will only occur when another nest member attempts to access a private
member. This allows verification to proceed without loading every class mentioned by a NestMembers
attribute.
...
A class is type safe if all its methods are type safe, and it does not subclass a final
class, and if it claims to belong to a nest, the referenced host class is in the same package and includes the class in its list of nest members.
classIsTypeSafe(Class) :-
classClassName(Class, Name),
classDefiningLoader(Class, L),
superclassChain(Name, L, Chain),
Chain = [],
classSuperClassName(Class, SuperclassName),
loadedClass(SuperclassName, L, Superclass),
classIsNotFinal(Superclass),
classHasValidNest(Class),
classMethods(Class, Methods),
checklist(methodIsTypeSafe(Class), Methods).
classIsTypeSafe(Class) :-
classClassName(Class,
'java/lang/Object'
),
classDefiningLoader(Class, L),
isBootstrapLoader(L),
classHasValidNest(Class),
classMethods(Class, Methods),
checklist(methodIsTypeSafe(Class), Methods).
The Prolog predicate classIsTypeSafe assumes that Class is a Prolog term representing a binary class that has been successfully parsed and loaded. This specification does not mandate the precise structure of this term, but does require that certain predicates be defined upon it.
For example, we assume a predicate classMethods(Class, Methods) that, given a term representing a class as described above as its first argument, binds its second argument to a list comprising all the methods of the class, represented in a convenient form described later.
Iff the predicate classIsTypeSafe is not true, the type checker must throw the exception VerifyError
to indicate that the class
file is malformed. Otherwise, the class file has type checked successfully and bytecode verification has completed successfully.
The classHasValidNest predicate checks the MemberOfNest
attribute of a class, as follows:
classHasValidNest(Class) :-
\+ classMemberOfNestName(Class, _).
classHasValidNest(Class) :-
classMemberOfNestName(Class, HostName),
classDefiningLoader(Class, L1),
loadedClass(HostName, L1, HostClass),
samePackageName(Class, HostClass),
classClassName(Class, Name),
classNestMemberNames(HostClass, MemberNames),
member(Name, MemberNames),
classDefiningLoader(HostClass, L2),
loadedClass(Name, L2, Class).
The rest of this section explains the process of type checking in detail:
...
We stipulate the existence of 31 Prolog predicates ("accessors") that have certain expected behavior but whose formal definitions are not given in this specification.
Extracts the name, ClassName, of the class Class.
True iff the class, Class, is an interface.
True iff the class, Class, is not a final
class.
Extracts the name, SuperClassName, of the superclass of class Class.
Extracts a list, InterfaceNames, of the names of the direct superinterfaces of the class Class.
Extracts a list, Methods, of the methods declared in the class Class.
Extracts a list, MemberNames, of the nest members identified by a NestMembers
attribute of the class Class (4.7.25).
Extracts the name, HostClassName, of the host class identified by a MemberOfNest
attribute of the class Class (4.7.26).
Extracts a list, Attributes, of the attributes of the class Class.
Each attribute is represented as a functor application of the form attribute(AttributeName, AttributeContents), where AttributeName is the name of the attribute. The format of the attribute's contents is unspecified.
This predicate is never used.
Extracts the defining class loader, Loader, of the class Class.
True iff the class loader Loader is the bootstrap class loader.
True iff there exists a class named Name whose representation (in accordance with this specification) when loaded by the class loader InitiatingLoader is ClassDefinition.
Applies loadedClass to a list of class names.
Extracts the name, Name, of the method Method.
Extracts the access flags, AccessFlags, of the method Method.
Extracts the descriptor, Descriptor, of the method Method.
Extracts a list, Attributes, of the attributes of the method Method.
Each attribute is represented as a functor application of the form attribute(AttributeName, AttributeContents), where AttributeName is the name of the attribute. The format of the attribute's contents is unspecified.
True iff Method (regardless of class) is named <init>
.
True iff Method (regardless of class) is not named <init>
.
True iff Method in class Class is not final
.
True iff Method in class Class is static
.
True iff Method in class Class is not static
.
True iff Method in class Class is private
.
True iff Method in class Class is not private
.
True iff there is a member named MemberName with descriptor MemberDescriptor in the class MemberClass and it is protected
.
True iff there is a member named MemberName with descriptor MemberDescriptor in the class MemberClass and it is not protected
.
True iff Member in class Class is protected
.
True iff Member in class Class is not protected
.
Given a symbolic reference to a field or method in class ReferencedClass named MemberName with descriptor MemberDescriptor, identifies the field or method Member declared in class DeclaringClass that would be produced by the resolution algorithm of 5.4.3.2, 5.4.3.3, or 5.4.3.4.
Converts a field descriptor, Descriptor, into the corresponding verification type Type (4.10.1.2).
Converts a method descriptor, Descriptor, into a list of verification types, ArgTypeList, corresponding to the method argument types, and a verification type, ReturnType, corresponding to the return type.
Extracts the instruction stream, ParsedCode, of the method Method in Class, as well as the maximum operand stack size, MaxStack, the maximal number of local variables, FrameSize, the exception handlers, Handlers, and the stack map StackMap.
The representation of the instruction stream and stack map attribute must be as specified in 4.10.1.3 and 4.10.1.4.
True iff the package names of Class1 and Class2 are the same.
True iff the package names of Class1 and Class2 are different.
...
protected
MembersAll instructions that access members must contend with the rules concerning protected
members. This section describes the protected
check that corresponds to JLS 6.6.2.1.
The protected
check applies only to protected
members of superclasses of the current class. protected
members in other classes will be caught by the access checking done at resolution (5.4.4). There are four cases:
The getfield
, putfield
, and invokevirtual
instructions may be used to access a protected
member declared in a different package, but only if the member is referenced via the current class, a superclass of the current class, or a subclass of the current class; and only if the type of the target reference is assignable to the type of the current class.
Similarly, the invokespecial
instruction may be used to invoke a non-private
, non-<init>
method only if the the method is referenced via the current class, a superclass of the current class, or a direct superinterface of the current class; and only if the type of the target reference is assignable to the type of the current class.
In both cases, the restriction on the referenced class is enforced after resolution (getfield
, putfield
, invokevirtual
, invokespecial
). But the restriction on the type of the target reference must be enforced by the verifier.
Rather than resolving every referenced member in order to check its access flags, the verifier limits its checks to cases in which the name of the referenced class matches a superclass or superinterface. In any other case, either i) the referenced class is not one of the supported classes, and an error will occur after resolution, or ii) the referenced class is the current class or a subclass of the current class, and verification will already ensure that the type of the target reference is assignable to that class.
While the treatment of protected
instance method invocations is slightly different from the treatment of non-private
invokespecial
method invocations, the ultimate goal—checking in some circumstances that the type on the stack is a subtype of the current class—is the same. So it's helpful to describe both of these checks at the same time.
There are a number of technical problems with the existing passesProtectedCheck rule, and it's not clear how closely the specified rule aligns with implementation behavior. The rule is rewritten here to address these problems and improve clarity. If any inconsistencies with longstanding implementation behavior are observed, the rewritten rule can be revised.
If the name of a class is not the name of any superclass, it cannot be a superclass, and so it can safely be ignored.
passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor, StackFrame) :-
thisClass(Environment, class(CurrentClassName, CurrentLoader)),
superclassChain(CurrentClassName, CurrentLoader, Chain),
notMember(class(MemberClassName, _), Chain).
If the MemberClassName is the same as the name of a superclass, the class being resolved may indeed be a superclass. In this case, if no superclass named MemberClassName in a different run-time package has a protected member named MemberName with descriptor MemberDescriptor, the protected check does not apply.
This is because the actual class being resolved will either be one of these superclasses, in which case we know that it is either in the same run-time package, and the access is legal; or the member in question is notprotected
and the check does not apply; or it will be a subclass, in which case the check would succeed anyway; or it will be some other class in the same run-time package, in which case the access is legal and the check need not take place; or the verifier need not flag this as a problem, since it will be caught anyway because resolution will per force fail.
passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor, StackFrame) :-
thisClass(Environment, class(CurrentClassName, CurrentLoader)),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
classesInOtherPkgWithProtectedMember(
class(CurrentClassName, CurrentLoader),
MemberName, MemberDescriptor, MemberClassName, Chain, []).
If there does exist a protected
superclass member in a different run-time package, then load MemberClassName; if the member in question is not protected
, the check does not apply. (Using a superclass member that is not protected
is trivially correct.)
passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor,
frame(_Locals, [Target | Rest], _Flags)) :-
thisClass(Environment, class(CurrentClassName, CurrentLoader)),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
classesInOtherPkgWithProtectedMember(
class(CurrentClassName, CurrentLoader),
MemberName, MemberDescriptor, MemberClassName, Chain, List),
List /= [],
loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
isNotProtected(ReferencedClass, MemberName, MemberDescriptor).
Otherwise, use of a member of an object of type Target requires that Target be assignable to the type of the current class.
passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor,
frame(_Locals, [Target | Rest], _Flags)) :-
thisClass(Environment, class(CurrentClassName, CurrentLoader)),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
classesInOtherPkgWithProtectedMember(
class(CurrentClassName, CurrentLoader),
MemberName, MemberDescriptor, MemberClassName, Chain, List),
List /= [],
loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
isProtected(ReferencedClass, MemberName, MemberDescriptor),
isAssignable(Target, class(CurrentClassName, CurrentLoader)).
The predicate classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Chain, List) is true if List is the set of classes in Chain with name MemberClassName that are in a different run-time package than Class which have a protected
member named MemberName with descriptor MemberDescriptor.
classesInOtherPkgWithProtectedMember(_, _, _, _, [], []).
classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName,
[class(MemberClassName, L) | Tail],
[class(MemberClassName, L) | T]) :-
differentRuntimePackage(Class, class(MemberClassName, L)),
loadedClass(MemberClassName, L, Super),
isProtected(Super, MemberName, MemberDescriptor),
classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName,
[class(MemberClassName, L) | Tail],
T) :-
differentRuntimePackage(Class, class(MemberClassName, L)),
loadedClass(MemberClassName, L, Super),
isNotProtected(Super, MemberName, MemberDescriptor),
classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName,
[class(MemberClassName, L) | Tail],T] :-
sameRuntimePackage(Class, class(MemberClassName, L)),
classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
sameRuntimePackage(Class1, Class2) :-
classDefiningLoader(Class1, L),
classDefiningLoader(Class2, L),
samePackageName(Class1, Class2).
differentRuntimePackage(Class1, Class2) :-
classDefiningLoader(Class1, L1),classDefiningLoader(Class2, L2),L1 = L2.
differentRuntimePackage(Class1, Class2) :-
differentPackageName(Class1, Class2).
A member reference is a restricted protected
reference if the referenced class is a superclass of the current class, the member is declared protected
, and the member is declared in a different package than the current class.
restrictedProtectedReference(CurrentClass, MemberClassName, MemberName, MemberDescriptor) :-
CurrentClass = class(CurrentClassName, CurrentLoader),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
member(ReferencedClass, Chain),
resolvedMember(ReferencedClass, MemberName, MemberDescriptor, DeclaringClass, Member),
isProtected(Member, DeclaringClass),
differentRuntimePackage(CurrentClass, DeclaringClass).
The first three bullets in the old definition of passesProtectedCheck are simply tests for cases in which restrictedProtectedReference is not true. We achieve the same effect below by negating the predicate.
This rule is careful to avoid unnecessary class loading: MemberClassName only needs to be loaded if the name matches that of a superclass of the current class.
The old rule took this a step further by only loading if the name matched and there was a potential protected
member in one of the superclasses. This avoids loading a class that happens to share a name with an indirect superclass but is not, in fact, that superclass. But that's a rare corner case, and doesn't seem to justify the added complexity.
A member reference is allowed by a getfield
, putfield
, or invokevirtual
instruction if it is not a restricted protected
reference, or if the type of the target reference is assignable to the type of the current class.
allowedInstanceMemberReference(Environment, MemberClassName, MemberName, MemberDescriptor, StackFrame) :-
thisClass(Environment, CurrentClass),
\+ restrictedProtectedReference(CurrentClass, MemberClassName, MemberName, MemberDescriptor).
allowedInstanceMemberReference(Environment, MemberClassName, MemberName, MemberDescriptor, StackFrame) :-
thisClass(Environment, CurrentClass),
restrictedProtectedReference(CurrentClass, MemberClassName, MemberName, MemberDescriptor),
StackFrame = frame(_, [Target | Rest], _),
isAssignable(Target, CurrentClass).
A method reference is a restricted invokespecial
reference if the referenced method is not named <init>
, the referenced class is a superclass or direct superinterface of the current class, and the method is not declared private
.
restrictedInvokespecialReference(CurrentClass, MethodClassName, MethodName, MethodDescriptor) :-
MethodName \=
'<init>'
,
CurrentClass = class(CurrentClassName, CurrentLoader),
superclassChain(CurrentClassName, CurrentLoader, Classes),
classInterfaceNames(CurrentClass, InterfaceNames),
loadedClasses(CurrentLoader, InterfaceNames, Interfaces),
append(Classes, Interfaces, Supers),
member(class(MethodClassName, _), Supers),
loadedClass(MethodClassName, CurrentLoader, ReferencedClass),
member(ReferencedClass, Supers),
resolvedMember(ReferencedClass, MethodName, MethodDescriptor, DeclaringClass, Method),
isNotPrivate(Method).
A method reference is allowed by an invokespecial
instruction if it is not a restricted invokespecial
reference, or if the type of the target reference is assignable to the type of the current class.
allowedInvokespecialReference(Environment, MethodClassName, MethodName, MethodDescriptor, StackFrame) :-
thisClass(Environment, CurrentClass),
\+ restrictedInvokeSpecialReference(CurrentClass, MethodClassName, MethodName, MethodDescriptor).
allowedInvokespecialReference(Environment, MethodClassName, MethodName, MethodDescriptor, StackFrame) :-
thisClass(Environment, CurrentClass),
restrictedInvokeSpecialReference(CurrentClass, MethodClassName, MethodName, MethodDescriptor),
StackFrame = frame(_, [Target | Rest], _)),
isAssignable(Target, CurrentClass).
...
getfield
A getfield
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting a field whose declared type is FieldType, declared in a class FieldClass, and one can validly replace a type matching FieldClass with type FieldType on the incoming operand stack yielding the outgoing type state. FieldClass must not be an array type. A reference to a protected
fields are subject to additional checksprotected
field may require that further restrictions be placed on the type on the stack (4.10.1.8).
instructionIsTypeSafe(getfield(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = field(FieldClass, FieldName, FieldDescriptor),
parseFieldDescriptor(FieldDescriptor, FieldType),
passesProtectedCheckallowedInstanceMemberReference(Environment, FieldClass, FieldName, FieldDescriptor, StackFrame),
validTypeTransition(Environment, [class(FieldClass)], FieldType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
invokespecial
An invokespecial
instruction is type safe iff all of the following are true:
Its first operand, CP, refers to a constant pool entry denoting a method named MethodName with descriptor Descriptor that is a member of a class MethodClassName.
Either:
MethodName is not <init>
.
MethodName is not <clinit>
.
One can validly replace types matching the current class and the argument types given in Descriptor on the incoming operand stack with the return type given in Descriptor, yielding the outgoing type state.
One can validly replace types matching the class MethodClassName and the argument types given in Descriptor on the incoming operand stack with the return type given in Descriptor, yielding the outgoing type state.
If the method is not private
, the type of the target reference operand is appropriate (4.10.1.8).
instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = method(MethodClassName, MethodName, Descriptor),
MethodName \='<init>'
,
MethodName \='<clinit>'
,
parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
reverse(OperandArgList, ArgList),
thisClass(Environment, class(CurrentClassName, CurrentLoader)),
currentClassLoader(Environment, CurrentLoader),
reverse([class(CurrentClassName, CurrentLoader) | OperandArgList], StackArgList),
validTypeTransition(Environment, StackArgList, ReturnType, StackFrame, NextStackFrame),
reverse([class(MethodClassName, CurrentLoader) | OperandArgList], StackArgList),
validTypeTransition(Environment, StackArgList, ReturnType, StackFrame, NextStackFrame),
isAssignable(class(CurrentClassName, CurrentLoader), class(MethodClassName, CurrentLoader)).
canPop(StackFrame, ArgList, PoppedFrame),
allowedInvokespecialReference(Environment, MethodClassName, MethodName, Descriptor, PoppedFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
The deleted checks on the type of the target reference operand are superseded by the allowedInvokespecialReference predicate. With this change, the rule is almost identical to that of invokevirtual
.
Or:
MethodName is <init>
.
Descriptor specifies a void
return type.
One can validly pop types matching the argument types given in Descriptor and an uninitialized type, UninitializedArg, off the incoming operand stack, yielding OperandStack.
The outgoing type state is derived from the incoming type state by first replacing the incoming operand stack with OperandStack and then replacing all instances of UninitializedArg with the type of instance being initialized.
...
invokevirtual
An invokevirtual
instruction is type safe iff all of the following are true:
Its first operand, CP, refers to a constant pool entry denoting a method named MethodName with descriptor Descriptor that is a member of a class MethodClassName.
MethodName is not <init>
.
MethodName is not <clinit>
.
One can validly replace types matching the class MethodClassName and the argument types given in Descriptor on the incoming operand stack with the return type given in Descriptor, yielding the outgoing type state.
If the method is protected
, the usage conforms to the special rules governing access to protected members type of the target reference operand is appropriate (4.10.1.8).
instructionIsTypeSafe(invokevirtual(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = method(MethodClassName, MethodName, Descriptor),
MethodName ='<init>'
,
MethodName ='<clinit>'
,
parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
reverse(OperandArgList, ArgList),
currentClassLoader(Environment, CurrentLoader),
reverse([class(MethodClassName, CurrentLoader) | OperandArgList], StackArgList),
validTypeTransition(Environment, StackArgList, ReturnType, StackFrame, NextStackFrame),
canPop(StackFrame, ArgList, PoppedFrame),
passesProtectedCheckallowedInstanceMemberReference(Environment, MethodClassName, MethodName, Descriptor, PoppedFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
putfield
A putfield
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting a field whose declared type is FieldType, declared in a class FieldClass, and one can validly pop types matching FieldType and FieldClass off the incoming operand stack yielding the outgoing type state. A reference to a protected
field may require that further restrictions be placed on the type of the target reference operand (4.10.1.8).
instructionIsTypeSafe(putfield(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = field(FieldClass, FieldName, FieldDescriptor),
parseFieldDescriptor(FieldDescriptor, FieldType),
canPop(StackFrame, [FieldType], PoppedFrame),
passesProtectedCheckallowedInstanceMemberReference(Environment, FieldClass, FieldName, FieldDescriptor, PoppedFrame),
currentClassLoader(Environment, CurrentLoader),
canPop(StackFrame, [FieldType, class(FieldClass, CurrentLoader)], NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
A class or interface C is accessible to a class or interface D if and only if either of the following is true:
C is public
.
C and D are members of the same run-time package (5.3).
A field or method R is accessible to a class or interface D if and only if any of the following is true:
R is public
.
R is protected
and is declared in a class C, and D is either a subclass of C or C itself. Furthermore, if R is not static
, then the symbolic reference to R
must contain a symbolic reference to a class T
, such that T
is either a subclass of D
, a superclass of D
, or D
itself.
R is either protected
or has default access (that is, neither public
nor protected
nor private
), and is declared by a class in the same run-time package as D.
R is private
and is declared in D by a class belonging to the same nest as D.
A class with a MemberOfNest
attribute belongs to the nest hosted by the referenced host class.
A class without a MemberOfNest
attribute implicitly belongs to a nest hosted by the class itself. (If the class also lacks a NestMembers
attribute, then the nest has only one member.)
This discussion of access control omits a related restriction on the target of a protected
field access or method invocation (the target must be of class D or a subtype of D). That requirement is checked as part of the verification process (4.10.1.8); it is not part of link-time access control.
This discussion also omits certain restrictions on the class named by the symbolic reference to R, depending on the access flags of R. These checks are performed immediately after resolution, as specified for getfield
, putfield
, invokevirtual
, and invokespecial
.
The restriction on the referenced type of a protected
instance member reference makes more sense as an instruction-specific requirement than as part of the definition of accessibility. Moving the check also gives us better congruence between the protected
check of invokevirtual
and the non-private
check of invokespecial
.
The change has a subtle, probably tolerable impact: if invokestatic
, getstatic
, or putstatic
references a non-static, protected
member declared in a superclass belonging to another package, referenced via a disallowed class, the check on the referenced class is no longer performed and users would see an IncompatibleClassChangeError
rather than an IllegalAccessError
. Similarly, such a reference to an <init>
method by invokespecial
will trigger a NoSuchMethodError
rather than an IllegalAccessError
.
getfield
Fetch field from object
getfield indexbyte1 indexbyte2
getfield = 180 (0xb4)
..., objectref →
..., value
The objectref, which must be of type reference
, is popped from the operand stack. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class in which the field is to be found. The referenced field is resolved (5.4.3.2). The value of the referenced field in objectref is fetched and pushed onto the operand stack.
The type of objectref must not be an array type. If the field is protected
, and it is a member of a superclass of the current class, and the field is not declared in the same run-time package (5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class.
These rules are redundant: verification already guarantees them (4.10.1.9).
During resolution of the symbolic reference to the field, any of the errors pertaining to field resolution (5.4.3.2) can be thrown.
Otherwise, if the resolved field is a static
field, getfield
throws an IncompatibleClassChangeError
.
Otherwise, if the resolved field is protected
and declared in a different run-time package (5.3) than the current class, and the class symbolically referenced by the instruction is neither the current class, nor a superclass of the current class, nor a subclass of the current class, then the getfield
instruction throws an IllegalAccessError
.
For improved presentation, this was moved from 5.4.4.
Otherwise, if objectref is null
, the getfield
instruction throws a NullPointerException
.
The getfield instruction cannot be used to access the length
field of an array. The arraylength
instruction (arraylength
) is used instead.
invokespecial
Invoke instance method; special handling for superclass, private, and instance initialization method invocations.
invokespecial indexbyte1 indexbyte2
invokespecial = 183 (0xb7)
..., objectref, [ arg1, [ arg2 ... ]] →
...
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a method or an interface method (5.1), which gives the name and descriptor (4.3.3) of the method as well as a symbolic reference to the class or interface in which the method is to be found. The named method is resolved (5.4.3.3, 5.4.3.4).
If the resolved method is protected
, and it is a member of a superclass of the current class, and the method is not declared in the same run-time package (5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class.
This rule is redundant: a broader check on all non-private
methods in superclasses is performed by verification (4.10.1.9).
If all of the following are true, let C be the direct superclass of the current class:
private
.ACC_SUPER
flag is set for the class
file (4.1).Otherwise, let C be the class or interface named by the symbolic reference.
The actual method to be invoked is selected by the following lookup procedure:
...
During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution (5.4.3.3, 5.4.3.4) can be thrown.
Otherwise, if the resolved method is an instance initialization method, and the class in which it is declared is not the class symbolically referenced by the instruction, a NoSuchMethodError
is thrown.
Otherwise, if the resolved method is a class ( static
)static
method, the invokespecial
instruction throws an IncompatibleClassChangeError
.
Otherwise, if the resolved method is not an instance initialization method and is not private
, and the class symbolically referenced by the instruction is neither the current class, nor a superclass of the current class, nor a direct superinterface of the current class, then the invokespecial
instruction throws an IllegalAccessError
.
This replaces a VerifyError
previously specified by 4.9.2. The check must be delayed until after resolution in order to determine whether the referenced method is private
.
Otherwise, if objectref is null
, the invokespecial
instruction throws a NullPointerException
.
Otherwise, if the resolved method is a protected
method of a superclass of the current class, declared in a different run-time package, and the class of objectref is not the current class or a subclass of the current class, then invokespecial
throws an IllegalAccessError
.
Otherwise, if the instruction symbolically references an interface method and the class of objectref does not implement the resolved interface, invokespecial
throws an IncompatibleClassChangeError
.
Otherwise, if the current class is an interface, and the resolved method is not an instance initialization method and is not private
, and the class of objectref does not implement the current interface, invokespecial
throws an IncompatibleClassChangeError
.
This is a possible fix for JDK-8134358. Like invokeinterface
, we can't trust assertions in the verifier that the objectref implements an interface, and so check them dynamically for each objectref.
Otherwise, if step 1, step 2, or step 3 of the lookup procedure selects an abstract
method, invokespecial
throws an AbstractMethodError
.
Otherwise, if step 1, step 2, or step 3 of the lookup procedure selects a native
method and the code that implements the method cannot be bound, invokespecial throws an UnsatisfiedLinkError
.
Otherwise, if step 4 of the lookup procedure determines there are multiple maximally-specific methods in the superinterfaces of C that match the resolved method's name and descriptor and are not abstract
, invokespecial
throws an IncompatibleClassChangeError
.
Otherwise, if step 4 of the lookup procedure determines there are zero maximally-specific methods in the superinterfaces of C that match the resolved method's name and descriptor and are not abstract
, invokespecial
throws an AbstractMethodError
.
The difference between the invokespecial
instruction and the invokevirtual
instruction (invokevirtual
) is that invokevirtual
invokes a method based on the class of the object. The invokespecial
instruction is used to invoke instance initialization methods (2.9) as well as private
methods and methods of a superclass of the current class.
The
invokespecial
instruction was namedinvokenonvirtual
prior to JDK release 1.0.2.
The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types long
and double
must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.
The invokespecial
instruction handles invocation of a private
interface method, a non-abstract
interface method referenced via a direct superinterface, and a non-abstract
interface method referenced via a superclass. In these cases, the rules for selection are essentially the same as those for invokeinterface
(except that the search starts from a different class).
invokevirtual
Invoke instance method; dispatch based on class
invokevirtual indexbyte1 indexbyte2
invokevirtual = 182 (0xb6)
..., objectref, [ arg1, [ arg2 ... ]] →
...
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a method (5.1), which gives the name and descriptor (4.3.3) of the method as well as a symbolic reference to the class in which the method is to be found. The named method is resolved (5.4.3.3).
The resolved method must not be an instance initialization method, or the class or interface initialization method (2.9).
If the resolved method is protected
, and it is a member of a superclass of the current class, and the method is not declared in the same run-time package (5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class.
These rules are redundant: verification already guarantees them (4.10.1.9).
If the resolved method is not signature polymorphic (2.9), then the invokevirtual
instruction proceeds as follows.
...
During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution (5.4.3.3) can be thrown.
Otherwise, if the resolved method is a class ( static
)static
method, the invokevirtual
instruction throws an IncompatibleClassChangeError
.
Otherwise, if the resolved method is protected
and declared in a different run-time package (5.3) than the current class, and the class symbolically referenced by the instruction is neither the current class, nor a superclass of the current class, nor a subclass of the current class, then the invokevirtual
instruction throws an IllegalAccessError
.
For improved presentation, this was moved from 5.4.4.
Otherwise, if the resolved method is signature polymorphic, then during resolution of the method type derived from the descriptor in the symbolic reference to the method, any of the exceptions pertaining to method type resolution ([5.4.3.5]) can be thrown.
...
putfield
Set field in object
putfield indexbyte1 indexbyte2
putfield = 181 (0xb5)
..., objectref, value →
...
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class in which the field is to be found. The class of objectref must not be an array. If the field is protected
, and it is a member of a superclass of the current class, and the field is not declared in the same run-time package (5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class.
The referenced field is resolved (5.4.3.2). The type of a value stored by a putfield
instruction must be compatible with the descriptor of the referenced field ([4.3.2]). If the field descriptor type is boolean
, byte
, char
, short
, or int
, then the value must be an int
. If the field descriptor type is float
, long
, or double
, then the value must be a float
, long
, or double
, respectively. If the field descriptor type is a reference type, then the value must be of a type that is assignment compatible (JLS 5.2) with the field descriptor type. If the field is final
, it must be declared in the current class, and the instruction must occur in an instance initialization method (<init>
) of the current class (2.9).
These rules are redundant: verification already guarantees most of them (4.10.1.9). The final
restriction is restated below.
The value and objectref are popped from the operand stack. The objectref must be of type reference
. The value undergoes value set conversion (2.8.3), resulting in value', and the referenced field in objectref is set to value'.
During resolution of the symbolic reference to the field, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.
Otherwise, if the resolved field is a static
field, putfield
throws an IncompatibleClassChangeError
.
Otherwise, if the resolved field is protected
and declared in a different run-time package (5.3) than the current class, and the class symbolically referenced by the instruction is neither the current class, nor a superclass of the current class, nor a subclass of the current class, then the putfield
instruction throws an IllegalAccessError
.
For improved presentation, this was moved from 5.4.4.
Otherwise, if the field is final
, it must be declared in the current class, and the instruction must occur in an instance initialization method (<init>
) of the current class. Otherwise, an IllegalAccessError
is thrown.
Otherwise, if objectref is null
, the getfield
instruction throws a NullPointerException
.
Copyright © 2017 Oracle America, Inc. 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved.
The Specification is protected by copyright and the information described therein may be protected by one or more U.S. patents, foreign patents, or pending applications. Except as provided under the following license, no part of the Specification may be reproduced in any form by any means without the prior written authorization of Oracle America, Inc. ("Oracle") and its licensors, if any. Any use of the Specification and the information described therein will be governed by the terms and conditions of this Agreement.
Subject to the terms and conditions of this license, including your compliance with Paragraphs 1 and 2 below, Oracle hereby grants you a fully-paid, non-exclusive, non-transferable, limited license (without the right to sublicense) under Oracle's intellectual property rights to:
Review the Specification for the purposes of evaluation. This includes: (i) developing implementations of the Specification for your internal, non-commercial use; (ii) discussing the Specification with any third party; and (iii) excerpting brief portions of the Specification in oral or written communications which discuss the Specification provided that such excerpts do not in the aggregate constitute a significant portion of the Technology.
Distribute implementations of the Specification to third parties for their testing and evaluation use, provided that any such implementation:
does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented;
is clearly and prominently marked with the word "UNTESTED" or "EARLY ACCESS" or "INCOMPATIBLE" or "UNSTABLE" or "BETA" in any list of available builds and in proximity to every link initiating its download, where the list or link is under Licensee's control; and
includes the following notice: "This is an implementation of an early-draft specification developed under the Java Community Process (JCP) and is made available for testing and evaluation purposes only. The code is not compatible with any specification of the JCP."
The grant set forth above concerning your distribution of implementations of the specification is contingent upon your agreement to terminate development and distribution of your "early draft" implementation as soon as feasible following final completion of the specification. If you fail to do so, the foregoing grant shall be considered null and void.
No provision of this Agreement shall be understood to restrict your ability to make and distribute to third parties applications written to the Specification.
Other than this limited license, you acquire no right, title or interest in or to the Specification or any other Oracle intellectual property, and the Specification may only be used in accordance with the license terms set forth herein. This license will expire on the earlier of: (a) two (2) years from the date of Release listed above; (b) the date on which the final version of the Specification is publicly released; or (c) the date on which the Java Specification Request (JSR) to which the Specification corresponds is withdrawn. In addition, this license will terminate immediately without notice from Oracle if you fail to comply with any provision of this license. Upon termination, you must cease use of or destroy the Specification.
"Licensor Name Space" means the public class or interface declarations whose names begin with "java", "javax", "com.oracle" or their equivalents in any subsequent naming convention adopted by Oracle through the Java Community Process, or any recognized successors or replacements thereof.
No right, title, or interest in or to any trademarks, service marks, or trade names of Oracle or Oracle's licensors is granted hereunder. Oracle, the Oracle logo, Java are trademarks or registered trademarks of Oracle USA, Inc. in the U.S. and other countries.
THE SPECIFICATION IS PROVIDED "AS IS" AND IS EXPERIMENTAL AND MAY CONTAIN DEFECTS OR DEFICIENCIES WHICH CANNOT OR WILL NOT BE CORRECTED BY ORACLE. ORACLE MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS. This document does not represent any commitment to release or implement any portion of the Specification in any product.
THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. ORACLE MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification.
TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL ORACLE OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF ORACLE AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
You will hold Oracle (and its licensors) harmless from any claims based on your use of the Specification for any purposes other than the limited right of evaluation as described above, and from any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license.
If this Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).
You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your evaluation of the Specification ("Feedback"). To the extent that you provide Oracle with any Feedback, you hereby: (i) agree that such Feedback is provided on a non-proprietary and non-confidential basis, and (ii) grant Oracle a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose related to the Specification and future versions, implementations, and test suites thereof.
Any action related to this Agreement will be governed by California law and controlling U.S. federal law. The U.N. Convention for the International Sale of Goods and the choice of law rules of any jurisdiction will not apply.
The Specification is subject to U.S. export control laws and may be subject to export or import regulations in other countries. Licensee agrees to comply strictly with all such laws and regulations and acknowledges that it has the responsibility to obtain such licenses to export, re-export or import as may be required after delivery to Licensee.
This Agreement is the parties' entire agreement relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, conditions, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification to this Agreement will be binding, unless in writing and signed by an authorized representative of each party.