diff --git a/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.java b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.java new file mode 100644 index 0000000000000..bc935ea99d19f --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, 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. + * + * 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 8144992 + * @requires vm.jvmti + * @modules java.base/jdk.internal.org.objectweb.asm + * @run main/othervm/native -agentlib:TestManyBreakpoints + * -Xlog:gc+metaspace + * -Xint + * -XX:MetaspaceSize=16K -XX:MaxMetaspaceSize=64M + * TestManyBreakpoints + */ + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +public class TestManyBreakpoints { + + static final int BATCHES = 50; + static final int METHODS = 1000; + + public static void main(String[] args) throws Exception { + for (int c = 0; c < BATCHES; c++) { + System.out.println("Batch " + c); + TestClassLoader loader = new TestClassLoader(); + Class.forName("Target", true, loader); + } + } + + private static class TestClassLoader extends ClassLoader implements Opcodes { + static byte[] TARGET_BYTES = generateTarget(); + + private static byte[] generateTarget() { + ClassWriter cw = new ClassWriter(0); + + cw.visit(52, ACC_SUPER | ACC_PUBLIC, "Target", null, "java/lang/Object", null); + for (int m = 0; m < METHODS; m++) { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m" + m, "()V", null, null); + mv.visitCode(); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals("Target")) { + return defineClass(name, TARGET_BYTES, 0, TARGET_BYTES.length); + } else { + return super.findClass(name); + } + } + } + +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/libTestManyBreakpoints.cpp b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/libTestManyBreakpoints.cpp new file mode 100644 index 0000000000000..dcb8f87ddd756 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/libTestManyBreakpoints.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022, 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. + * + * 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 +#include + +#include "jvmti.h" + +#define TARGET_CLASS_NAME "LTarget;" + +static jvmtiEnv *jvmti = NULL; + +static void +check_jvmti_status(JNIEnv* jni, jvmtiError err, const char* msg) { + if (err != JVMTI_ERROR_NONE) { + printf("check_jvmti_status: %s, JVMTI function returned error: %d\n", msg, err); + jni->FatalError(msg); + } +} + +void JNICALL classprepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass) { + char* buf; + jvmtiError err; + + err = jvmti->GetClassSignature(klass, &buf, NULL); + check_jvmti_status(jni_env, err, "classprepare: GetClassSignature error"); + + if (strncmp(buf, TARGET_CLASS_NAME, strlen(TARGET_CLASS_NAME)) == 0) { + jint nMethods; + jmethodID* methods; + int i; + + err = jvmti->GetClassMethods(klass, &nMethods, &methods); + check_jvmti_status(jni_env, err, "classprepare: GetClassMethods error"); + printf("Setting breakpoints in %s\n", buf); + fflush(stdout); + for (i = 0; i < nMethods; i++) { + err = jvmti->SetBreakpoint(methods[i], 0); + check_jvmti_status(jni_env, err, "classprepare: SetBreakpoint error"); + } + } +} + + +void JNICALL breakpoint(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location) { + // Do nothing +} + +JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { + jvmtiCapabilities capa; + jvmtiEventCallbacks cbs; + jint err; + + err = vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); + if (err != JNI_OK) { + printf("Agent_OnLoad: GetEnv error\n"); + return JNI_ERR; + } + + memset(&capa, 0, sizeof(capa)); + capa.can_generate_breakpoint_events = 1; + capa.can_generate_single_step_events = 1; + err = jvmti->AddCapabilities(&capa); + if (err != JNI_OK) { + printf("Agent_OnLoad: AddCapabilities error\n"); + return JNI_ERR; + } + + memset(&cbs, 0, sizeof(cbs)); + cbs.ClassPrepare = classprepare; + cbs.Breakpoint = breakpoint; + err = jvmti->SetEventCallbacks(&cbs, sizeof(cbs)); + if (err != JNI_OK) { + printf("Agent_OnLoad: SetEventCallbacks error\n"); + return JNI_ERR; + } + + err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL); + if (err != JNI_OK) { + printf("Agent_OnLoad: SetEventNotificationMode CLASS_PREPARE error\n"); + return JNI_ERR; + } + + err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL); + if (err != JNI_OK) { + printf("Agent_OnLoad: SetEventNotificationMode BREAKPOINT error\n"); + return JNI_ERR; + } + + return JNI_OK; +}