Skip to content

Commit

Permalink
Merge pull request #13199 from ChengJin01/vm_icce_getdeclaringclass_c…
Browse files Browse the repository at this point in the history
…heck_innerclass_v3

Check the InnerClass attribute of the enclosing class
  • Loading branch information
pshipton committed Nov 19, 2021
2 parents 7561d93 + 12257af commit b16777a
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 27 deletions.
39 changes: 38 additions & 1 deletion jcl/src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ private static final class MetadataCache {
private transient Class<?> cachedEnclosingClass;
private static long cachedEnclosingClassOffset = -1;

private transient boolean cachedCheckInnerClassAttr;

private static Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];

static MethodHandles.Lookup implLookup;
Expand Down Expand Up @@ -1293,6 +1295,13 @@ public Class<?> getDeclaringClass() {
*/
Class<?> declaringClass = cachedDeclaringClass == ClassReflectNullPlaceHolder.class ? null : cachedDeclaringClass;
if (declaringClass == null) {
if (!cachedCheckInnerClassAttr) {
/* Check whether the enclosing class has an valid inner class entry to the current class.
* Note: the entries are populated with the InnerClass attribute when creating ROM class.
*/
checkInnerClassAttrOfEnclosingClass();
cachedCheckInnerClassAttr = true;
}
return declaringClass;
}
if (declaringClass.isClassADeclaredClass(this)) {
Expand Down Expand Up @@ -1320,7 +1329,23 @@ public Class<?> getDeclaringClass() {

/*[MSG "K0555", "incompatible InnerClasses attribute between \"{0}\" and \"{1}\""]*/
throw new IncompatibleClassChangeError(
com.ibm.oti.util.Msg.getString("K0555", this.getName(), declaringClass.getName())); //$NON-NLS-1$
com.ibm.oti.util.Msg.getString("K0555", this.getName(), declaringClass.getName())); //$NON-NLS-1$
}

/**
* Checks whether the current class exists in the InnerClass attribute of the specified enclosing class
* when this class is not defined directly inside the enclosing class (e.g. defined inside a method).
*
* Note: The direct inner classes of the declaring class is already checked in getDeclaringClass()
* when the enclosing class is the declaring class.
*/
private void checkInnerClassAttrOfEnclosingClass() {
Class<?> enclosingClass = getEnclosingObjectClass();
if ((enclosingClass != null) && !enclosingClass.isClassAnEnclosedClass(this)) {
/*[MSG "K0555", "incompatible InnerClasses attribute between \"{0}\" and \"{1}\""]*/
throw new IncompatibleClassChangeError(
com.ibm.oti.util.Msg.getString("K0555", this.getName(), enclosingClass.getName())); //$NON-NLS-1$
}
}

/**
Expand All @@ -1342,6 +1367,18 @@ public Class<?> getDeclaringClass() {
*/
private native boolean isClassADeclaredClass(Class<?> aClass);

/**
* Returns true if the class passed in to the method is an enclosed class of
* this class, which includes both the declared classes and the classes defined
* inside a method of this class.
*
* @param aClass The class to validate
* @return true if aClass an enclosed class of this class
* false otherwise.
*
*/
private native boolean isClassAnEnclosedClass(Class<?> aClass);

/**
* Answers the class which declared the class represented
* by the receiver. This will return null if the receiver
Expand Down
10 changes: 9 additions & 1 deletion runtime/bcutil/ClassFileOracle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
_doubleScalarStaticCount(0),
_memberAccessFlags(0),
_innerClassCount(0),
_enclosedInnerClassCount(0),
#if JAVA_SPEC_VERSION >= 11
_nestMembersCount(0),
_nestHost(0),
Expand Down Expand Up @@ -459,7 +460,7 @@ ClassFileOracle::walkAttributes()
if (outerClassUTF8 == thisClassUTF8) {
/* Member class - mark the class' name. */
markClassNameAsReferenced(entry->innerClassInfoIndex);
_innerClassCount++;
_innerClassCount += 1;
} else if (innerClassUTF8 == thisClassUTF8) {
_isInnerClass = true;
_memberAccessFlags = entry->innerClassAccessFlags;
Expand All @@ -474,6 +475,13 @@ ClassFileOracle::walkAttributes()
markConstantUTF8AsReferenced(entry->innerNameIndex);
_simpleNameIndex = entry->innerNameIndex;
}
} else {
/* Count all entries in the InnerClass attribute (except the inner class itself) so as
* to check the InnerClass attribute between the inner classes and the enclosing class.
* See getDeclaringClass() for details.
*/
markClassNameAsReferenced(entry->innerClassInfoIndex);
_enclosedInnerClassCount += 1;
}
}
Trc_BCU_Assert_Equals(NULL, _innerClasses);
Expand Down
24 changes: 24 additions & 0 deletions runtime/bcutil/ClassFileOracle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,28 @@ class RecordComponentIterator
}
}

