Skip to content

Commit

Permalink
Merge pull request #18491 from theresa-m/parseannotations
Browse files Browse the repository at this point in the history
0.43.0: Append cp to method and field annotation data to fix redefinition inconsistencies
  • Loading branch information
tajila committed Nov 20, 2023
2 parents 837e7c2 + 90d0a1c commit f263056
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 82 deletions.
Expand Up @@ -105,17 +105,10 @@ private static byte[] getAttributeData(Class clazz) {
*/
public static AnnotatedType[] buildAnnotatedInterfaces(Class clazz) {
byte[] attr = getAttributeData(clazz);
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + ((attr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE) - VM.FJ9OBJECT_SIZE);
long ramCPAddr = 0;
if (VM.FJ9OBJECT_SIZE == 4) {
/* Compressed object refs */
ramCPAddr = Integer.toUnsignedLong(Unsafe.getUnsafe().getInt(attr, offset));
} else {
ramCPAddr = Unsafe.getUnsafe().getLong(attr, offset);
}
Object internalConstantPool = VM.getVMLangAccess().createInternalConstantPool(ramCPAddr);

AnnotatedType[] annotatedInterfaces = sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedInterfaces(attr, AnnotationParser.getConstantPool(internalConstantPool), clazz);
AnnotatedType[] annotatedInterfaces = sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedInterfaces(
attr,
VM.getConstantPoolFromAnnotationBytes(clazz, attr),
clazz);
return annotatedInterfaces;
}
/**
Expand All @@ -125,17 +118,10 @@ public static AnnotatedType[] buildAnnotatedInterfaces(Class clazz) {
*/
public static AnnotatedType buildAnnotatedSupertype(Class clazz) {
byte[] attr = getAttributeData(clazz);
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + ((attr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE) - VM.FJ9OBJECT_SIZE);
long ramCPAddr = 0;
if (VM.FJ9OBJECT_SIZE == 4) {
/* Compressed object refs */
ramCPAddr = Integer.toUnsignedLong(Unsafe.getUnsafe().getInt(attr, offset));
} else {
ramCPAddr = Unsafe.getUnsafe().getLong(attr, offset);
}
Object internalConstantPool = VM.getVMLangAccess().createInternalConstantPool(ramCPAddr);

AnnotatedType annotatedSuperclass = sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedSuperclass(attr, AnnotationParser.getConstantPool(internalConstantPool), clazz);
AnnotatedType annotatedSuperclass = sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedSuperclass(
attr,
VM.getConstantPoolFromAnnotationBytes(clazz, attr),
clazz);
return annotatedSuperclass;
}
}
34 changes: 34 additions & 0 deletions jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java
Expand Up @@ -27,9 +27,13 @@
import com.ibm.oti.util.Util;

/*[IF Sidecar19-SE]
import jdk.internal.misc.Unsafe;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.ConstantPool;
/*[ELSE]*/
import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool;
/*[ENDIF]*/

/**
Expand Down Expand Up @@ -583,4 +587,34 @@ public static int markCurrentThreadAsSystem()
* @return true if JVM is in single threaded mode, false otherwise
*/
public static native boolean isJVMInSingleThreadedMode();

