2626
2727import static com .oracle .svm .core .util .VMError .guarantee ;
2828import static com .oracle .svm .jni .JNIObjectHandles .nullHandle ;
29- import static com .oracle .svm .jvmtiagentbase .Support .callObjectMethod ;
3029import static com .oracle .svm .jvmtiagentbase .Support .check ;
3130import static com .oracle .svm .jvmtiagentbase .Support .checkNoException ;
3231import static com .oracle .svm .jvmtiagentbase .Support .clearException ;
4039import static com .oracle .svm .jvmtiagentbase .Support .jniFunctions ;
4140import static com .oracle .svm .jvmtiagentbase .Support .jvmtiEnv ;
4241import static com .oracle .svm .jvmtiagentbase .Support .jvmtiFunctions ;
43- import static com .oracle .svm .jvmtiagentbase .Support .newObjectL ;
4442import static com .oracle .svm .jvmtiagentbase .Support .testException ;
4543import static com .oracle .svm .jvmtiagentbase .Support .toCString ;
4644import static com .oracle .svm .jvmtiagentbase .jvmti .JvmtiEvent .JVMTI_EVENT_BREAKPOINT ;
@@ -647,11 +645,14 @@ private static boolean getBundleImplJDK8OrEarlier(JNIEnvironment jni, Breakpoint
647645 JNIObjectHandle loader = getObjectArgument (2 );
648646 JNIObjectHandle control = getObjectArgument (3 );
649647 JNIObjectHandle result = Support .callStaticObjectMethodLLLL (jni , bp .clazz , bp .method , baseName , locale , loader , control );
648+ BundleInfo bundleInfo = BundleInfo .NONE ;
650649 if (clearException (jni )) {
651650 result = nullHandle ();
651+ } else {
652+ bundleInfo = extractBundleInfo (jni , result );
652653 }
653654 traceBreakpoint (jni , nullHandle (), nullHandle (), callerClass , "getBundleImplJDK8OrEarlier" , result .notEqual (nullHandle ()),
654- state .getFullStackTraceOrNull (), fromJniString (jni , baseName ), Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE );
655+ state .getFullStackTraceOrNull (), fromJniString (jni , baseName ), Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE , bundleInfo . classNames , bundleInfo . locales );
655656 return true ;
656657 }
657658
@@ -671,14 +672,80 @@ private static boolean getBundleImplJDK11OrLater(JNIEnvironment jni, Breakpoint
671672 JNIObjectHandle locale = getObjectArgument (3 );
672673 JNIObjectHandle control = getObjectArgument (4 );
673674 JNIObjectHandle result = Support .callStaticObjectMethodLLLLL (jni , bp .clazz , bp .method , callerModule , module , baseName , locale , control );
675+ BundleInfo bundleInfo = BundleInfo .NONE ;
674676 if (clearException (jni )) {
675677 result = nullHandle ();
678+ } else {
679+ bundleInfo = extractBundleInfo (jni , result );
676680 }
677681 traceBreakpoint (jni , nullHandle (), nullHandle (), callerClass , "getBundleImplJDK11OrLater" , result .notEqual (nullHandle ()),
678- state .getFullStackTraceOrNull (), Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE , fromJniString (jni , baseName ), Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE );
682+ state .getFullStackTraceOrNull (), Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE , fromJniString (jni , baseName ), Tracer .UNKNOWN_VALUE , Tracer .UNKNOWN_VALUE , bundleInfo .classNames ,
683+ bundleInfo .locales );
679684 return true ;
680685 }
681686
687+ private static String readLocaleTag (JNIEnvironment jni , JNIObjectHandle locale ) {
688+ JNIObjectHandle languageTag = Support .callObjectMethod (jni , locale , agent .handles ().getJavaUtilLocaleToLanguageTag (jni ));
689+ if (clearException (jni )) {
690+ /*- return root locale */
691+ return "" ;
692+ }
693+ return fromJniString (jni , languageTag );
694+ }
695+
696+ private static final class BundleInfo {
697+
698+ static final BundleInfo NONE = new BundleInfo (new String [0 ], new String [0 ]);
699+
700+ final String [] classNames ;
701+ final String [] locales ;
702+
703+ BundleInfo (String [] classNames , String [] locales ) {
704+ this .classNames = classNames ;
705+ this .locales = locales ;
706+ }
707+ }
708+
709+ /**
710+ * Traverses the bundle parent chain and collects classnames and locales of all encountered
711+ * bundles.
712+ *
713+ */
714+ private static BundleInfo extractBundleInfo (JNIEnvironment jni , JNIObjectHandle bundle ) {
715+ List <String > locales = new ArrayList <>();
716+ List <String > classNames = new ArrayList <>();
717+ JNIObjectHandle curr = bundle ;
718+ while (curr .notEqual (nullHandle ())) {
719+ JNIObjectHandle locale = Support .callObjectMethod (jni , curr , agent .handles ().getJavaUtilResourceBundleGetLocale (jni ));
720+ if (clearException (jni )) {
721+ return BundleInfo .NONE ;
722+ }
723+ String localeTag = readLocaleTag (jni , locale );
724+ if (localeTag .equals ("und" )) {
725+ /*- Root locale is serialized into "und" */
726+ localeTag = "" ;
727+ }
728+ JNIObjectHandle clazz = Support .callObjectMethod (jni , curr , agent .handles ().javaLangObjectGetClass );
729+ if (!clearException (jni )) {
730+ JNIObjectHandle classNameHandle = Support .callObjectMethod (jni , clazz , agent .handles ().javaLangClassGetName );
731+ if (!clearException (jni )) {
732+ classNames .add (fromJniString (jni , classNameHandle ));
733+ locales .add (localeTag );
734+ }
735+ }
736+ curr = getResourceBundleParent (jni , curr );
737+ }
738+ return new BundleInfo (classNames .toArray (new String [0 ]), locales .toArray (new String [0 ]));
739+ }
740+
741+ private static JNIObjectHandle getResourceBundleParent (JNIEnvironment jni , JNIObjectHandle bundle ) {
742+ JNIObjectHandle parent = Support .readObjectField (jni , bundle , agent .handles ().getJavaUtilResourceBundleParentField (jni ));
743+ if (!clearException (jni )) {
744+ return parent ;
745+ }
746+ return nullHandle ();
747+ }
748+
682749 private static boolean loadClass (JNIEnvironment jni , Breakpoint bp , InterceptedState state ) {
683750 assert experimentalClassLoaderSupport ;
684751 /*
@@ -981,7 +1048,7 @@ private static boolean objectStreamClassConstructor(JNIEnvironment jni, Breakpoi
9811048 JNIObjectHandle serializeTargetClass = getObjectArgument (1 );
9821049 String serializeTargetClassName = getClassNameOrNull (jni , serializeTargetClass );
9831050
984- JNIObjectHandle objectStreamClassInstance = newObjectL (jni , bp .clazz , bp .method , serializeTargetClass );
1051+ JNIObjectHandle objectStreamClassInstance = Support . newObjectL (jni , bp .clazz , bp .method , serializeTargetClass );
9851052 boolean validObjectStreamClassInstance = nullHandle ().notEqual (objectStreamClassInstance );
9861053 if (clearException (jni )) {
9871054 validObjectStreamClassInstance = false ;
@@ -1001,7 +1068,7 @@ private static boolean objectStreamClassConstructor(JNIEnvironment jni, Breakpoi
10011068 * recursively. Call ObjectStreamClass.getClassDataLayout0() can get all of them.
10021069 */
10031070 JNIMethodId getClassDataLayout0MId = agent .handles ().getJavaIoObjectStreamClassGetClassDataLayout0 (jni , bp .clazz );
1004- JNIObjectHandle dataLayoutArray = callObjectMethod (jni , objectStreamClassInstance , getClassDataLayout0MId );
1071+ JNIObjectHandle dataLayoutArray = Support . callObjectMethod (jni , objectStreamClassInstance , getClassDataLayout0MId );
10051072 if (!clearException (jni ) && nullHandle ().notEqual (dataLayoutArray )) {
10061073 int length = jniFunctions ().getGetArrayLength ().invoke (jni , dataLayoutArray );
10071074 // If only 1 element is got from getClassDataLayout0(). it is base ObjectStreamClass
@@ -1016,7 +1083,7 @@ private static boolean objectStreamClassConstructor(JNIEnvironment jni, Breakpoi
10161083 if (hasData ) {
10171084 JNIObjectHandle oscInstanceInSlot = jniFunctions ().getGetObjectField ().invoke (jni , classDataSlot , descFId );
10181085 if (!jniFunctions ().getIsSameObject ().invoke (jni , oscInstanceInSlot , objectStreamClassInstance )) {
1019- JNIObjectHandle oscClazz = callObjectMethod (jni , oscInstanceInSlot , javaIoObjectStreamClassForClassMId );
1086+ JNIObjectHandle oscClazz = Support . callObjectMethod (jni , oscInstanceInSlot , javaIoObjectStreamClassForClassMId );
10201087 String oscClassName = getClassNameOrNull (jni , oscClazz );
10211088 transitiveSerializeTargets .add (oscClassName );
10221089 }
@@ -1062,7 +1129,7 @@ private static boolean customTargetConstructorSerialization(JNIEnvironment jni,
10621129 JNIObjectHandle customConstructorObj = getObjectArgument (2 );
10631130 JNIObjectHandle customConstructorClass = jniFunctions ().getGetObjectClass ().invoke (jni , customConstructorObj );
10641131 JNIMethodId getDeclaringClassNameMethodID = agent .handles ().getJavaLangReflectConstructorDeclaringClassName (jni , customConstructorClass );
1065- JNIObjectHandle declaredClassNameObj = callObjectMethod (jni , customConstructorObj , getDeclaringClassNameMethodID );
1132+ JNIObjectHandle declaredClassNameObj = Support . callObjectMethod (jni , customConstructorObj , getDeclaringClassNameMethodID );
10661133 String customConstructorClassName = fromJniString (jni , declaredClassNameObj );
10671134
10681135 if (tracer != null ) {
@@ -1261,9 +1328,9 @@ private static void setupClassLoadEvent(JvmtiEnv jvmti, JNIEnvironment jni) {
12611328 JNIMethodId getPlatformLoader = agent .handles ().getMethodIdOptional (jni , classLoader , "getPlatformClassLoader" , "()Ljava/lang/ClassLoader;" , true );
12621329 JNIMethodId getAppLoader = agent .handles ().getMethodIdOptional (jni , classLoader , "getBuiltinAppClassLoader" , "()Ljava/lang/ClassLoader;" , true );
12631330 if (getPlatformLoader .isNonNull () && getAppLoader .isNonNull ()) { // only on JDK 9 and later
1264- JNIObjectHandle platformLoader = callObjectMethod (jni , classLoader , getPlatformLoader );
1331+ JNIObjectHandle platformLoader = Support . callObjectMethod (jni , classLoader , getPlatformLoader );
12651332 checkNoException (jni );
1266- JNIObjectHandle appLoader = callObjectMethod (jni , classLoader , getAppLoader );
1333+ JNIObjectHandle appLoader = Support . callObjectMethod (jni , classLoader , getAppLoader );
12671334 checkNoException (jni );
12681335 guarantee (platformLoader .notEqual (nullHandle ()) && appLoader .notEqual (nullHandle ()));
12691336
0 commit comments