/*
* Iterate over the constant pool indices corresponding to enclosed inner class names (UTF8s).
*/
void enclosedInnerClassesDo(ConstantPoolIndexVisitor *visitor)
{
if (NULL != _innerClasses) {
J9CfrClassesEntry *end = _innerClasses->classes + _innerClasses->numberOfClasses;
U_16 thisClassUTF8 = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, _classFile->thisClass);
for (J9CfrClassesEntry *entry = _innerClasses->classes; entry != end; ++entry) {
U_16 outerClassUTF8 = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, entry->outerClassInfoIndex);
U_16 innerClassUTF8 = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, entry->innerClassInfoIndex);
/* Count all remaining entries in the InnerClass attribute (except the entries covered by innerClassesDo())
* so as to check the InnerClass attribute between the inner classes and the enclosing class.
* See getDeclaringClass() for details.
*/
if ((thisClassUTF8 != outerClassUTF8) && (thisClassUTF8 != innerClassUTF8)) {
visitor->visitConstantPoolIndex(innerClassUTF8);
}
}
}
}

#if JAVA_SPEC_VERSION >= 11
void nestMembersDo(ConstantPoolIndexVisitor *visitor)
{
Expand Down Expand Up @@ -913,6 +935,7 @@ class RecordComponentIterator
U_16 getDoubleScalarStaticCount() const { return _doubleScalarStaticCount; }
U_16 getMemberAccessFlags() const { return _memberAccessFlags; }
U_16 getInnerClassCount() const { return _innerClassCount; }
U_16 getEnclosedInnerClassCount() const { return _enclosedInnerClassCount; }
#if JAVA_SPEC_VERSION >= 11
U_16 getNestMembersCount() const { return _nestMembersCount; }
U_16 getNestHostNameIndex() const { return _nestHost; }
Expand Down Expand Up @@ -1064,6 +1087,7 @@ class RecordComponentIterator
U_16 _doubleScalarStaticCount;
U_16 _memberAccessFlags;
U_16 _innerClassCount;
U_16 _enclosedInnerClassCount;
#if JAVA_SPEC_VERSION >= 11
U_16 _nestMembersCount;
U_16 _nestHost;
Expand Down
38 changes: 34 additions & 4 deletions runtime/bcutil/ClassFileWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ ClassFileWriter::analyzeROMClass()
#endif /* JAVA_SPEC_VERSION >= 11 */

/* For a local class only InnerClasses.class[i].inner_name_index is preserved as simpleName in its J9ROMClass */
if ((0 != _romClass->innerClassCount) || J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
if ((0 != _romClass->innerClassCount)
|| (0 != _romClass->enclosedInnerClassCount)
|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)
) {
addEntry((void *) &INNER_CLASSES, 0, CFR_CONSTANT_Utf8);

if (NULL != outerClassName) {
Expand All @@ -139,6 +142,11 @@ ClassFileWriter::analyzeROMClass()
J9UTF8 * className = NNSRP_PTR_GET(innerClasses, J9UTF8 *);
addClassEntry(className, 0);
}
J9SRP * enclosedInnerClasses = (J9SRP *) J9ROMCLASS_ENCLOSEDINNERCLASSES(_romClass);
for (UDATA i = 0; i < _romClass->enclosedInnerClassCount; i++, enclosedInnerClasses++) {
J9UTF8 * className = NNSRP_PTR_GET(enclosedInnerClasses, J9UTF8 *);
addClassEntry(className, 0);
}
}

#if JAVA_SPEC_VERSION >= 11
Expand Down Expand Up @@ -954,7 +962,10 @@ ClassFileWriter::writeAttributes()
U_16 nestMemberCount = _romClass->nestMemberCount;
#endif /* JAVA_SPEC_VERSION >= 11 */

if ((0 != _romClass->innerClassCount) || J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
if ((0 != _romClass->innerClassCount)
|| (0 != _romClass->enclosedInnerClassCount)
|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)
) {
attributesCount += 1;
}
if (NULL != enclosingObject) {
Expand Down Expand Up @@ -992,8 +1003,11 @@ ClassFileWriter::writeAttributes()
#endif /* JAVA_SPEC_VERSION >= 11 */
writeU16(attributesCount);

if ((0 != _romClass->innerClassCount) || J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
U_16 innerClassesCount(_romClass->innerClassCount);
if ((0 != _romClass->innerClassCount)
|| (0 != _romClass->enclosedInnerClassCount)
|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)
) {
U_16 innerClassesCount(_romClass->innerClassCount + _romClass->enclosedInnerClassCount);

if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
/* This is an inner class, so we have one extra inner class attribute to allocate/write */
Expand Down Expand Up @@ -1022,6 +1036,22 @@ ClassFileWriter::writeAttributes()
writeU16(0); /* innerClassAccessFlags */
}

/* Write enclosed inner classes of this class */
J9SRP * enclosedInnerClasses = (J9SRP *) J9ROMCLASS_ENCLOSEDINNERCLASSES(_romClass);
/* Write the enclosed inner class entries for inner classes of this class */
for (UDATA i = 0; i < _romClass->enclosedInnerClassCount; i++, enclosedInnerClasses++) {
J9UTF8 * enclosedInnerClassName = NNSRP_PTR_GET(enclosedInnerClasses, J9UTF8 *);

writeU16(indexForClass(enclosedInnerClassName));
/* NOTE: outerClassInfoIndex (these inner class are not the declared classes of this class),
* innerNameIndex and innerClassAccessFlags are not preserved in the ROM class
* - technically incorrect, but this should only matter to compilers.
*/
writeU16(0); /* outerClassInfoIndex */
writeU16(0); /* innerNameIndex */
writeU16(0); /* innerClassAccessFlags */
}

if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
/* This is an inner class. Write an inner class attribute for itself. */
writeU16(thisClassCPIndex);
Expand Down
24 changes: 24 additions & 0 deletions runtime/bcutil/ROMClassWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ ROMClassWriter::ROMClassWriter(BufferManager *bufferManager, ClassFileOracle *cl
_fieldsSRPKey(srpKeyProducer->generateKey()),
_cpDescriptionShapeSRPKey(srpKeyProducer->generateKey()),
_innerClassesSRPKey(srpKeyProducer->generateKey()),
_enclosedInnerClassesSRPKey(srpKeyProducer->generateKey()),
#if JAVA_SPEC_VERSION >= 11
_nestMembersSRPKey(srpKeyProducer->generateKey()),
#endif /* JAVA_SPEC_VERSION >= 11 */
Expand Down Expand Up @@ -399,6 +400,8 @@ ROMClassWriter::writeROMClass(Cursor *cursor,
cursor->writeU32(_classFileOracle->getMemberAccessFlags(), Cursor::GENERIC);
cursor->writeU32(_classFileOracle->getInnerClassCount(), Cursor::GENERIC);
cursor->writeSRP(_innerClassesSRPKey, Cursor::SRP_TO_GENERIC);
cursor->writeU32(_classFileOracle->getEnclosedInnerClassCount(), Cursor::GENERIC);
cursor->writeSRP(_enclosedInnerClassesSRPKey, Cursor::SRP_TO_GENERIC);
#if JAVA_SPEC_VERSION >= 11
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getNestHostNameIndex()), Cursor::SRP_TO_UTF8);
cursor->writeU16(_classFileOracle->getNestMembersCount(), Cursor::GENERIC);
Expand Down Expand Up @@ -440,6 +443,7 @@ ROMClassWriter::writeROMClass(Cursor *cursor,
writeFields(cursor, markAndCountOnly);
writeInterfaces(cursor, markAndCountOnly);
writeInnerClasses(cursor, markAndCountOnly);
writeEnclosedInnerClasses(cursor, markAndCountOnly);
#if JAVA_SPEC_VERSION >= 11
writeNestMembers(cursor, markAndCountOnly);
#endif /* JAVA_SPEC_VERSION >= 11 */
Expand Down Expand Up @@ -759,6 +763,13 @@ class ROMClassWriter::Helper :
}
}

void writeEnclosedInnerClasses()
{
if (!_markAndCountOnly) {
_classFileOracle->enclosedInnerClassesDo(this); /* visitConstantPoolIndex */
}
}

#if JAVA_SPEC_VERSION >= 11
void writeNestMembers()
{
Expand Down Expand Up @@ -1159,6 +1170,19 @@ ROMClassWriter::writeInnerClasses(Cursor *cursor, bool markAndCountOnly)
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
}

void
ROMClassWriter::writeEnclosedInnerClasses(Cursor *cursor, bool markAndCountOnly)
{
cursor->mark(_enclosedInnerClassesSRPKey);
UDATA size = UDATA(_classFileOracle->getEnclosedInnerClassCount()) * sizeof(J9SRP);
CheckSize _(cursor, size);
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeEnclosedInnerClasses();
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeEnclosedInnerClasses();
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
}

#if JAVA_SPEC_VERSION >= 11
void
ROMClassWriter::writeNestMembers(Cursor *cursor, bool markAndCountOnly)
Expand Down
2 changes: 2 additions & 0 deletions runtime/bcutil/ROMClassWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class ROMClassWriter
void writeFields(Cursor *cursor, bool markAndCountOnly);
void writeInterfaces(Cursor *cursor, bool markAndCountOnly);
void writeInnerClasses(Cursor *cursor, bool markAndCountOnly);
void writeEnclosedInnerClasses(Cursor *cursor, bool markAndCountOnly);
void writeNestMembers(Cursor *cursor, bool markAndCountOnly);
void writeNameAndSignatureBlock(Cursor *cursor);
void writeMethods(Cursor *cursor, Cursor *lineNumberCursor, Cursor *variableInfoCursor, bool markAndCountOnly);
Expand Down Expand Up @@ -171,6 +172,7 @@ class ROMClassWriter
UDATA _fieldsSRPKey;
UDATA _cpDescriptionShapeSRPKey;
UDATA _innerClassesSRPKey;
UDATA _enclosedInnerClassesSRPKey;
#if JAVA_SPEC_VERSION >= 11
UDATA _nestMembersSRPKey;
#endif /* JAVA_SPEC_VERSION >= 11 */
Expand Down

0 comments on commit b16777a

Please sign in to comment.