0

I want to overwrite the return value of a static method, SysMLUtilityInternal.getFlowPropertyDirection(), deeply buried in a foreign JAR. The code below is part of a MagicDraw plugin. It runs as expected if the plugin is started from IntelliJ.

If, however, the plugin is run in a standalone mode (that is properly installed under MagicDraw), the code is either a) ignored, b) it crashes MagicDraw, or c) it fails with an unrelated NoClassDefFoundError depending on the class loader used (commented out in the code below).

How can I ensure a consistent behavior?

private static class MyAdvice {
    @Advice.OnMethodExit
    public static void exit(@Advice.Return(readOnly = false) String returned) {
        returned = "";
    }
}

public static void applyPatch() {
    ByteBuddyAgent.install();
    Class<?> clazz = SysMLUtilityInternal.class;
    ClassLoader loader = new MultipleParentClassLoader.Builder().appendMostSpecific(clazz).build();
    //ClassLoader loader = clazz.getClassLoader();
    //ClassLoader loader = ClassLoader.getPlatformClassLoader();
    //ClassLoader loader = ClassLoader.getSystemClassLoader();
    
    new ByteBuddy()
            .redefine(clazz)
            .visit(Advice.to(MyAdvice.class).on(ElementMatchers.named("getFlowPropertyDirection")))
            .make()
            .load(loader, ClassReloadingStrategy.fromInstalledAgent());
            
}
takiwo
  • 1
  • 1

1 Answers1

0

The question is what class loader SysMLUtilityInternal will be loaded on. Your agent will be loaded on the system loader. If the class in question is not present on that class loader, the agent will fail.

Rather, use an AgentBuilder with retransformation enabled. Instead of using the type literal, match the type by name.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192