Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
8216324: GetClassMethods is confused by the presence of default metho…
…ds in super interfaces Reviewed-by: sspitsyn, amenkov
- Loading branch information
Daniil Titov
committed
Jul 27, 2020
1 parent
ed7f796
commit 277ec3d
Showing
5 changed files
with
253 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
test/hotspot/jtreg/serviceability/jvmti/GetClassMethods/OverpassMethods.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 only, as | ||
* published by the Free Software Foundation. Oracle designates this | ||
* particular file as subject to the "Classpath" exception as provided | ||
* by Oracle in the LICENSE file that accompanied this code. | ||
* | ||
* This code is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* version 2 for more details (a copy is included in the LICENSE file that | ||
* accompanied this code). | ||
* | ||
* You should have received a copy of the GNU General Public License version | ||
* 2 along with this work; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
* or visit www.oracle.com if you need additional information or have any | ||
* questions. | ||
*/ | ||
|
||
/** | ||
* @test | ||
* @bug 8216324 | ||
* @summary GetClassMethods is confused by the presence of default methods in super interfaces | ||
* @library /test/lib | ||
* @compile OverpassMethods.java | ||
* @run main/othervm/native -agentlib:OverpassMethods OverpassMethods | ||
* @run main/othervm/native -agentlib:OverpassMethods=maintain_original_method_order OverpassMethods | ||
*/ | ||
|
||
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
|
||
public class OverpassMethods { | ||
|
||
static { | ||
try { | ||
System.loadLibrary("OverpassMethods"); | ||
} catch (UnsatisfiedLinkError ex) { | ||
System.err.println("Could not load OverpassMethods library"); | ||
System.err.println("java.library.path:" + System.getProperty("java.library.path")); | ||
throw ex; | ||
} | ||
} | ||
|
||
static private void log(Object msg) { | ||
System.out.println(String.valueOf(msg)); | ||
} | ||
|
||
static private native Method[] getJVMTIDeclaredMethods(Class<?> klass); | ||
|
||
public interface Parent { | ||
default String def() { return "Parent.def"; } | ||
String method0(); | ||
String method1(); | ||
} | ||
|
||
public interface Child extends Parent { | ||
String method2(); | ||
} | ||
|
||
public static class Impl implements Child { | ||
public String method0() { return "Impl.method0"; } | ||
public String method1() { return "Impl.method1"; } | ||
public String method2() { return "Impl.method2"; } | ||
} | ||
|
||
public static void main(String[] args) { | ||
new Impl(); // To get classes initialized | ||
|
||
Method[] reflectMethods = Child.class.getDeclaredMethods(); | ||
Method[] jvmtiMethods = getJVMTIDeclaredMethods(Child.class); | ||
|
||
if (jvmtiMethods == null) { | ||
throw new RuntimeException("getJVMTIDeclaredMethods failed"); | ||
} | ||
|
||
log("Reflection getDeclaredMethods returned: " + Arrays.toString(reflectMethods)); | ||
log("JVMTI GetClassMethods returned: " + Arrays.toString(jvmtiMethods)); | ||
|
||
if (reflectMethods.length != jvmtiMethods.length) { | ||
throw new RuntimeException("OverpassMethods failed: Unexpected method count from JVMTI GetClassMethods!"); | ||
} | ||
if (!reflectMethods[0].equals(jvmtiMethods[0])) { | ||
throw new RuntimeException("OverpassMethods failed: Unexpected method from JVMTI GetClassMethods!"); | ||
} | ||
log("Test passed: Got expected output from JVMTI GetClassMethods!"); | ||
} | ||
} |
103 changes: 103 additions & 0 deletions
103
test/hotspot/jtreg/serviceability/jvmti/GetClassMethods/libOverpassMethods.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. | ||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
* | ||
* This code is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 only, as | ||
* published by the Free Software Foundation. Oracle designates this | ||
* particular file as subject to the "Classpath" exception as provided | ||
* by Oracle in the LICENSE file that accompanied this code. | ||
* | ||
* This code is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
* version 2 for more details (a copy is included in the LICENSE file that | ||
* accompanied this code). | ||
* | ||
* You should have received a copy of the GNU General Public License version | ||
* 2 along with this work; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
* or visit www.oracle.com if you need additional information or have any | ||
* questions. | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include "jvmti.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#define ACC_STATIC 0x0008 | ||
|
||
static jvmtiEnv *jvmti = NULL; | ||
|
||
JNIEXPORT | ||
jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { | ||
return JNI_VERSION_9; | ||
} | ||
|
||
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { | ||
vm->GetEnv((void **)&jvmti, JVMTI_VERSION_11); | ||
|
||
if (options != NULL && strcmp(options, "maintain_original_method_order") == 0) { | ||
printf("Enabled capability: maintain_original_method_order\n"); | ||
jvmtiCapabilities caps = {}; | ||
caps.can_maintain_original_method_order = 1; | ||
|
||
jvmtiError err = jvmti->AddCapabilities(&caps); | ||
if (err != JVMTI_ERROR_NONE) { | ||
printf("Agent_OnLoad: AddCapabilities failed with error: %d\n", err); | ||
return JNI_ERR; | ||
} | ||
} | ||
return JNI_OK; | ||
} | ||
|
||
JNIEXPORT jobjectArray JNICALL Java_OverpassMethods_getJVMTIDeclaredMethods(JNIEnv *env, jclass static_klass, jclass klass) { | ||
jint method_count = 0; | ||
jmethodID* methods = NULL; | ||
jvmtiError err = jvmti->GetClassMethods(klass, &method_count, &methods); | ||
if (err != JVMTI_ERROR_NONE) { | ||
printf("GetClassMethods failed with error: %d\n", err); | ||
return NULL; | ||
} | ||
|
||
jclass method_cls = env->FindClass("java/lang/reflect/Method"); | ||
if (method_cls == NULL) { | ||
printf("FindClass (Method) failed\n"); | ||
return NULL; | ||
} | ||
jobjectArray array = env->NewObjectArray(method_count, method_cls, NULL); | ||
if (array == NULL) { | ||
printf("NewObjectArray failed\n"); | ||
return NULL; | ||
} | ||
|
||
for (int i = 0; i < method_count; i++) { | ||
jint modifiers = 0; | ||
err = jvmti->GetMethodModifiers(methods[i], &modifiers); | ||
if (err != JVMTI_ERROR_NONE) { | ||
printf("GetMethodModifiers failed with error: %d\n", err); | ||
return NULL; | ||
} | ||
|
||
jobject m = env->ToReflectedMethod(klass, methods[i], (modifiers & ACC_STATIC) == ACC_STATIC); | ||
if (array == NULL) { | ||
printf("ToReflectedMethod failed\n"); | ||
return NULL; | ||
} | ||
env->SetObjectArrayElement(array, i, m); | ||
|
||
env->DeleteLocalRef(m); | ||
} | ||
jvmti->Deallocate((unsigned char *)methods); | ||
|
||
return array; | ||
} | ||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters