2016-08-25 3 views
1

В настоящее время мы используем premain для преобразования всех классов до их загрузки. Но мы хотим сделать преобразование под контролем, что означает, что мы можем удалить/повторно добавить код, который мы вставляем в методы.Можем ли мы повторно преобразовывать классы после их загрузки?

Итак, мы нашли ретрансформу, но я не совсем понимаю ее.

  1. Можно ли загружать классы классов?
  2. Если это можно сделать, будут ли экземпляры повторно преобразованных классов запускать повторно преобразованный код?
  3. Если это невозможно, существует ли какая-либо технология для изменения кода определенного метода во время выполнения.

ОБНОВЛЕНО

Например, мы имеем класс А. Класс A имеет два метода Foo() и бар():

void foo() { 
    while(true) { 
     bar(); 
    } 
} 
void bar() { 
    System.out.println("a"); 
} 

мы называем Instrument.retransformClasses (Класс). и изменить бар() для:

void bar() { 
    System.out.println("b"); 
} 

Если есть поток уже вызова Foo(), мы можем иметь выход:

... 
a 
a 
a 
b 
b 
b 
... 

если нет, то есть ли способ осуществить это?

+0

Что вы подразумеваете под "transform"? – byxor

+1

Возможный дубликат [Обновить код Java во время выполнения] (http://stackoverflow.com/questions/3079280/update-java-code-during-runtime) – Blobonat

+0

В настоящее время мы реализуем ClassFileTransformer для вставки некоторого кода для каждого метода классов, который есть специальная аннотация на нем. Как я понимаю, преобразование изменяет байт-коды класса (по крайней мере, он выглядит как изменение байт-кодов, согласно javadoc классаFileTransformer # transform()). –

ответ

1

Итак, у вас уже есть ClassFileTransformer для преобразования байт-кода класса перед его загрузкой и установкой в ​​JVM. И теперь вы захотите снова преобразовать его по жизненному циклу JVM, не так ли?

Ну, ретрансформация может быть выполнена с помощью Instrumentation, через метод Instrumentation.retransformClasses. Но сначала вам необходимо обеспечить поддержку ретрансляции, позвонив по номеру Instrumentation.isRetransformClassesSupported.

Когда эта ретрансформация действует? В соответствии с javadocs:

Если ретрансформационный метод имеет активные кадры стека, то эти активные кадры продолжают запускать байт-коды исходного метода. Ретрансформированный метод будет использоваться для новых вызовов.

Это означает, что в вашем примере foo() повторно ссылается на bar(). Если между тем ретрансформируется bar, преобразованный код будет иметь эффект на следующей следующей итерации, которая вызывает bar.

Добавлю еще некоторую сложность в вашем примере:

void foo() { 
    while(true) { 
     bar(); 
    } 
} 

void bar() { 
    myRetransform(); 
    System.out.println("a"); 
} 

void myRetransform() { 
    // This is where a retransformation of class A, method bar, is triggered. 
} 

Когда ретрансформации срабатывает, текущий кадр стека:

  • myRetransform
  • бар
  • Foo

В нем есть активный стек стека вызовов с bar, поэтому, когда возвращается myRetransform, он все равно напечатает «a» в system.out.

Затем bar вернется и оставить текущий кадр стека, как это:

  • Foo

И Теперь когда последний срабатывает преобразование вступит в силу. I.e: в самом следующем вызове до bar.