0

I am trying to change the method access modifier through an agent via javassist, however, I get an error. So, is it possible to change the access modifier via java agent and how to fix it? Is there any other way to influence the bytecode in runtime?

Agent

public static void premain(String args, Instrumentation instrumentation)
    throws ClassNotFoundException, IOException, UnmodifiableClassException, NotFoundException {

  final ClassPool pool = ClassPool.getDefault();
  pool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));

  final ClassFile file = pool.get("...")
      .getClassFile();
  file.getMethod("...").setAccessFlags(AccessFlag.PUBLIC);

  ByteArrayOutputStream bytes = new ByteArrayOutputStream();
  DataOutputStream dos = new DataOutputStream(bytes);
  file.write(dos);
  
  Class<?> clazz = ...;

  instrumentation.redefineClasses(new ClassDefinition(clazz, bytes.toByteArray()));
}

MANIFEST

Manifest-Version: 1.0
Premain-Class: ...Agent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Can-Set-Native-Method-Prefix: true

Question_283
  • 11
  • 1
  • 4
  • See the [JVMTI spec](https://docs.oracle.com/en/java/javase/17/docs/specs/jvmti.html#RedefineClasses) about redefining classes: " The redefinition **must not** add, remove or rename fields or methods, change the signatures of methods, **change modifiers**, or change inheritance" – Johannes Kuhn Dec 19 '22 at 19:56
  • Thank you! Ohh... is there any way to influence it differently? or nothing? – Question_283 Dec 19 '22 at 20:00
  • There should be no need to do that. What do you actually try to do? (Most of the time, plain old reflection will work as a substitute, or even MethodHandles) – Johannes Kuhn Dec 19 '22 at 20:03
  • I don't have a special goal, it was just interesting to try this way. thank you for the information! – Question_283 Dec 19 '22 at 20:04
  • 2
    You can change access modifiers before the class is defined, either through load-time transformation or by changing the class file even before getting loaded. As a side note, the `Thread.currentThread().getContextClassLoader()` is wrong in most cases (if not all cases). For a particular class, use the class’s defining loader. Or no class loader at all when it comes to bytecode manipulation. Which boils down to not using Javassist for such tasks, as that library leads to using the wrong approaches too often. – Holger Dec 20 '22 at 09:28

0 Answers0