Код: Выделить всё
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();
Почему это не работает?
Есть ли способ загрузить класс/интерфейс независимо от основного потока/потока пользовательского интерфейса?
Обратите внимание: я не хочу обсуждать размер интерфейса и что его следует разделить на несколько интерфейсов или классов. К сожалению, так дано и мне приходится с этим бороться.
Редактировать 1
Я обнаружил, что существует проблема с реализацией 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.
[b]Может ли кто-нибудь проверить результат на своей машине?[/b] Пожалуйста, запустите код и НЕ запускайте его в режиме отладки.
[b]Может ли кто-нибудь запустить его в другой реализации JVM?[/b]
Я пытался найти ответственный код в реализации OpenJDK, начиная здесь: java.base.share.native.libjava.ClassLoader.c, но до сих пор не нашел его.
После пары тестов выяснилось, что время выполнения класса увеличивается. Загрузка определения/класса экспоненциально зависит от количества полей/членов. Например, для 20000 полей требуется 2 секунды, для 30000 – 6 секунд, для 40 000 – 10 секунд и для 65 000 – 30 секунд.
Подробнее здесь: [url]https://stackoverflow.com/questions/79873770/eclipse-how-to-load-a-huge-class-interface-including-40000-static-fields-in[/url]
Мобильная версия