Удержание MethodHandles.lookup (). DefineClass - PullRequest
0 голосов
/ 09 октября 2018

MethodHandles.Lookup.defineClass создает новый класс из байтового массива во время выполнения.

При каких обстоятельствах возвращаемый класс может быть подвергнут сборке мусора?Сохраняется ли он в течение всего времени жизни загрузчика классов, связанного с объектом Lookup, или он может быть удален, если на объект Class больше нет ссылок?

1 Ответ

0 голосов
/ 09 октября 2018

Классы, созданные с помощью MethodHandles.Lookup.defineClass, регистрируются в загрузчике определяющих классов, как и любой другой класс, и на них можно ссылаться по именам, как и обычные классы.Они могут даже заменить статически скомпилированные классы при регистрации до того, как эти классы будут разрешены, как в следующем примере:

import java.lang.invoke.MethodHandles;
import java.nio.charset.StandardCharsets;

public class LookupDynamicClass {
    public static void main(String[] args) throws IllegalAccessException {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        lookup.defineClass(("Êþº¾\0\0\0005\0\26\11\0\11\0\12\10\0\13\12\0\14\0"
        +"\15\7\0\16\7\0\17\1\0\3foo\1\0\3()V\1\0\4Code\7\0\20\14\0\21\0\22\1\0"
        +"\30hello from dynamic class\7\0\23\14\0\24\0\25\1\0\4Lazy\1\0\20java/"
        +"lang/Object\1\0\20java/lang/System\1\0\3out\1\0\25Ljava/io/PrintStream;"
        +"\1\0\23java/io/PrintStream\1\0\7println\1\0\25(Ljava/lang/String;)V\6\0"
        +"\0\4\0\5\0\0\0\0\0\1\0\11\0\6\0\7\0\1\0\10\0\0\0\25\0\2\0\0\0\0\0\11²\0"
        + "\1\22\2¶\0\3±\0\0\0\0\0\0").getBytes(StandardCharsets.ISO_8859_1));

        Lazy.foo();
    }
}
interface Lazy {
    static void foo() {
    }
}

Попробуйте это онлайн

Этот пример динамическиопределяет класс Lazy, метод foo() которого будет вызывать hello from dynamic class при вызове.

На JVM, таких как HotSpot, где символическая ссылка "Lazy" разрешается лениво, то есть прямо при попыткеinvoke Lazy.foo() сделан, это закончится в динамически определенном классе.Для JVM, которые с готовностью разрешают символьные ссылки, класс Lazy уже существует, когда вызывается MethodHandles.Lookup.defineClass, и поэтому будет выдано LinkageError с сообщением типа «попытка повторного определения для Lazy».

Inдругими словами, эти динамически сгенерированные классы имеют то же пространство имен (контекст загрузки классов), что и статически скомпилированные классы.Будучи зарегистрированными в загрузчике классов как обычный класс, они могут собирать мусор только тогда, когда загрузчик определяющего класса становится недоступным (включая все его определенные классы), как в случае с обычными классами.

...