/**
* A J9ConstantPool* is appended to anntation parameter byte arrays
* so it will be consistent with annotation data if the class is redefined.
* Only use this method with:
* - java.lang.Class.getAnnotationCache()
* - java.lang.reflect.Executable.annotations
* - java.lang.reflect.Method.parameterAnnotations
* - java.lang.reflect.Method.annotationDefault
* - java.lang.reflect.Field.annotations
* @param clazz
* @param array
* @return ConstantPool associated with byte array, if array is null return
* constantpool associated with clazz
*/
public static ConstantPool getConstantPoolFromAnnotationBytes(Class<?> clazz, byte[] array) {
if (null == array) {
return getVMLangAccess().getConstantPool(clazz);
}
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + ((array.length * Unsafe.ARRAY_BYTE_INDEX_SCALE) - FJ9OBJECT_SIZE);
long ramCPAddr = 0;
if (FJ9OBJECT_SIZE == 4) {
/* Compressed object refs */
ramCPAddr = Integer.toUnsignedLong(Unsafe.getUnsafe().getInt(array, offset));
} else {
ramCPAddr = Unsafe.getUnsafe().getLong(array, offset);
}
Object internalCP = getVMLangAccess().createInternalConstantPool(ramCPAddr);
return getVMLangAccess().getConstantPool(internalCP);
}
}
13 changes: 2 additions & 11 deletions jcl/src/java.base/share/classes/java/lang/Class.java
Expand Up @@ -3591,20 +3591,11 @@ private AnnotationCache getAnnotationCache() {
if (annotationsData == null) {
annotationCacheResult = new AnnotationCache(null, buildAnnotations(null));
} else {
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + ((annotationsData.length * Unsafe.ARRAY_BYTE_INDEX_SCALE) - VM.FJ9OBJECT_SIZE);
long ramCPAddr = 0;
if (VM.FJ9OBJECT_SIZE == 4) {
/* Compressed object refs */
ramCPAddr = Integer.toUnsignedLong(unsafe.getInt(annotationsData, offset));
} else {
ramCPAddr = unsafe.getLong(annotationsData, offset);
}
Object internalCP = VM.getVMLangAccess().createInternalConstantPool(ramCPAddr);

ConstantPool cp = VM.getConstantPoolFromAnnotationBytes(this, annotationsData);
Annotation[] directAnnotations = sun.reflect.annotation.AnnotationParser.toArray(
sun.reflect.annotation.AnnotationParser.parseAnnotations(
annotationsData,
getConstantPool(internalCP),
cp,
this));

LinkedHashMap<Class<? extends Annotation>, Annotation> directAnnotationsMap = new LinkedHashMap<>(directAnnotations.length * 4 / 3);
Expand Down
92 changes: 43 additions & 49 deletions runtime/jcl/common/reflecthelp.c
Expand Up @@ -59,6 +59,20 @@ static J9WalkFieldAction countFieldIterator(J9ROMFieldShape *romField, J9Class *
static J9WalkFieldAction allFieldIterator(J9ROMFieldShape *romField, J9Class *declaringClass, void *userData);
static jmethodID reflectMethodToID(J9VMThread *vmThread, jobject reflectMethod);

/* Append J9ConstantPool* at end of array so Class.getAnnotationCache, java.lang.reflect.Method and
* java.lang.reflect.Field can use it to get a ConstantPool consistent with the annotation data in case of redefine
*/
static void
appendConstantPoolToByteArray(struct J9VMThread *vmThread, j9object_t byteArray, U_32 byteCount, J9ConstantPool *ramCP)
{
J9ConstantPool *ramCPPtr = (J9ConstantPool *)(I_8 *)J9JAVAARRAY_EA(vmThread, byteArray, byteCount, I_8);
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
*(U_32 *)ramCPPtr = (U_32)(UDATA)ramCP;
} else {
*(UDATA *)ramCPPtr = (UDATA)ramCP;
}
}

static UDATA
isConstructor(J9Method *ramMethod)
{
Expand All @@ -77,7 +91,7 @@ isConstructor(J9Method *ramMethod)
* If/when the annotation data is moved, these functions must be updated.
*/
static j9object_t
getAnnotationDataAsByteArray(struct J9VMThread *vmThread, U_32 *annotationData)
getAnnotationDataAsByteArray(struct J9VMThread *vmThread, U_32 *annotationData, struct J9ConstantPool *constantPool)
{
U_32 i = 0;
U_32 byteCount = *annotationData;
Expand All @@ -94,6 +108,10 @@ getAnnotationDataAsByteArray(struct J9VMThread *vmThread, U_32 *annotationData)
J9JAVAARRAYOFBYTE_STORE(vmThread, byteArray, i, byteData[i]);
}

if (NULL != constantPool) {
appendConstantPoolToByteArray(vmThread, byteArray, *annotationData, constantPool);
}

return byteArray;
}

Expand All @@ -104,7 +122,7 @@ getAnnotationDataFromROMMethodHelper(struct J9VMThread *vmThread, J9Method *ramM
J9ROMMethod *romMethod = (J9ROMMethod *) (ramMethod->bytecodes - sizeof(J9ROMMethod));
U_32 *annotationData = getAnnotationDataFromROMMethod(romMethod);
if (NULL != annotationData) {
result = getAnnotationDataAsByteArray(vmThread, annotationData);
result = getAnnotationDataAsByteArray(vmThread, annotationData, J9_CP_FROM_METHOD(ramMethod));
}
return result;
}
Expand All @@ -115,20 +133,7 @@ getClassAnnotationData(struct J9VMThread *vmThread, struct J9Class *declaringCla
j9object_t result = NULL;
U_32 *annotationData = getClassAnnotationsDataForROMClass(declaringClass->romClass);
if (NULL != annotationData) {
J9ConstantPool *ramCP = J9_CP_FROM_CLASS(declaringClass);
result = getAnnotationDataAsByteArray(vmThread, annotationData);
if (NULL != result) {
U_32 byteCount = *annotationData;
/* Append J9ConstantPool* at end of array so Class.getAnnotationCache can use it to
* get a ConstantPool consistent with the annotation data in case of redefine
*/
J9ConstantPool *ramCPPtr = (J9ConstantPool *)(I_8 *)J9JAVAARRAY_EA(vmThread, result, byteCount, I_8);
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
*(U_32 *)ramCPPtr = (U_32)(UDATA)ramCP;
} else {
*(UDATA *)ramCPPtr = (UDATA)ramCP;
}
}
result = getAnnotationDataAsByteArray(vmThread, annotationData, J9_CP_FROM_CLASS(declaringClass));
}
return result;
}
Expand All @@ -146,19 +151,8 @@ getClassTypeAnnotationsAsByteArray(JNIEnv *env, jclass jlClass)
struct J9Class *declaringClass = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, clazz);
U_32 *annotationData = getClassTypeAnnotationsDataForROMClass(declaringClass->romClass);
if (NULL != annotationData) {
J9ConstantPool *ramCP = J9_CP_FROM_CLASS(declaringClass);
j9object_t annotationsByteArray = getAnnotationDataAsByteArray(vmThread, annotationData);
j9object_t annotationsByteArray = getAnnotationDataAsByteArray(vmThread, annotationData, J9_CP_FROM_CLASS(declaringClass));
if (NULL != annotationsByteArray) {
U_32 byteCount = *annotationData;
/* Append J9ConstantPool* at end of array so Class.getAnnotationCache can use it to
* get a ConstantPool consistent with the annotation data in case of redefine
*/
J9ConstantPool *ramCPPtr = (J9ConstantPool *)(I_8 *)J9JAVAARRAY_EA(vmThread, annotationsByteArray, byteCount, I_8);
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
*(U_32 *)ramCPPtr = (U_32)(UDATA)ramCP;
} else {
*(UDATA *)ramCPPtr = (UDATA)ramCP;
}
result = vmThread->javaVM->internalVMFunctions->j9jni_createLocalRef(env, annotationsByteArray);
}
}
Expand All @@ -173,32 +167,32 @@ getFieldAnnotationData(struct J9VMThread *vmThread, struct J9Class *declaringCla
j9object_t result = NULL;
U_32 *annotationData = getFieldAnnotationsDataFromROMField(j9FieldID->field);
if ( NULL != annotationData ) {
result = getAnnotationDataAsByteArray(vmThread, annotationData);
result = getAnnotationDataAsByteArray(vmThread, annotationData, J9_CP_FROM_CLASS(declaringClass));
}
return result;
}

