From 3037ba8427b2b06021ebb4fecb7b5763ed0208f0 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 2 Dec 2021 20:11:12 +0000 Subject: [PATCH 1/2] Revert "Revert "Fix inconsistency between J9Class and annotation data when redefine"" This reverts commit 06ae5711cfba307e681e74302c844df3b4b8a4ee. Closes: #10026 Signed-off-by: Eric Yang eric.yang@ibm.com --- .../com/ibm/oti/reflect/AnnotationParser.java | 14 +- .../ibm/oti/reflect/TypeAnnotationParser.java | 32 ++- .../share/classes/com/ibm/oti/vm/VM.java | 7 + .../classes/com/ibm/oti/vm/VMLangAccess.java | 36 +++- .../share/classes/java/lang/Class.java | 16 +- ...amClass.java => InternalConstantPool.java} | 12 +- .../share/classes/java/lang/VMAccess.java | 55 +++-- .../lang/invoke/MethodHandleResolver.java | 70 +++---- runtime/jcl/common/com_ibm_oti_vm_VM.c | 14 +- runtime/jcl/common/java_lang_Access.c | 27 ++- runtime/jcl/common/reflecthelp.c | 60 ++++-- runtime/jcl/common/sun_reflect_ConstantPool.c | 52 ++--- runtime/jcl/exports.cmake | 1 + runtime/jcl/uma/se7_exports.xml | 1 + runtime/oti/jclprots.h | 7 + runtime/oti/vmconstantpool.xml | 4 +- runtime/tests/jvmtitests/agent/tests.c | 3 +- runtime/tests/jvmtitests/exports.cmake | 3 +- runtime/tests/jvmtitests/include/jvmti_test.h | 1 + runtime/tests/jvmtitests/module.xml | 3 +- runtime/tests/jvmtitests/src/CMakeLists.txt | 1 + .../ibm/jvmti/tests/redefineClasses/rc021.c | 77 +++++++ .../jvmtitests/jvmtitests_hcr.xml | 7 +- .../cmdLineTests/jvmtitests/playlist.xml | 6 + .../jvmti/tests/redefineClasses/rc021.java | 195 ++++++++++++++++++ .../rc021_testAnnotatedType_O.java | 46 +++++ .../rc021_testAnnotatedType_R.java | 38 ++++ .../rc021_testAnnotationCache_O.java | 46 +++++ .../rc021_testAnnotationCache_R.java | 30 +++ 29 files changed, 738 insertions(+), 126 deletions(-) rename jcl/src/java.base/share/classes/java/lang/{InternalRamClass.java => InternalConstantPool.java} (88%) create mode 100644 runtime/tests/jvmtitests/src/com/ibm/jvmti/tests/redefineClasses/rc021.c create mode 100644 test/functional/cmdLineTests/jvmtitests/src/com/ibm/jvmti/tests/redefineClasses/rc021.java create mode 100644 test/functional/cmdLineTests/jvmtitests/src/com/ibm/jvmti/tests/redefineClasses/rc021_testAnnotatedType_O.java create mode 100644 test/functional/cmdLineTests/jvmtitests/src/com/ibm/jvmti/tests/redefineClasses/rc021_testAnnotatedType_R.java create mode 100644 test/functional/cmdLineTests/jvmtitests/src/com/ibm/jvmti/tests/redefineClasses/rc021_testAnnotationCache_O.java create mode 100644 test/functional/cmdLineTests/jvmtitests/src/com/ibm/jvmti/tests/redefineClasses/rc021_testAnnotationCache_R.java diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java index 59b9d8d0b4c..a400dc32a0f 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java +++ b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/AnnotationParser.java @@ -2,7 +2,7 @@ package com.ibm.oti.reflect; /******************************************************************************* - * Copyright (c) 2010, 2020 IBM Corp. and others + * Copyright (c) 2010, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -33,6 +33,7 @@ /*[ELSE]*/ import sun.reflect.ConstantPool; /*[ENDIF]*/ +import com.ibm.oti.vm.VM; public class AnnotationParser { @@ -73,6 +74,7 @@ public static Object parseDefaultValue(Method method) { if (elementValueData == null) return null; ByteBuffer buf = ByteBuffer.wrap(elementValueData); Class clazz = method.getDeclaringClass(); + Object internalConstantPool = VM.getVMLangAccess().getInternalConstantPoolFromClass(clazz); /* The AnnotationParser boxes primitive return types */ Class returnType = method.getReturnType(); @@ -95,14 +97,15 @@ public static Object parseDefaultValue(Method method) { returnType = Double.class; } } - return sun.reflect.annotation.AnnotationParser.parseMemberValue(returnType, buf, getConstantPool(clazz), clazz); + return sun.reflect.annotation.AnnotationParser.parseMemberValue(returnType, buf, getConstantPool(internalConstantPool), clazz); } public static Annotation[] parseAnnotations(byte[] annotationsData, Class clazz) { + Object internalConstantPool = VM.getVMLangAccess().getInternalConstantPoolFromClass(clazz); return sun.reflect.annotation.AnnotationParser.toArray( sun.reflect.annotation.AnnotationParser.parseAnnotations( annotationsData, - getConstantPool(clazz), + getConstantPool(internalConstantPool), clazz)); } @@ -112,7 +115,7 @@ public static Annotation[] parseAnnotations(byte[] annotationsData, Class clazz) private static native byte[] getParameterAnnotationsData(Constructor constructor); private static native byte[] getParameterAnnotationsData(Method method); private static native byte[] getDefaultValueData(Method method); - static native ConstantPool getConstantPool(Class clazz); + static native ConstantPool getConstantPool(Object internalConstantPool); private static native byte[] getAnnotationsDataImpl(java.lang.Class clazz); private static Annotation[][] parseParameterAnnotations(byte[] annotationsData, Class declaringClass, int parametersCount) { @@ -123,6 +126,7 @@ private static Annotation[][] parseParameterAnnotations(byte[] annotationsData, } return annotations; } - return sun.reflect.annotation.AnnotationParser.parseParameterAnnotations(annotationsData, getConstantPool(declaringClass), declaringClass); + Object internalConstantPool = VM.getVMLangAccess().getInternalConstantPoolFromClass(declaringClass); + return sun.reflect.annotation.AnnotationParser.parseParameterAnnotations(annotationsData, getConstantPool(internalConstantPool), declaringClass); } } diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/TypeAnnotationParser.java b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/TypeAnnotationParser.java index d19d87abd99..e4722e50f40 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/reflect/TypeAnnotationParser.java +++ b/jcl/src/java.base/share/classes/com/ibm/oti/reflect/TypeAnnotationParser.java @@ -3,9 +3,15 @@ import java.lang.reflect.AnnotatedType; import java.lang.reflect.Constructor; +import com.ibm.oti.vm.VM; +/*[IF JAVA_SPEC_VERSION == 8] +import sun.misc.Unsafe; +/*[ELSE]*/ +import jdk.internal.misc.Unsafe; +/*[ENDIF]*/ /******************************************************************************* - * Copyright (c) 2014, 2014 IBM Corp. and others + * Copyright (c) 2014, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -99,7 +105,17 @@ private static byte[] getAttributeData(Class clazz) { */ public static AnnotatedType[] buildAnnotatedInterfaces(Class clazz) { byte[] attr = getAttributeData(clazz); - AnnotatedType[] annotatedInterfaces = sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedInterfaces(attr, AnnotationParser.getConstantPool(clazz), 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); return annotatedInterfaces; } /** @@ -109,7 +125,17 @@ public static AnnotatedType[] buildAnnotatedInterfaces(Class clazz) { */ public static AnnotatedType buildAnnotatedSupertype(Class clazz) { byte[] attr = getAttributeData(clazz); - AnnotatedType annotatedSuperclass = sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedSuperclass(attr, AnnotationParser.getConstantPool(clazz), 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); return annotatedSuperclass; } } diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java b/jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java index fa6c22fc0d5..8a56626945c 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java +++ b/jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java @@ -572,4 +572,11 @@ public static int markCurrentThreadAsSystem() private static native int markCurrentThreadAsSystemImpl(); +/** + * Gets the J9ConstantPool address from a J9Class address + * @param j9clazz J9Class address + * @return Address of J9ConstantPool + */ +public static native long getJ9ConstantPoolFromJ9Class(long j9clazz); + } diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/vm/VMLangAccess.java b/jcl/src/java.base/share/classes/com/ibm/oti/vm/VMLangAccess.java index 5dd7b76e5ec..86e26264b2c 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/vm/VMLangAccess.java +++ b/jcl/src/java.base/share/classes/com/ibm/oti/vm/VMLangAccess.java @@ -129,20 +129,38 @@ public interface VMLangAccess { /*[ENDIF]*/ /** - * Returns an InternalRamClass object. - * - * @param addr - the native addr of the J9Class - * @return An InternalRamClass object - */ - public Object createInternalRamClass(long addr); - + * Returns an InternalConstantPool object. + * + * @param addr - the native addr of the J9ConstantPool + * @return An InternalConstantPool object + */ + public Object createInternalConstantPool(long addr); + /** * Returns a ConstantPool object * - * @param internalRamClass An object ref to an internalRamClass + * @param internalConstantPool An object ref to an InternalConstantPool * @return ConstantPool instance */ - public ConstantPool getConstantPool(Object internalRamClass); + public ConstantPool getConstantPool(Object internalConstantPool); + + /** + * Returns an InternalConstantPool object from a J9Class address. The ConstantPool + * natives expect an InternalConstantPool as the constantPoolOop parameter. + * + * @param j9class the native address of the J9Class + * @return InternalConstantPool a wrapper for a j9constantpool + */ + public Object getInternalConstantPoolFromJ9Class(long j9class); + + /** + * Returns an InternalConstantPool object from a Class. The ConstantPool + * natives expect an InternalConstantPool as the constantPoolOop parameter. + * + * @param clazz the Class to fetch the constant pool from + * @return an InternalConstantPool wrapper for a j9constantpool + */ + public Object getInternalConstantPoolFromClass(Class clazz); /*[IF Sidecar19-SE]*/ /** diff --git a/jcl/src/java.base/share/classes/java/lang/Class.java b/jcl/src/java.base/share/classes/java/lang/Class.java index 39d6dc343cb..842a75a7674 100644 --- a/jcl/src/java.base/share/classes/java/lang/Class.java +++ b/jcl/src/java.base/share/classes/java/lang/Class.java @@ -3349,10 +3349,20 @@ 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); + Annotation[] directAnnotations = sun.reflect.annotation.AnnotationParser.toArray( sun.reflect.annotation.AnnotationParser.parseAnnotations( annotationsData, - getConstantPool(), + getConstantPool(internalCP), this)); LinkedHashMap, Annotation> directAnnotationsMap = new LinkedHashMap<>(directAnnotations.length * 4 / 3); @@ -5049,8 +5059,8 @@ Object setMethodHandleCache(Object cache) { return result; } -ConstantPool getConstantPool() { - return SharedSecrets.getJavaLangAccess().getConstantPool(this); +ConstantPool getConstantPool(Object internalCP) { + return VM.getVMLangAccess().getConstantPool(internalCP); } /*[IF Sidecar19-SE]*/ diff --git a/jcl/src/java.base/share/classes/java/lang/InternalRamClass.java b/jcl/src/java.base/share/classes/java/lang/InternalConstantPool.java similarity index 88% rename from jcl/src/java.base/share/classes/java/lang/InternalRamClass.java rename to jcl/src/java.base/share/classes/java/lang/InternalConstantPool.java index 3adffae4800..21c96d91313 100644 --- a/jcl/src/java.base/share/classes/java/lang/InternalRamClass.java +++ b/jcl/src/java.base/share/classes/java/lang/InternalConstantPool.java @@ -1,7 +1,7 @@ /*[INCLUDE-IF Sidecar18-SE]*/ package java.lang; /******************************************************************************* - * Copyright (c) 2017, 2017 IBM Corp. and others + * Copyright (c) 2017, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -23,14 +23,14 @@ *******************************************************************************/ /** - * Represents the internal J9Class - * + * Represents the internal J9ConstantPool + * */ -final class InternalRamClass { +final class InternalConstantPool { @SuppressWarnings("unused") private final long vmref; - - public InternalRamClass(long addr) { + + public InternalConstantPool(long addr) { vmref = addr; } } diff --git a/jcl/src/java.base/share/classes/java/lang/VMAccess.java b/jcl/src/java.base/share/classes/java/lang/VMAccess.java index eca90ff41d5..fa416f52443 100644 --- a/jcl/src/java.base/share/classes/java/lang/VMAccess.java +++ b/jcl/src/java.base/share/classes/java/lang/VMAccess.java @@ -34,6 +34,7 @@ import com.ibm.oti.vm.*; +import com.ibm.jit.JITHelpers; /** * Helper class to allow privileged access to classes @@ -185,26 +186,56 @@ public Package getSystemPackage(String name) { /*[ENDIF]*/ /** - * Returns a InternalRamClass object. - * - * @param addr - the native addr of the J9Class - * @return A InternalRamClass reference object - */ + * Returns an InternalConstantPool object. + * + * @param addr - the native addr of the J9ConstantPool + * @return An InternalConstantPool reference object + */ @Override - public Object createInternalRamClass(long addr) { - return new InternalRamClass(addr); + public Object createInternalConstantPool(long addr) { + return new InternalConstantPool(addr); } - + /** * Returns a ConstantPool object - * @param internalRamClass An object ref to a j9class + * @param internalConstantPool An object ref to a j9constantpool * @return ConstantPool instance */ @Override - public ConstantPool getConstantPool(Object internalRamClass) { - return Access.getConstantPool(internalRamClass); + public ConstantPool getConstantPool(Object internalConstantPool) { + return Access.getConstantPool(internalConstantPool); } - + + /** + * Returns an InternalConstantPool object from a J9Class address. The ConstantPool + * natives expect an InternalConstantPool as the constantPoolOop parameter. + * + * @param j9class the native address of the J9Class + * @return InternalConstantPool a wrapper for a j9constantpool + */ + public Object getInternalConstantPoolFromJ9Class(long j9class) { + long j9constantpool = VM.getJ9ConstantPoolFromJ9Class(j9class); + return createInternalConstantPool(j9constantpool); + } + + /** + * Returns an InternalConstantPool object from a Class. The ConstantPool + * natives expect an InternalConstantPool as the constantPoolOop parameter. + * + * @param clazz the Class to fetch the constant pool from + * @return an InternalConstantPool wrapper for a j9constantpool + */ + public Object getInternalConstantPoolFromClass(Class clazz) { + JITHelpers helpers = JITHelpers.getHelpers(); + long j9class; + if (helpers.is32Bit()) { + j9class = helpers.getJ9ClassFromClass32(clazz); + } else { + j9class = helpers.getJ9ClassFromClass64(clazz); + } + return getInternalConstantPoolFromJ9Class(j9class); + } + /*[IF Sidecar19-SE]*/ @Override public void addPackageToList(java.lang.Class newClass, ClassLoader loader) { diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandleResolver.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandleResolver.java index e765f2b3519..0fc8755bc85 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandleResolver.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandleResolver.java @@ -59,49 +59,49 @@ final class MethodHandleResolver { /* * Return the result of J9_CP_TYPE(J9Class->romClass->cpShapeDescription, index) */ - private static final native int getCPTypeAt(Object internalRamClass, int index); + private static final native int getCPTypeAt(Object internalConstantPool, int index); /* * sun.reflect.ConstantPool doesn't have a getMethodTypeAt method. This is the * equivalent for MethodType. */ - private static final native MethodType getCPMethodTypeAt(Object internalRamClass, int index); + private static final native MethodType getCPMethodTypeAt(Object internalConstantPool, int index); /* * sun.reflect.ConstantPool doesn't have a getMethodHandleAt method. This is the * equivalent for MethodHandle. */ - private static final native MethodHandle getCPMethodHandleAt(Object internalRamClass, int index); + private static final native MethodHandle getCPMethodHandleAt(Object internalConstantPool, int index); /** * Get the class name from a constant pool class element, which is located - * at the specified index in clazz's constant pool. + * at the specified index in internalConstantPool. * - * @param an instance of class - its constant pool is accessed - * @param the constant pool index + * @param internalConstantPool the constant pool as an InternalConstantPool object + * @param index the constant pool index * * @return instance of String which contains the class name or NULL in * case of error * - * @throws NullPointerException if clazz is null + * @throws NullPointerException if internalConstantPool is null * @throws IllegalArgumentException if index has wrong constant pool type */ - private static final native String getCPClassNameAt(Class clazz, int index); + private static final native String getCPClassNameAt(Object internalConstantPool, int index); /*[IF JAVA_SPEC_VERSION >= 11]*/ /* * sun.reflect.ConstantPool doesn't have a getConstantDynamicAt method. This is the * equivalent for ConstantDynamic. */ - private static final native Object getCPConstantDynamicAt(Object internalRamClass, int index); + private static final native Object getCPConstantDynamicAt(Object internalConstantPool, int index); @SuppressWarnings("unused") private static final Object resolveConstantDynamic(long j9class, String name, String fieldDescriptor, long bsmData) throws Throwable { Object result = null; VMLangAccess access = VM.getVMLangAccess(); - Object internalRamClass = access.createInternalRamClass(j9class); + Object internalConstantPool = access.getInternalConstantPoolFromJ9Class(j9class); Class classObject = getClassFromJ9Class(j9class); Class typeClass = fromFieldDescriptorString(fieldDescriptor, access.getClassloader(classObject)); @@ -110,7 +110,7 @@ private static final Object resolveConstantDynamic(long j9class, String name, St int bsmArgCount = UNSAFE.getShort(bsmData + BSM_ARGUMENT_COUNT_OFFSET); long bsmArgs = bsmData + BSM_ARGUMENTS_OFFSET; - MethodHandle bsm = getCPMethodHandleAt(internalRamClass, bsmIndex); + MethodHandle bsm = getCPMethodHandleAt(internalConstantPool, bsmIndex); if (null == bsm) { /*[MSG "K05cd", "unable to resolve 'bootstrap_method_ref' in '{0}' at index {1}"]*/ throw new NullPointerException(Msg.getString("K05cd", classObject.toString(), bsmIndex)); //$NON-NLS-1$ @@ -131,7 +131,7 @@ private static final Object resolveConstantDynamic(long j9class, String name, St /*[IF OPENJDK_METHODHANDLES]*/ Object[] staticArgs = new Object[bsmArgCount]; for (int i = 0; i < bsmArgCount; i++) { - staticArgs[i] = getAdditionalBsmArg(access, internalRamClass, classObject, bsm, bsmArgs, bsmTypeArgCount, i); + staticArgs[i] = getAdditionalBsmArg(access, internalConstantPool, classObject, bsm, bsmArgs, bsmTypeArgCount, i); } /*[ELSE] OPENJDK_METHODHANDLES*/ Object[] staticArgs = new Object[BSM_OPTIONAL_ARGUMENTS_START_INDEX + bsmArgCount]; @@ -140,7 +140,7 @@ private static final Object resolveConstantDynamic(long j9class, String name, St staticArgs[BSM_NAME_ARGUMENT_INDEX] = name; staticArgs[BSM_TYPE_ARGUMENT_INDEX] = typeClass; for (int i = 0; i < bsmArgCount; i++) { - staticArgs[BSM_OPTIONAL_ARGUMENTS_START_INDEX + i] = getAdditionalBsmArg(access, internalRamClass, classObject, bsm, bsmArgs, bsmTypeArgCount, i); + staticArgs[BSM_OPTIONAL_ARGUMENTS_START_INDEX + i] = getAdditionalBsmArg(access, internalConstantPool, classObject, bsm, bsmArgs, bsmTypeArgCount, i); } /*[ENDIF] OPENJDK_METHODHANDLES*/ @@ -227,7 +227,7 @@ private static final Object invokeBsm(MethodHandle bsm, Object[] staticArgs) thr private static final Object resolveInvokeDynamic(long j9class, String name, String methodDescriptor, long bsmData) throws Throwable { /*[IF OPENJDK_METHODHANDLES]*/ VMLangAccess access = VM.getVMLangAccess(); - Object internalRamClass = access.createInternalRamClass(j9class); + Object internalConstantPool = access.getInternalConstantPoolFromJ9Class(j9class); Class classObject = getClassFromJ9Class(j9class); MethodType type = MethodTypeHelper.vmResolveFromMethodDescriptorString(methodDescriptor, access.getClassloader(classObject), null); @@ -237,7 +237,7 @@ private static final Object resolveInvokeDynamic(long j9class, String name, Stri int bsmIndex = UNSAFE.getShort(bsmData); int bsmArgCount = UNSAFE.getShort(bsmData + BSM_ARGUMENT_COUNT_OFFSET); long bsmArgs = bsmData + BSM_ARGUMENTS_OFFSET; - MethodHandle bsm = getCPMethodHandleAt(internalRamClass, bsmIndex); + MethodHandle bsm = getCPMethodHandleAt(internalConstantPool, bsmIndex); if (null == bsm) { /*[MSG "K05cd", "unable to resolve 'bootstrap_method_ref' in '{0}' at index {1}"]*/ throw new NullPointerException(Msg.getString("K05cd", classObject.toString(), bsmIndex)); //$NON-NLS-1$ @@ -247,7 +247,7 @@ private static final Object resolveInvokeDynamic(long j9class, String name, Stri /* Static optional arguments */ int bsmTypeArgCount = bsm.type().parameterCount(); for (int i = 0; i < bsmArgCount; i++) { - staticArgs[i] = getAdditionalBsmArg(access, internalRamClass, classObject, bsm, bsmArgs, bsmTypeArgCount, i); + staticArgs[i] = getAdditionalBsmArg(access, internalConstantPool, classObject, bsm, bsmArgs, bsmTypeArgCount, i); } Object[] appendixResult = new Object[1]; @@ -278,7 +278,7 @@ private static final Object resolveInvokeDynamic(long j9class, String name, Stri try { /*[ENDIF] JAVA_SPEC_VERSION < 11 */ VMLangAccess access = VM.getVMLangAccess(); - Object internalRamClass = access.createInternalRamClass(j9class); + Object internalConstantPool = access.getInternalConstantPoolFromJ9Class(j9class); Class classObject = getClassFromJ9Class(j9class); type = MethodTypeHelper.vmResolveFromMethodDescriptorString(methodDescriptor, access.getClassloader(classObject), null); @@ -293,7 +293,7 @@ private static final Object resolveInvokeDynamic(long j9class, String name, Stri int bsmIndex = UNSAFE.getShort(bsmData); int bsmArgCount = UNSAFE.getShort(bsmData + BSM_ARGUMENT_COUNT_OFFSET); long bsmArgs = bsmData + BSM_ARGUMENTS_OFFSET; - MethodHandle bsm = getCPMethodHandleAt(internalRamClass, bsmIndex); + MethodHandle bsm = getCPMethodHandleAt(internalConstantPool, bsmIndex); if (null == bsm) { /*[MSG "K05cd", "unable to resolve 'bootstrap_method_ref' in '{0}' at index {1}"]*/ throw new NullPointerException(Msg.getString("K05cd", classObject.toString(), bsmIndex)); //$NON-NLS-1$ @@ -307,7 +307,7 @@ private static final Object resolveInvokeDynamic(long j9class, String name, Stri /* Static optional arguments */ int bsmTypeArgCount = bsm.type().parameterCount(); for (int i = 0; i < bsmArgCount; i++) { - staticArgs[BSM_OPTIONAL_ARGUMENTS_START_INDEX + i] = getAdditionalBsmArg(access, internalRamClass, classObject, bsm, bsmArgs, bsmTypeArgCount, i); + staticArgs[BSM_OPTIONAL_ARGUMENTS_START_INDEX + i] = getAdditionalBsmArg(access, internalConstantPool, classObject, bsm, bsmArgs, bsmTypeArgCount, i); } /*[IF JAVA_SPEC_VERSION >= 11]*/ @@ -536,7 +536,7 @@ private static final Class fromFieldDescriptorString(String fieldDescriptor, /** * Retrieve a static argument of the bootstrap method at argIndex from constant pool * @param access - * @param internalRamClass + * @param internalConstantPool * @param classObject RAM class object * @param bsm bootstrap method * @param bsmArgs starting address of bootstrap arguments in the RAM class call site @@ -546,27 +546,27 @@ private static final Class fromFieldDescriptorString(String fieldDescriptor, * @return additional argument from the constant pool * @throws Throwable any throwable will be handled by the caller */ - private static final Object getAdditionalBsmArg(VMLangAccess access, Object internalRamClass, Class classObject, MethodHandle bsm, long bsmArgs, int bsmTypeArgCount, int argIndex) throws Throwable { + private static final Object getAdditionalBsmArg(VMLangAccess access, Object internalConstantPool, Class classObject, MethodHandle bsm, long bsmArgs, int bsmTypeArgCount, int argIndex) throws Throwable { /* Check if we need to treat the last parameter specially when handling primitives. * The type of the varargs array will determine how primitive ints from the constantpool * get boxed: {Boolean, Byte, Short, Character or Integer}. */ boolean treatLastArgAsVarargs = bsm.isVarargsCollector(); - /* internalRamClass is not a j.l.Class object but the ConstantPool natives know how to - * get the internal constantPool from the j9class - */ - ConstantPool cp = access.getConstantPool(internalRamClass); + /* The ConstantPool natives expect an InternalConstantPool to extract the j9constantpool + * from. + */ + ConstantPool cp = access.getConstantPool(internalConstantPool); int staticArgIndex = BSM_OPTIONAL_ARGUMENTS_START_INDEX + argIndex; short index = UNSAFE.getShort(bsmArgs + (argIndex * BSM_ARGUMENT_SIZE)); - int cpType = getCPTypeAt(internalRamClass, index); + int cpType = getCPTypeAt(internalConstantPool, index); Object cpEntry = null; switch (cpType) { case 1: cpEntry = cp.getClassAt(index); if (cpEntry == null) { - throw throwNoClassDefFoundError(classObject, index); + throw throwNoClassDefFoundError(internalConstantPool, index); } break; case 2: @@ -609,14 +609,14 @@ private static final Object getAdditionalBsmArg(VMLangAccess access, Object inte cpEntry = cp.getDoubleAt(index); break; case 13: - cpEntry = getCPMethodTypeAt(internalRamClass, index); + cpEntry = getCPMethodTypeAt(internalConstantPool, index); break; case 14: - cpEntry = getCPMethodHandleAt(internalRamClass, index); + cpEntry = getCPMethodHandleAt(internalConstantPool, index); break; /*[IF JAVA_SPEC_VERSION >= 11]*/ case 17: - cpEntry = getCPConstantDynamicAt(internalRamClass, index); + cpEntry = getCPConstantDynamicAt(internalConstantPool, index); break; /*[ENDIF] JAVA_SPEC_VERSION >= 11 */ default: @@ -629,19 +629,19 @@ private static final Object getAdditionalBsmArg(VMLangAccess access, Object inte /** * Retrieve the class name of the constant pool class element located at the specified - * index in clazz's constant pool. Then, throw a NoClassDefFoundError with the cause + * index in internalConstantPool. Then, throw a NoClassDefFoundError with the cause * set as ClassNotFoundException. The message of NoClassDefFoundError and * ClassNotFoundException contains the name of the class, which couldn't be found. * - * @param an instance of Class - its constant pool is accessed - * @param integer value of the constant pool index + * @param internalConstantPool the constant pool as an InternalConstantPool object + * @param index the integer value of the constant pool index * * @return Throwable to prevent any fall through case * * @throws NoClassDefFoundError with the cause set as ClassNotFoundException */ - private static final Throwable throwNoClassDefFoundError(Class clazz, int index) { - String className = getCPClassNameAt(clazz, index); + private static final Throwable throwNoClassDefFoundError(Object internalConstantPool, int index) { + String className = getCPClassNameAt(internalConstantPool, index); NoClassDefFoundError noClassDefFoundError = new NoClassDefFoundError(className); noClassDefFoundError.initCause(new ClassNotFoundException(className)); throw noClassDefFoundError; diff --git a/runtime/jcl/common/com_ibm_oti_vm_VM.c b/runtime/jcl/common/com_ibm_oti_vm_VM.c index 1f8e79b29cb..9b9c485eccb 100644 --- a/runtime/jcl/common/com_ibm_oti_vm_VM.c +++ b/runtime/jcl/common/com_ibm_oti_vm_VM.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2018 IBM Corp. and others + * Copyright (c) 1998, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -156,3 +156,15 @@ Java_com_ibm_oti_vm_VM_markCurrentThreadAsSystemImpl(JNIEnv *env) return rc; } + +/** + * Gets the J9ConstantPool address from a J9Class address + * @param j9clazz J9Class address + * @return address of J9ConstantPool + */ +jlong JNICALL +Java_com_ibm_oti_vm_VM_getJ9ConstantPoolFromJ9Class(JNIEnv *env, jclass unused, jlong j9clazz) +{ + J9Class *clazz = (J9Class *)(IDATA)j9clazz; + return *(jlong *)&clazz->ramConstantPool; +} diff --git a/runtime/jcl/common/java_lang_Access.c b/runtime/jcl/common/java_lang_Access.c index eb2d0b86f1f..d29ed145d11 100644 --- a/runtime/jcl/common/java_lang_Access.c +++ b/runtime/jcl/common/java_lang_Access.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1998, 2014 IBM Corp. and others + * Copyright (c) 1998, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -32,7 +32,7 @@ * * @param env The current thread. * @param unusedClass See note above - this parameter should not be used. - * @param classToIntrospect The Class instance the ConstantPool should represent. + * @param classToIntrospect The Class or InternalConstantPool instance the ConstantPool should represent. * * @return a ConstantPool object reference or NULL on error. */ @@ -42,6 +42,10 @@ Java_java_lang_Access_getConstantPool(JNIEnv *env, jclass unusedClass, jobject c jclass sun_reflect_ConstantPool = JCL_CACHE_GET(env,CLS_sun_reflect_ConstantPool); jfieldID constantPoolOop; jobject constantPool; + J9VMThread *vmThread = (J9VMThread *)env; + J9InternalVMFunctions *vmFunctions = vmThread->javaVM->internalVMFunctions; + J9MemoryManagerFunctions *gcFunctions = vmThread->javaVM->memoryManagerFunctions; + j9object_t classObject = NULL; /* lazy-initialize the cached field IDs */ if (NULL == sun_reflect_ConstantPool) { @@ -57,6 +61,25 @@ Java_java_lang_Access_getConstantPool(JNIEnv *env, jclass unusedClass, jobject c return NULL; } + /* if this method is called with java/lang/Class, allocate an InternalConstantPool and store the J9ConstantPool */ + vmFunctions->internalEnterVMFromJNI(vmThread); + classObject = J9_JNI_UNWRAP_REFERENCE(classToIntrospect); + if (J9VMJAVALANGCLASS_OR_NULL(vmThread->javaVM) == J9OBJECT_CLAZZ(vmThread, classObject)) { + J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, classObject); + J9ConstantPool *constantPool = (J9ConstantPool *)clazz->ramConstantPool; + J9Class *internalConstantPool = J9VMJAVALANGINTERNALCONSTANTPOOL_OR_NULL(vmThread->javaVM); + Assert_JCL_notNull(internalConstantPool); + j9object_t internalConstantPoolObject = gcFunctions->J9AllocateObject(vmThread, internalConstantPool, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE); + if (NULL == internalConstantPoolObject) { + vmFunctions->setHeapOutOfMemoryError(vmThread); + vmFunctions->internalExitVMToJNI(vmThread); + return NULL; + } + J9VMJAVALANGINTERNALCONSTANTPOOL_SET_VMREF(vmThread, internalConstantPoolObject, constantPool); + classToIntrospect = vmFunctions->j9jni_createLocalRef(env, internalConstantPoolObject); + } + vmFunctions->internalExitVMToJNI(vmThread); + /* and set the private constantPoolOop member */ constantPoolOop = JCL_CACHE_GET(env, FID_sun_reflect_ConstantPool_constantPoolOop); (*env)->SetObjectField(env, constantPool, constantPoolOop, classToIntrospect); diff --git a/runtime/jcl/common/reflecthelp.c b/runtime/jcl/common/reflecthelp.c index 7f996952587..a01bb415605 100644 --- a/runtime/jcl/common/reflecthelp.c +++ b/runtime/jcl/common/reflecthelp.c @@ -77,7 +77,7 @@ getAnnotationDataAsByteArray(struct J9VMThread *vmThread, U_32 *annotationData) U_32 byteCount = *annotationData; U_8 *byteData = (U_8 *)(annotationData + 1); j9object_t byteArray = vmThread->javaVM->memoryManagerFunctions->J9AllocateIndexableObject( - vmThread, vmThread->javaVM->byteArrayClass, byteCount, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE); + vmThread, vmThread->javaVM->byteArrayClass, byteCount + J9VMTHREAD_OBJECT_HEADER_SIZE(vmThread), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE); if (NULL == byteArray) { vmThread->javaVM->internalVMFunctions->setHeapOutOfMemoryError(vmThread); return NULL; @@ -109,7 +109,20 @@ 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; + } + } } return result; } @@ -117,24 +130,35 @@ getClassAnnotationData(struct J9VMThread *vmThread, struct J9Class *declaringCla jbyteArray getClassTypeAnnotationsAsByteArray(JNIEnv *env, jclass jlClass) { - jobject result = NULL; - j9object_t clazz = NULL; - J9VMThread *vmThread = (J9VMThread *) env; + jobject result = NULL; + j9object_t clazz = NULL; + J9VMThread *vmThread = (J9VMThread *) env; - enterVMFromJNI(vmThread); - clazz = J9_JNI_UNWRAP_REFERENCE(jlClass); - if (NULL != clazz) { - struct J9Class *declaringClass = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, clazz); - U_32 *annotationData = getClassTypeAnnotationsDataForROMClass(declaringClass->romClass); - if (NULL != annotationData) { - j9object_t annotationsByteArray = getAnnotationDataAsByteArray(vmThread, annotationData); - if (NULL != annotationsByteArray) { - result = vmThread->javaVM->internalVMFunctions->j9jni_createLocalRef(env, annotationsByteArray); - } - } - } - exitVMToJNI(vmThread); - return result; + enterVMFromJNI(vmThread); + clazz = J9_JNI_UNWRAP_REFERENCE(jlClass); + if (NULL != clazz) { + 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); + 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); + } + } + } + exitVMToJNI(vmThread); + return result; } j9object_t diff --git a/runtime/jcl/common/sun_reflect_ConstantPool.c b/runtime/jcl/common/sun_reflect_ConstantPool.c index cd6eee69849..766f7b3eb1b 100644 --- a/runtime/jcl/common/sun_reflect_ConstantPool.c +++ b/runtime/jcl/common/sun_reflect_ConstantPool.c @@ -28,7 +28,7 @@ #include "jniidcacheinit.h" #include "j9.h" -#define J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, j9ClassRef) J9VMJAVALANGINTERNALRAMCLASS_VMREF(vmThread, J9_JNI_UNWRAP_REFERENCE(j9ClassRef)) +#define J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, j9ClassRef) J9VMJAVALANGINTERNALCONSTANTPOOL_VMREF(vmThread, J9_JNI_UNWRAP_REFERENCE(j9ClassRef)) typedef enum { OK, @@ -47,12 +47,12 @@ clearException(J9VMThread *vmThread) static SunReflectCPResult getRAMConstantRefAndType(J9VMThread *vmThread, jobject constantPoolOop, jint cpIndex, UDATA *cpType, J9RAMConstantRef **ramConstantRef) { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); + J9ConstantPool *ramConstantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + J9Class *ramClass = ramConstantPool->ramClass; J9ROMClass *romClass = ramClass->romClass; SunReflectCPResult result = CP_INDEX_OUT_OF_BOUNDS_EXCEPTION; if ((0 <= cpIndex) && ((U_32)cpIndex < romClass->ramConstantPoolCount)) { - J9ConstantPool *ramConstantPool = J9_CP_FROM_CLASS(ramClass); U_32 *cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(romClass); *cpType = J9_CP_TYPE(cpShapeDescription, cpIndex); *ramConstantRef = ((J9RAMConstantRef *) ramConstantPool) + cpIndex; @@ -76,12 +76,12 @@ getRAMConstantRef(J9VMThread *vmThread, jobject constantPoolOop, jint cpIndex, U static SunReflectCPResult getROMCPItemAndType(J9VMThread *vmThread, jobject constantPoolOop, jint cpIndex, UDATA *cpType, J9ROMConstantPoolItem **romCPItem) { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); + J9ConstantPool *ramConstantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + J9Class *ramClass = ramConstantPool->ramClass; J9ROMClass *romClass = ramClass->romClass; SunReflectCPResult result = CP_INDEX_OUT_OF_BOUNDS_EXCEPTION; if ((0 <= cpIndex) && ((U_32)cpIndex < romClass->romConstantPoolCount)) { - J9ConstantPool *ramConstantPool = J9_CP_FROM_CLASS(ramClass); J9ROMConstantPoolItem *romConstantPool = J9_ROM_CP_FROM_CP(ramConstantPool); U_32 *cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(romClass); *cpType = J9_CP_TYPE(cpShapeDescription, cpIndex); @@ -113,8 +113,8 @@ getJ9ClassAt(J9VMThread *vmThread, jobject constantPoolOop, jint cpIndex, UDATA if (NULL != ramClassRefWrapper->value) { *clazz = ramClassRefWrapper->value; } else { - J9Class *cpClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - *clazz = vmFunctions->resolveClassRef(vmThread, J9_CP_FROM_CLASS(cpClass), cpIndex, resolveFlags); + J9ConstantPool *constantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + *clazz = vmFunctions->resolveClassRef(vmThread, constantPool, cpIndex, resolveFlags); } } return result; @@ -150,11 +150,11 @@ getStringAt(JNIEnv *env, jobject unusedObject, jobject constantPoolOop, jint cpI vmFunctions->internalEnterVMFromJNI(vmThread); result = getRAMConstantRef(vmThread, constantPoolOop, cpIndex, cpType, (J9RAMConstantRef **) &ramStringRef); if (OK == result) { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - j9object_t stringObject = J9STATIC_OBJECT_LOAD(vmThread, ramClass, &ramStringRef->stringObject); + J9ConstantPool *ramConstantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + j9object_t stringObject = J9STATIC_OBJECT_LOAD(vmThread, ramConstantPool->ramClass, &ramStringRef->stringObject); if (NULL == stringObject) { - stringObject = vmFunctions->resolveStringRef(vmThread, J9_CP_FROM_CLASS(ramClass), cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE | J9_RESOLVE_FLAG_NO_THROW_ON_FAIL); + stringObject = vmFunctions->resolveStringRef(vmThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE | J9_RESOLVE_FLAG_NO_THROW_ON_FAIL); } if (NULL != stringObject) { returnValue = vmFunctions->j9jni_createLocalRef(env, stringObject); @@ -211,8 +211,8 @@ getMethodAt(JNIEnv *env, jobject constantPoolOop, jint cpIndex, UDATA resolveFla result = getRAMConstantRefAndType(vmThread, constantPoolOop, cpIndex, &cpType, &ramConstantRef); if (OK == result) { J9Method *method = NULL; - J9Class *cpClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - J9ConstantPool *constantPool = J9_CP_FROM_CLASS(cpClass); + J9ConstantPool *constantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + J9Class *cpClass = constantPool->ramClass; switch (cpType) { case J9CPTYPE_HANDLE_METHOD: /* fall through */ case J9CPTYPE_INSTANCE_METHOD: /* fall through */ @@ -301,8 +301,8 @@ getFieldAt(JNIEnv *env, jobject constantPoolOop, jint cpIndex, UDATA resolveFlag if (OK == result) { J9ROMFieldShape *resolvedField = NULL; UDATA offset = 0; - J9Class *cpClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - J9ConstantPool *constantPool = J9_CP_FROM_CLASS(cpClass); + J9ConstantPool *constantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + J9Class *cpClass = constantPool->ramClass; switch (cpType) { case J9CPTYPE_FIELD: { /* Try to resolve as instance field, then as a static */ @@ -417,7 +417,7 @@ Java_sun_reflect_ConstantPool_getSize0(JNIEnv *env, jobject unusedObject, jobjec if (NULL != constantPoolOop) { vmFunctions->internalEnterVMFromJNI(vmThread); { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); + J9Class *ramClass = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop)->ramClass; if (NULL != ramClass) { J9ROMClass *romClass = ramClass->romClass; returnValue = romClass->romConstantPoolCount; @@ -474,7 +474,7 @@ Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0(JNIEnv *env, jobject unusedObj * * @param env[in] the JNI env * @param unusedObject[in] unused - * @param constantPoolOop[in] the class - its constant pool is accessed + * @param constantPoolOop[in] the constant pool as an InternalConstantPool object * @param cpIndex[in] the constant pool index * * @return instance of String which contains the class name or NULL in @@ -683,7 +683,7 @@ Java_java_lang_invoke_MethodHandleResolver_getCPTypeAt(JNIEnv *env, jclass unuse J9ROMClass *romClass; result = CP_INDEX_OUT_OF_BOUNDS_EXCEPTION; vmFunctions->internalEnterVMFromJNI(vmThread); - ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); + ramClass = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop)->ramClass; romClass = ramClass->romClass; if ((0 <= cpIndex) && ((U_32)cpIndex < romClass->romConstantPoolCount)) { @@ -716,11 +716,11 @@ Java_java_lang_invoke_MethodHandleResolver_getCPMethodTypeAt(JNIEnv *env, jclass vmFunctions->internalEnterVMFromJNI(vmThread); result = getRAMConstantRef(vmThread, constantPoolOop, cpIndex, J9CPTYPE_METHOD_TYPE, (J9RAMConstantRef **) &ramMethodTypeRef); if (OK == result) { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - j9object_t methodTypeObject = J9STATIC_OBJECT_LOAD(vmThread, ramClass, &ramMethodTypeRef->type); + J9ConstantPool *ramConstantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + j9object_t methodTypeObject = J9STATIC_OBJECT_LOAD(vmThread, ramConstantPool->ramClass, &ramMethodTypeRef->type); if (NULL == methodTypeObject) { - methodTypeObject = vmFunctions->resolveMethodTypeRef(vmThread, J9_CP_FROM_CLASS(ramClass), cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE); + methodTypeObject = vmFunctions->resolveMethodTypeRef(vmThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE); } if (NULL != methodTypeObject) { returnValue = vmFunctions->j9jni_createLocalRef(env, methodTypeObject); @@ -751,14 +751,14 @@ Java_java_lang_invoke_MethodHandleResolver_getCPMethodHandleAt(JNIEnv *env, jcla vmFunctions->internalEnterVMFromJNI(vmThread); result = getRAMConstantRef(vmThread, constantPoolOop, cpIndex, J9CPTYPE_METHODHANDLE, (J9RAMConstantRef **) &ramMethodHandleRef); if (OK == result) { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - j9object_t methodHandleObject = J9STATIC_OBJECT_LOAD(vmThread, ramClass, &ramMethodHandleRef->methodHandle); + J9ConstantPool *ramConstantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + j9object_t methodHandleObject = J9STATIC_OBJECT_LOAD(vmThread, ramConstantPool->ramClass, &ramMethodHandleRef->methodHandle); if (NULL == methodHandleObject) { /* Avoid initializing the class from there so as to postpone the static initialization * to the invocation of the specified method of the class. */ - methodHandleObject = vmFunctions->resolveMethodHandleRef(vmThread, J9_CP_FROM_CLASS(ramClass), cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE | J9_RESOLVE_FLAG_NO_CLASS_INIT); + methodHandleObject = vmFunctions->resolveMethodHandleRef(vmThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE | J9_RESOLVE_FLAG_NO_CLASS_INIT); } if (NULL != methodHandleObject) { returnValue = vmFunctions->j9jni_createLocalRef(env, methodHandleObject); @@ -785,13 +785,13 @@ Java_java_lang_invoke_MethodHandleResolver_getCPConstantDynamicAt(JNIEnv *env, j vmFunctions->internalEnterVMFromJNI(vmThread); result = getRAMConstantRef(vmThread, constantPoolOop, cpIndex, J9CPTYPE_CONSTANT_DYNAMIC, (J9RAMConstantRef **) &ramConstantDynamicRef); if (OK == result) { - J9Class *ramClass = J9CLASS_FROMCPINTERNALRAMCLASS(vmThread, constantPoolOop); - j9object_t value = J9STATIC_OBJECT_LOAD(vmThread, ramClass, &ramConstantDynamicRef->value); + J9ConstantPool *ramConstantPool = J9CONSTANTPOOL_FROMCPINTERNALCONSTANTPOOL(vmThread, constantPoolOop); + j9object_t value = J9STATIC_OBJECT_LOAD(vmThread, ramConstantPool->ramClass, &ramConstantDynamicRef->value); /* Check if the value is resolved, Void.Class exception represents a valid null reference */ if ((NULL == value) && (ramConstantDynamicRef->exception != vmThread->javaVM->voidReflectClass->classObject)) { /* If entry resolved to an exception previously, same exception will be set by resolution code */ - value = vmFunctions->resolveConstantDynamic(vmThread, J9_CP_FROM_CLASS(ramClass), (UDATA)cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE); + value = vmFunctions->resolveConstantDynamic(vmThread, ramConstantPool, (UDATA)cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE); } if (NULL != value) { diff --git a/runtime/jcl/exports.cmake b/runtime/jcl/exports.cmake index 4e1867d9c05..284fbb90a0b 100644 --- a/runtime/jcl/exports.cmake +++ b/runtime/jcl/exports.cmake @@ -298,6 +298,7 @@ omr_add_exports(jclse Java_com_ibm_oti_vm_VM_localGC Java_com_ibm_oti_vm_VM_markCurrentThreadAsSystemImpl Java_com_ibm_oti_vm_VM_setCommonData + Java_com_ibm_oti_vm_VM_getJ9ConstantPoolFromJ9Class Java_com_ibm_rmi_io_IIOPInputStream_00024LUDCLStackWalkOptimizer_LUDCLMarkFrame Java_com_ibm_rmi_io_IIOPInputStream_00024LUDCLStackWalkOptimizer_LUDCLUnmarkFrameImpl Java_com_ibm_virtualization_management_internal_GuestOS_retrieveMemoryUsageImpl diff --git a/runtime/jcl/uma/se7_exports.xml b/runtime/jcl/uma/se7_exports.xml index 1e3730cb518..f1cb12fee5d 100644 --- a/runtime/jcl/uma/se7_exports.xml +++ b/runtime/jcl/uma/se7_exports.xml @@ -73,4 +73,5 @@ + diff --git a/runtime/oti/jclprots.h b/runtime/oti/jclprots.h index ca32f4aa106..11e35a14ad8 100644 --- a/runtime/oti/jclprots.h +++ b/runtime/oti/jclprots.h @@ -1210,6 +1210,13 @@ Java_com_ibm_lang_management_internal_JvmCpuMonitor_getThreadCategoryImpl(JNIEnv */ jint JNICALL Java_com_ibm_oti_vm_VM_markCurrentThreadAsSystemImpl(JNIEnv *env); +/** + * Gets the J9ConstantPool address from a J9Class address + * @param j9clazz J9Class address + * @return Address of J9ConstantPool + */ +jlong JNICALL +Java_com_ibm_oti_vm_VM_getJ9ConstantPoolFromJ9Class(JNIEnv *env, jclass unused, jlong j9clazz); #if JAVA_SPEC_VERSION >= 16 jboolean JNICALL diff --git a/runtime/oti/vmconstantpool.xml b/runtime/oti/vmconstantpool.xml index df320a69a71..3be16931ec2 100644 --- a/runtime/oti/vmconstantpool.xml +++ b/runtime/oti/vmconstantpool.xml @@ -82,7 +82,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti - + @@ -341,7 +341,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti - + diff --git a/runtime/tests/jvmtitests/agent/tests.c b/runtime/tests/jvmtitests/agent/tests.c index 169ca5921bd..88114d52fa3 100644 --- a/runtime/tests/jvmtitests/agent/tests.c +++ b/runtime/tests/jvmtitests/agent/tests.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2020 IBM Corp. and others + * Copyright (c) 2001, 2021 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -95,6 +95,7 @@ static jvmtiTest jvmtiTestList[] = { "rc019a", rc019a, "com.ibm.jvmti.tests.redefineClasses.rc019a", "RedefineClasses" }, { "rc019b", rc019b, "com.ibm.jvmti.tests.redefineClasses.rc019b", "RedefineClasses" }, { "rc020", rc020, "com.ibm.jvmti.tests.redefineClasses.rc020", "RedefineClasses" }, + { "rc021", rc021, "com.ibm.jvmti.tests.redefineClasses.rc021", "RedefineClasses" }, { "gtgc001", gtgc001, "com.ibm.jvmti.tests.getThreadGroupChildren.gtgc001", "GetThreadGroupChildren" }, { "gtgc002", gtgc002, "com.ibm.jvmti.tests.getThreadGroupChildren.gtgc002", "3 bytes name buffer overflow" }, { "gts001", gts001, "com.ibm.jvmti.tests.getThreadState.gts001", "GetThreadState" }, diff --git a/runtime/tests/jvmtitests/exports.cmake b/runtime/tests/jvmtitests/exports.cmake index 0bf293f4952..6317f60d059 100644 --- a/runtime/tests/jvmtitests/exports.cmake +++ b/runtime/tests/jvmtitests/exports.cmake @@ -1,5 +1,5 @@ ################################################################################ -# Copyright (c) 2019, 2020 IBM Corp. and others +# Copyright (c) 2019, 2021 IBM Corp. and others # # This program and the accompanying materials are made available under # the terms of the Eclipse Public License 2.0 which accompanies this @@ -112,6 +112,7 @@ omr_add_exports(jvmtitest Java_com_ibm_jvmti_tests_redefineClasses_rc019b_redefineClass Java_com_ibm_jvmti_tests_redefineClasses_rc019b_getValue Java_com_ibm_jvmti_tests_redefineClasses_rc020_redefineClass + Java_com_ibm_jvmti_tests_redefineClasses_rc021_redefineClass Java_com_ibm_jvmti_tests_getPotentialCapabilities_gpc001_verifyOnLoadCapabilities Java_com_ibm_jvmti_tests_getPotentialCapabilities_gpc001_verifyLiveCapabilities Java_com_ibm_jvmti_tests_getPotentialCapabilities_gpc002_verifyCapabilityRetention diff --git a/runtime/tests/jvmtitests/include/jvmti_test.h b/runtime/tests/jvmtitests/include/jvmti_test.h index 4aa795159d4..73a6b36271d 100644 --- a/runtime/tests/jvmtitests/include/jvmti_test.h +++ b/runtime/tests/jvmtitests/include/jvmti_test.h @@ -187,6 +187,7 @@ jint JNICALL rc018(agentEnv * env, char * args); jint JNICALL rc019a(agentEnv * env, char * args); jint JNICALL rc019b(agentEnv * env, char * args); jint JNICALL rc020(agentEnv * env, char * args); +jint JNICALL rc021(agentEnv * env, char * args); jint JNICALL re001(agentEnv * env, char * args); jint JNICALL re002(agentEnv * env, char * args); jint JNICALL fr001(agentEnv * env, char * args); diff --git a/runtime/tests/jvmtitests/module.xml b/runtime/tests/jvmtitests/module.xml index 687c9da886e..e0c93f35660 100644 --- a/runtime/tests/jvmtitests/module.xml +++ b/runtime/tests/jvmtitests/module.xml @@ -1,7 +1,7 @@