Как загрузить огромный класс/интерфейс (включая более 40000 статических полей) в фоновом потокеJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как загрузить огромный класс/интерфейс (включая более 40000 статических полей) в фоновом потоке

Сообщение Anonymous »

У меня есть интерфейс примерно с 40 000 статических полей (я знаю, что он огромен), и я стараюсь загрузить его эффективно. Обычная загрузка занимает 10 секунд и замораживает поток пользовательского интерфейса Eclipse, что неприятно для пользователя. Чтобы предотвратить зависание, я попытался загрузить интерфейс в фоновом потоке, используя следующий код:

Код: Выделить всё

var thread = new Thread(() -> {
var classLoader = My_Small_Class_Of_The_Same_Plugin.getClass().getClassLoader();
try {
classLoader.loadClass("My_Super_Big_Interface");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
thread.start();
Неожиданно поток пользовательского интерфейса все еще зависает. Ответственный EquinoxClassLoader зарегистрирован как «параллельно поддерживающий», что похоже на то, что его можно использовать в отдельном потоке для повышения производительности.
Почему это не работает таким образом? Есть ли способ загрузить класс/интерфейс независимо от основного потока/UI потока?
Обратите внимание: я не хочу обсуждать размер интерфейса и то, что его следует разделить на несколько интерфейсов или классов. К сожалению, так дано и мне приходится с этим бороться.
Я обнаружил, что есть проблема с реализацией JVM (в моем случае OpenJDK 21). Когда загрузчик классов начинает загрузку с использованием собственного метода defineClass1(ClassLoader loader, ...); (см.: OpenJDK ClassLoader.java), он приостанавливает каждый поток до тех пор, пока выполняется определение класса. Это как минимум удивительно. Еще более удивительно то, что загрузка класса размером около 1,5 МБ, который не ссылается ни на какие другие классы или интерфейсы, занимает около 10 секунд. Вот небольшой пример (1 класс + 1 интерфейс) того, как его можно воспроизвести:
  • Код: Выделить всё

    My_Super_Big_Interface
    : Поскольку интерфейс слишком велик для публикации его здесь, сгенерируйте его самостоятельно, используя следующий или собственный код:

    Код: Выделить всё

    /**
    * Generates a big interface with a huge number of fields.
    *
    * @param args
    */
    public static void main(String[] args) {
    var NUMBER_OF_FIELDS = 40000;
    var fields = "";
    
    for (var i = 1; i  {
    var i = 1;
    while (true) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("\t\tLoop thread: " + i++ + ".  round: " + LocalDateTime.now());
    }
    }).start();
    System.out.println("Loop thread started at: " + LocalDateTime.now());
    
    // 2) start the class loading thread which pauses the other threads
    var class_Loading_Thread = new Thread(() -> {
    var classLoader = MainClass.class.getClassLoader();
    try {
    var start_Millis = System.currentTimeMillis();
    System.out.println("Before class loading: " + LocalDateTime.now());
    
    // start the loading which causes every thread to pause
    classLoader.loadClass("com.test.My_Super_Big_Interface");       //  11:24:41.438144700
    
    Может ли кто-нибудь проверить результат на своей машине? Пожалуйста, запустите код и не запускайте его в режиме отладки.
    Может ли кто-нибудь запустить его в другой реализации JVM?
    Я пытался найти ответственный код в реализации OpenJDK, начиная здесь: java.base.share.native.libjava.ClassLoader.c, но до сих пор я его не нашел.
    После нескольких тестов кажется, что затраты времени определение класса/загрузка класса экспоненциально зависит от количества полей/членов. Например, для 20000 полей требуется 2 секунды, для 30000 – 6 секунд, для 40 000 – 10 секунд и для 65 000 – 30 секунд.

    Подробнее здесь: https://stackoverflow.com/questions/798 ... -a-backgro
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»