jbyteArray
getFieldTypeAnnotationsAsByteArray(JNIEnv *env, jobject jlrField)
{
jobject result = NULL;
j9object_t fieldObject = NULL;
J9VMThread *vmThread = (J9VMThread *) env;

enterVMFromJNI(vmThread);
fieldObject = J9_JNI_UNWRAP_REFERENCE(jlrField);
if (NULL != fieldObject) {
J9JNIFieldID *fieldID = vmThread->javaVM->reflectFunctions.idFromFieldObject(vmThread, NULL, fieldObject);
U_32 *annotationData = getFieldTypeAnnotationsDataFromROMField(fieldID->field);
if ( NULL != annotationData ) {
j9object_t annotationsByteArray = getAnnotationDataAsByteArray(vmThread, annotationData);
if (NULL != annotationsByteArray) {
result = vmThread->javaVM->internalVMFunctions->j9jni_createLocalRef(env, annotationsByteArray);
}
}
}
exitVMToJNI(vmThread);
return result;
jobject result = NULL;
j9object_t fieldObject = NULL;
J9VMThread *vmThread = (J9VMThread *) env;

enterVMFromJNI(vmThread);
fieldObject = J9_JNI_UNWRAP_REFERENCE(jlrField);
if (NULL != fieldObject) {
J9JNIFieldID *fieldID = vmThread->javaVM->reflectFunctions.idFromFieldObject(vmThread, NULL, fieldObject);
U_32 *annotationData = getFieldTypeAnnotationsDataFromROMField(fieldID->field);
if ( NULL != annotationData ) {
j9object_t annotationsByteArray = getAnnotationDataAsByteArray(vmThread, annotationData, NULL);
if (NULL != annotationsByteArray) {
result = vmThread->javaVM->internalVMFunctions->j9jni_createLocalRef(env, annotationsByteArray);
}
}
}
exitVMToJNI(vmThread);
return result;
}

/**
Expand Down Expand Up @@ -1936,7 +1930,7 @@ getRecordComponentsHelper(JNIEnv *env, jobject cls)
/* byte[] annotations */
if (recordComponentHasAnnotations(recordComponent)) {
U_32* annotationData = getRecordComponentAnnotationData(recordComponent);
j9object_t byteArray = getAnnotationDataAsByteArray(vmThread, annotationData);
j9object_t byteArray = getAnnotationDataAsByteArray(vmThread, annotationData, NULL);
if (NULL != vmThread->currentException) {
DROP_OBJECT_IN_SPECIAL_FRAME(vmThread); /* recordComponentObject */
goto done;
Expand All @@ -1948,7 +1942,7 @@ getRecordComponentsHelper(JNIEnv *env, jobject cls)
/* byte[] typeAnnotations */
if (recordComponentHasTypeAnnotations(recordComponent)) {
U_32* typeAnnotationData = getRecordComponentTypeAnnotationData(recordComponent);
j9object_t byteArray = getAnnotationDataAsByteArray(vmThread, typeAnnotationData);
j9object_t byteArray = getAnnotationDataAsByteArray(vmThread, typeAnnotationData, NULL);
if (NULL != vmThread->currentException) {
DROP_OBJECT_IN_SPECIAL_FRAME(vmThread); /* recordComponentObject */
goto done;
Expand Down

0 comments on commit f263056

Please sign in to comment.