Skip to content

Commit

Permalink
8282170: JVMTI SetBreakpoint metaspace allocation test
Browse files Browse the repository at this point in the history
Reviewed-by: cjplummer, lmesnik
  • Loading branch information
shipilev committed Mar 10, 2022
1 parent b13cacc commit 7b91bbb
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -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 <string.h>
#include <stdio.h>

#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;
}

1 comment on commit 7b91bbb

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.