Как трансформировать класс с помощью ClassTransformer?
У меня есть готовый ClassTransformer, который мне нужно вызывать исключительно при вызове метода startProfiling. При этом в premain я указала, чтобы трансформер был демоном и ждал выполнения условий. У меня есть задачи, исполнение которых я вызываю в виде потоков, и мне нужно при вызове метода startProfiling добавить к ним время исполнения. Задачи вызываются классом Tasks, но вызываются они и вне метода startProfiling, а трансформер, если мы находимся в классе Tasks начинает менять вывод, хотя мне это пока не нужно (пока я startProfiling не вызвала).
Как разрешить эту проблему? Пробовала ставить флаг в метод startProfiling, добавлять трансформеру еще проверку флага на true, но он просто его не видит.
Вот код классов ClassTransformer, Premain:
public class ClassTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println(className);
try {
if (className.equals("jmx/Tasks")) {
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(loader));
CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
CtMethod[] methods = ctClass.getMethods();
for( CtMethod method : methods){
if (method.getName().equals("run")){
System.out.println("Entering "+ method.getName() + " of " + className);
method.addLocalVariable("elapsedTime", CtClass.longType);
method.insertBefore("elapsedTime = System.currentTimeMillis();");
method.insertAfter("{elapsedTime = System.currentTimeMillis() - elapsedTime;"
+ "System.out.println(\"[profiling]Execution time was: \" + elapsedTime);}");
} }
return ctClass.toBytecode();
}
else {
return classfileBuffer;
} }
catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException();
} } }
public class Premain {
public static void premain(String args, Instrumentation instrumentation) {
instrumentation.addTransformer(new ClassTransformer());
} }
Метод startProfiling:
@Override
public void startProfiling(String name, String mainClass) {
if (Tasks.statusStore.get(name + "|" + mainClass + ".class").equals(Thread.State.RUNNABLE)) {
var classpath = Tasks.classpathStore.get(name + "|" + mainClass + ".class");
cancel(name, mainClass);
try {
isProfiling = true;
submit(name, Tasks.classpathStore.get(name + "|" + mainClass + ".class"),
mainClass, periodStore.get(name + "|" + mainClass + ".class"));
} catch (NullPointerException e) {
System.out.println("\nTask <" + name + "> not found...\n");
} } else {
System.out.println("\nTask <" + name + "> is not in a state of execution!\n");
} }