Byte Buddy installOn API выдает ошибку: добавление ретрансформируемых преобразователей не поддерживается? - PullRequest
1 голос
/ 18 февраля 2020

Почему installOn API выдает ошибку в моем коде. Я хочу вызвать Instrumentation.retransformClasses API из другого потока. или мы можем вызвать API Instrumentation.retransformClasses в bytebuddy. Я хочу вставить поле stati c после загрузки класса. Если это возможно, был бы хорош короткий пример!

public static void premain(String arguments, Instrumentation instrumentation) {

    System.out.println("Agent for add fields ");
    final ByteBuddy byteBuddy = new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE);
    new AgentBuilder.Default()    
              .with(byteBuddy).with(RedefinitionStrategy.RETRANSFORMATION)
              .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
              .with(TypeStrategy.Default.REDEFINE)
              .type((ElementMatchers.nameContains("Method")))
              .transform(new Transformer() {
                   public Builder<?> transform(Builder<?> arg0, TypeDescription arg1, ClassLoader arg2,
                            JavaModule arg3) {
                        // TODO Auto-generated method stub
                        return null;
                    }
                })
              .installOn(instrumentation);

    Thread thread = new Thread() {
        public void run() {
            System.out.println("Thread Running");
            try {
                Thread.currentThread().sleep(10000);

                Class c[] = instrumentation.getAllLoadedClasses();
                for (int i = 0; i < c.length; i++) {
                    String clsName = c[i].getName();

                    System.out.println(clsName);
                    if (clsName.equals("com.github.shehanperera.example.Method")) {

                            instrumentation.retransformClasses(c[i]);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println(e);
            }

        }
    };

    thread.start(); 
}

Предоставление исключения:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
Caused by: java.lang.IllegalStateException: Could not install class file transformer
    at net.bytebuddy.agent.builder.AgentBuilder$Default.installOn(AgentBuilder.java:8538)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$Delegator.installOn(AgentBuilder.java:10179)
    at com.github.shehanperera.addfield.Agent.premain(Agent.java:39)
    ... 6 more
Caused by: java.lang.UnsupportedOperationException: adding retransformable transformers is not supported in this environment
    at sun.instrument.InstrumentationImpl.addTransformer(InstrumentationImpl.java:88)
    at net.bytebuddy.agent.builder.AgentBuilder$Default.installOn(AgentBuilder.java:8514)
    ... 8 more
FATAL ERROR in native method: processing of -javaagent failed

1 Ответ

2 голосов
/ 18 февраля 2020

Javassist не допускает ничего подобного по умолчанию, javassist просто делает хитрый трюк и позволяет редактировать класс до его фактической загрузки, так как классы загружаются при первом использовании. В противном случае также должен использоваться типичный агент с ретрансформированием.

И для создания инструментария, который может ретрансформировать классы, необходимо добавить соответствующий флаг в манифест:
Can-Retransform-Classes: true

https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html

...