8331877: JFR: Remove JIInliner framework

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2024-05-31 13:45:17 +00:00
parent d9e7b7e7da
commit 5abc02927b
13 changed files with 10 additions and 766 deletions

View File

@ -23,35 +23,26 @@
* questions.
*/
package jdk.jfr.internal.instrument;
package jdk.jfr.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import jdk.internal.access.SharedSecrets;
import jdk.internal.event.JFRTracing;
import jdk.internal.event.ThrowableTracer;
import jdk.internal.platform.Container;
import jdk.internal.platform.Metrics;
import jdk.jfr.Event;
import jdk.jfr.events.ActiveRecordingEvent;
import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.events.ContainerIOUsageEvent;
import jdk.jfr.events.ContainerConfigurationEvent;
import jdk.jfr.events.ContainerCPUUsageEvent;
import jdk.jfr.events.ContainerCPUThrottlingEvent;
import jdk.jfr.events.ContainerCPUUsageEvent;
import jdk.jfr.events.ContainerConfigurationEvent;
import jdk.jfr.events.ContainerIOUsageEvent;
import jdk.jfr.events.ContainerMemoryUsageEvent;
import jdk.jfr.events.DirectBufferStatisticsEvent;
import jdk.jfr.events.FileForceEvent;
import jdk.jfr.events.InitialSecurityPropertyEvent;
import jdk.jfr.internal.JVM;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
import jdk.jfr.internal.Logger;
import jdk.jfr.internal.SecuritySupport;
import jdk.jfr.internal.periodic.PeriodicEvents;
import jdk.internal.platform.Container;
import jdk.internal.platform.Metrics;
public final class JDKEvents {
@ -85,11 +76,6 @@ public final class JDKEvents {
InitialSecurityPropertyEvent.class,
};
// This is a list of the classes with instrumentation code that should be applied.
private static final Class<?>[] instrumentationClasses = new Class<?>[] {
};
private static final Class<?>[] targetClasses = new Class<?>[instrumentationClasses.length];
private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
private static final Runnable emitDirectBufferStatistics = JDKEvents::emitDirectBufferStatistics;
private static final Runnable emitContainerConfiguration = JDKEvents::emitContainerConfiguration;
@ -121,24 +107,6 @@ public final class JDKEvents {
}
}
public static void addInstrumentation() {
try {
List<Class<?>> list = new ArrayList<>();
for (int i = 0; i < instrumentationClasses.length; i++) {
JIInstrumentationTarget tgt = instrumentationClasses[i].getAnnotation(JIInstrumentationTarget.class);
Class<?> clazz = Class.forName(tgt.value());
targetClasses[i] = clazz;
list.add(clazz);
}
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Retransformed JDK classes");
JVM.retransformClasses(list.toArray(new Class<?>[list.size()]));
} catch (IllegalStateException ise) {
throw ise;
} catch (Exception e) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not add instrumentation for JDK events. " + e.getMessage());
}
}
private static void initializeContainerEvents() {
if (JVM.isContainerized() ) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "JVM is containerized");
@ -225,20 +193,6 @@ public final class JDKEvents {
}
}
@SuppressWarnings("deprecation")
public static byte[] retransformCallback(Class<?> klass, byte[] oldBytes) throws Throwable {
for (int i = 0; i < targetClasses.length; i++) {
if (targetClasses[i].equals(klass)) {
Class<?> c = instrumentationClasses[i];
if (Logger.shouldLog(LogTag.JFR_SYSTEM, LogLevel.TRACE)) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.TRACE, "Processing instrumentation class: " + c);
}
return new JIClassInstrumentation(instrumentationClasses[i], klass, oldBytes).getNewBytes();
}
}
return oldBytes;
}
public static void remove() {
PeriodicEvents.removeEvent(emitExceptionStatistics);
PeriodicEvents.removeEvent(emitDirectBufferStatistics);

View File

@ -27,7 +27,6 @@ package jdk.jfr.internal;
import java.lang.reflect.Modifier;
import jdk.jfr.internal.event.EventConfiguration;
import jdk.jfr.internal.instrument.JDKEvents;
import jdk.jfr.internal.util.Bytecode;
/**
* All upcalls from the JVM should go through this class.
@ -78,7 +77,7 @@ final class JVMUpcalls {
Bytecode.log(clazz.getName(), bytes);
return bytes;
}
return JDKEvents.retransformCallback(clazz, oldBytes);
return oldBytes;
} catch (Throwable t) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Unexpected error when adding instrumentation to event class " + clazz.getName());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, 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
@ -57,7 +57,6 @@ import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.internal.SecuritySupport.SafePath;
import jdk.jfr.internal.SecuritySupport.SecureRecorderListener;
import jdk.jfr.internal.consumer.EventLog;
import jdk.jfr.internal.instrument.JDKEvents;
import jdk.jfr.internal.periodic.PeriodicEvents;
import jdk.jfr.internal.util.Utils;
@ -83,7 +82,6 @@ public final class PlatformRecorder {
Logger.log(JFR_SYSTEM, INFO, "Created native");
JDKEvents.initialize();
Logger.log(JFR_SYSTEM, INFO, "Registered JDK events");
JDKEvents.addInstrumentation();
startDiskMonitor();
shutdownHook = SecuritySupport.createThreadWitNoPermissions("JFR Shutdown Hook", new ShutdownHook(this));
SecuritySupport.setUncaughtExceptionHandler(shutdownHook, new ShutdownHook.ExceptionHandler());

View File

@ -73,7 +73,6 @@ import jdk.jfr.internal.consumer.FileAccess;
*/
public final class SecuritySupport {
private static final String EVENTS_PACKAGE_NAME = "jdk.jfr.events";
private static final String INSTRUMENT_PACKAGE_NAME = "jdk.jfr.internal.instrument";
private static final String EVENT_PACKAGE_NAME = "jdk.jfr.internal.event";
public static final String REGISTER_EVENT = "registerEvent";
@ -89,7 +88,6 @@ public final class SecuritySupport {
addReadEdge(Object.class);
addInternalEventExport(Object.class);
addEventsExport(Object.class);
addInstrumentExport(Object.class);
}
static final class SecureRecorderListener implements FlightRecorderListener {
@ -323,10 +321,6 @@ public final class SecuritySupport {
Modules.addExports(JFR_MODULE, EVENTS_PACKAGE_NAME, clazz.getModule());
}
static void addInstrumentExport(Class<?> clazz) {
Modules.addExports(JFR_MODULE, INSTRUMENT_PACKAGE_NAME, clazz.getModule());
}
static void addReadEdge(Class<?> clazz) {
Modules.addReads(clazz.getModule(), JFR_MODULE);
}

View File

@ -1,130 +0,0 @@
/*
* Copyright (c) 2013, 2021, 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.
*/
package jdk.jfr.internal.instrument;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.tree.ClassNode;
import jdk.jfr.internal.SecuritySupport;
/**
* This class will perform byte code instrumentation given an "instrumentor" class.
*
* @see JITracer
*
* @author Staffan Larsen
*/
@Deprecated
final class JIClassInstrumentation {
private final Class<?> instrumentor;
private final String targetName;
private final String instrumentorName;
private final byte[] newBytes;
private final ClassReader targetClassReader;
private final ClassReader instrClassReader;
/**
* Creates an instance and performs the instrumentation.
*
* @param instrumentor instrumentor class
* @param target target class
* @param old_target_bytes bytes in target
*
* @throws ClassNotFoundException
* @throws IOException
*/
JIClassInstrumentation(Class<?> instrumentor, Class<?> target, byte[] old_target_bytes) throws ClassNotFoundException, IOException {
instrumentorName = instrumentor.getName();
this.targetName = target.getName();
this.instrumentor = instrumentor;
this.targetClassReader = new ClassReader(old_target_bytes);
this.instrClassReader = new ClassReader(getOriginalClassBytes(instrumentor));
this.newBytes = makeBytecode();
}
private static byte[] getOriginalClassBytes(Class<?> clazz) throws IOException {
String name = "/" + clazz.getName().replace(".", "/") + ".class";
try (InputStream is = SecuritySupport.getResourceAsStream(name)) {
return is.readAllBytes();
}
}
private byte[] makeBytecode() throws IOException, ClassNotFoundException {
// Find the methods to instrument and inline
final List<Method> instrumentationMethods = new ArrayList<>();
for (final Method m : instrumentor.getDeclaredMethods()) {
JIInstrumentationMethod im = m.getAnnotation(JIInstrumentationMethod.class);
if (im != null) {
instrumentationMethods.add(m);
}
}
// We begin by inlining the target's methods into the instrumentor
ClassNode temporary = new ClassNode();
ClassVisitor inliner = new JIInliner(
Opcodes.ASM7,
temporary,
targetName,
instrumentorName,
targetClassReader,
instrumentationMethods);
instrClassReader.accept(inliner, ClassReader.EXPAND_FRAMES);
// Now we have the target's methods inlined into the instrumentation code (in 'temporary').
// We now need to replace the target's method with the code in the
// instrumentation method.
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
JIMethodMergeAdapter ma = new JIMethodMergeAdapter(
cw,
temporary,
instrumentationMethods,
instrumentor.getAnnotationsByType(JITypeMapping.class));
targetClassReader.accept(ma, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
/**
* Get the instrumented byte codes that can be used to retransform the class.
*
* @return bytes
*/
public byte[] getNewBytes() {
return newBytes.clone();
}
}

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.tree.ClassNode;
import jdk.internal.org.objectweb.asm.tree.MethodNode;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
import jdk.jfr.internal.Logger;
@Deprecated
final class JIInliner extends ClassVisitor {
private final String targetClassName;
private final String instrumentationClassName;
private final ClassNode targetClassNode;
private final List<Method> instrumentationMethods;
/**
* A ClassVisitor which will check all methods of the class it visits against the instrumentationMethods
* list. If a method is on that list, the method will be further processed for inlining into that
* method.
*/
JIInliner(int api, ClassVisitor cv, String targetClassName, String instrumentationClassName,
ClassReader targetClassReader,
List<Method> instrumentationMethods) {
super(api, cv);
this.targetClassName = targetClassName;
this.instrumentationClassName = instrumentationClassName;
this.instrumentationMethods = instrumentationMethods;
ClassNode cn = new ClassNode(Opcodes.ASM7);
targetClassReader.accept(cn, ClassReader.EXPAND_FRAMES);
this.targetClassNode = cn;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (isInstrumentationMethod(name, desc)) {
MethodNode methodToInline = findTargetMethodNode(name, desc);
if (methodToInline == null) {
throw new IllegalArgumentException("Could not find the method to instrument in the target class");
}
if (Modifier.isNative(methodToInline.access)) {
throw new IllegalArgumentException("Cannot instrument native methods: " + targetClassNode.name + "." + methodToInline.name + methodToInline.desc);
}
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG, "Inliner processing method " + name + desc);
JIMethodCallInliner mci = new JIMethodCallInliner(access,
desc,
mv,
methodToInline,
targetClassName,
instrumentationClassName);
return mci;
}
return mv;
}
private boolean isInstrumentationMethod(String name, String desc) {
for(Method m : instrumentationMethods) {
if (m.getName().equals(name) && Type.getMethodDescriptor(m).equals(desc)) {
return true;
}
}
return false;
}
private MethodNode findTargetMethodNode(String name, String desc) {
for (MethodNode mn : targetClassNode.methods) {
if (mn.desc.equals(desc) && mn.name.equals(name)) {
return mn;
}
}
throw new IllegalArgumentException("could not find MethodNode for "
+ name + desc);
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface JIInstrumentationMethod {
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface JIInstrumentationTarget {
String value();
}

View File

@ -1,152 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.commons.LocalVariablesSorter;
import jdk.internal.org.objectweb.asm.commons.Remapper;
import jdk.internal.org.objectweb.asm.commons.SimpleRemapper;
import jdk.internal.org.objectweb.asm.tree.MethodNode;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
import jdk.jfr.internal.Logger;
/**
* Class responsible for finding the call to inline and inlining it.
*
* This code is heavily influenced by section 3.2.6 "Inline Method" in
* "Using ASM framework to implement common bytecode transformation patterns",
* E. Kuleshov, AOSD.07, March 2007, Vancouver, Canada.
* http://asm.ow2.org/index.html
*/
@Deprecated
final class JIMethodCallInliner extends LocalVariablesSorter {
private final String oldClass;
private final String newClass;
private final MethodNode inlineTarget;
private final List<CatchBlock> blocks = new ArrayList<>();
private boolean inlining;
/**
* inlineTarget defines the method to inline and also contains the actual
* code to inline.
*
* @param access
* @param desc
* @param mv
* @param inlineTarget
* @param oldClass
* @param newClass
* @param logger
*/
public JIMethodCallInliner(int access, String desc, MethodVisitor mv,
MethodNode inlineTarget, String oldClass, String newClass) {
super(Opcodes.ASM7, access, desc, mv);
this.oldClass = oldClass;
this.newClass = newClass;
this.inlineTarget = inlineTarget;
if (Logger.shouldLog(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG)) {
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG,
"MethodCallInliner: targetMethod=" + newClass + "."
+ inlineTarget.name + inlineTarget.desc);
}
}
@Override
public void visitMethodInsn(int opcode, String owner, String name,
String desc, boolean itf) {
// Now we are looking at method call in the source method
if (!shouldBeInlined(owner, name, desc)) {
// If this method call should not be inlined, just keep it
mv.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
// If the call should be inlined, we create a MethodInliningAdapter
// The MIA will walk the instructions in the inlineTarget and add them
// to the current method, doing the necessary name remappings.
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG, "Inlining call to " + name + desc);
Remapper remapper = new SimpleRemapper(oldClass, newClass);
Label end = new Label();
inlining = true;
inlineTarget.instructions.resetLabels();
JIMethodInliningAdapter mia = new JIMethodInliningAdapter(this, end,
opcode == Opcodes.INVOKESTATIC ? Opcodes.ACC_STATIC : 0, desc,
remapper);
inlineTarget.accept(mia);
inlining = false;
super.visitLabel(end);
}
/**
* Determine if the method should be inlined or not.
*/
private boolean shouldBeInlined(String owner, String name, String desc) {
return inlineTarget.desc.equals(desc) && inlineTarget.name.equals(name)
&& owner.equals(newClass.replace('.', '/'));
}
@Override
public void visitTryCatchBlock(Label start, Label end, Label handler,
String type) {
if (!inlining) {
// try-catch blocks are saved here and replayed at the end
// of the method (in visitMaxs)
blocks.add(new CatchBlock(start, end, handler, type));
} else {
super.visitTryCatchBlock(start, end, handler, type);
}
}
@Override
public void visitMaxs(int stack, int locals) {
for (CatchBlock b : blocks) {
super.visitTryCatchBlock(b.start, b.end, b.handler, b.type);
}
super.visitMaxs(stack, locals);
}
static final class CatchBlock {
final Label start;
final Label end;
final Label handler;
final String type;
CatchBlock(Label start, Label end, Label handler, String type) {
this.start = start;
this.end = end;
this.handler = handler;
this.type = type;
}
}
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.LocalVariablesSorter;
import jdk.internal.org.objectweb.asm.commons.Remapper;
import jdk.internal.org.objectweb.asm.commons.RemappingMethodAdapter;
@Deprecated
final class JIMethodInliningAdapter extends RemappingMethodAdapter {
private final LocalVariablesSorter lvs;
private final Label end;
public JIMethodInliningAdapter(LocalVariablesSorter mv, Label end, int acc, String desc, Remapper remapper) {
super(acc, desc, mv, remapper);
this.lvs = mv;
this.end = end;
int offset = isStatic(acc) ? 0 : 1;
Type[] args = Type.getArgumentTypes(desc);
for (int i = args.length - 1; i >= 0; i--) {
super.visitVarInsn(args[i].getOpcode(Opcodes.ISTORE), i + offset);
}
if (offset > 0) {
super.visitVarInsn(Opcodes.ASTORE, 0);
}
}
private boolean isStatic(int acc) {
return (acc & Opcodes.ACC_STATIC) != 0;
}
@Override
public void visitInsn(int opcode) {
if (opcode == Opcodes.RETURN || opcode == Opcodes.IRETURN
|| opcode == Opcodes.ARETURN || opcode == Opcodes.LRETURN) {
super.visitJumpInsn(Opcodes.GOTO, end);
} else {
super.visitInsn(opcode);
}
}
@Override
public void visitMaxs(int stack, int locals) {
}
@Override
protected int newLocalMapping(Type type) {
return lvs.newLocal(type);
}
}

View File

@ -1,122 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.RemappingMethodAdapter;
import jdk.internal.org.objectweb.asm.commons.SimpleRemapper;
import jdk.internal.org.objectweb.asm.tree.ClassNode;
import jdk.internal.org.objectweb.asm.tree.MethodNode;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
import jdk.jfr.internal.Logger;
/**
* This class will merge (some) methods from one class into another one.
*
* @author Staffan Larsen
*/
@Deprecated
final class JIMethodMergeAdapter extends ClassVisitor {
private final ClassNode cn;
private final List<Method> methodFilter;
private final Map<String, String> typeMap;
/**
* Methods in methodFilter that exist in cn will be merged into cv. If the method already exists,
* the original method will be deleted.
*
* @param cv
* @param cn - a ClassNode with Methods that will be merged into this class
* @param methodFilter - only methods in this list will be merged
* @param typeMappings - while merging, type references in the methods will be changed according to this map
*/
public JIMethodMergeAdapter(ClassVisitor cv, ClassNode cn, List<Method> methodFilter, JITypeMapping[] typeMappings) {
super(Opcodes.ASM7, cv);
this.cn = cn;
this.methodFilter = methodFilter;
this.typeMap = new HashMap<>();
for (JITypeMapping tm : typeMappings) {
typeMap.put(tm.from().replace('.', '/'), tm.to().replace('.', '/'));
}
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
typeMap.put(cn.name, name);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if(methodInFilter(name, desc)) {
// If the method is one that we will be replacing, delete the method
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG, "Deleting " + name + desc);
return null;
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
@Override
public void visitEnd() {
SimpleRemapper remapper = new SimpleRemapper(typeMap);
for (MethodNode mn : cn.methods) {
// Check if the method is in the list of methods to copy
if (methodInFilter(mn.name, mn.desc)) {
if (Logger.shouldLog(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG)) {
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG, "Copying method: " + mn.name + mn.desc);
Logger.log(LogTag.JFR_SYSTEM_BYTECODE, LogLevel.DEBUG, " with mapper: " + typeMap);
}
String[] exceptions = new String[mn.exceptions.size()];
mn.exceptions.toArray(exceptions);
MethodVisitor mv = cv.visitMethod(mn.access, mn.name, mn.desc, mn.signature, exceptions);
mn.instructions.resetLabels();
mn.accept(new RemappingMethodAdapter(mn.access, mn.desc, mv, remapper));
}
}
super.visitEnd();
}
private boolean methodInFilter(String name, String desc) {
for(Method m : methodFilter) {
if (m.getName().equals(name) && Type.getMethodDescriptor(m).equals(desc)) {
return true;
}
}
return false;
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2013, 2018, 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.
*/
package jdk.jfr.internal.instrument;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@interface JITypeMapping {
String from();
String to();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, 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
@ -41,6 +41,7 @@ import jdk.jfr.EventSettings;
import jdk.jfr.EventType;
import jdk.jfr.Recording;
import jdk.jfr.consumer.EventStream;
import jdk.jfr.internal.JDKEvents;
import jdk.jfr.internal.JVMSupport;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
@ -57,7 +58,6 @@ import jdk.jfr.internal.WriteableUserPath;
import jdk.jfr.internal.consumer.AbstractEventStream;
import jdk.jfr.internal.consumer.EventDirectoryStream;
import jdk.jfr.internal.consumer.FileAccess;
import jdk.jfr.internal.instrument.JDKEvents;
/**
* The management API in module jdk.management.jfr should be built on top of the