Java ClassNotFoundException для класса, который наверняка загружен - PullRequest
0 голосов
/ 11 января 2019

Я написал библиотеку базы данных sqlite, которая позволяет мне загружать объекты Java во время выполнения из базы данных. Я использую эту библиотеку на сервере Minecraft, где я также добавил свои плагины, которые используют эту библиотеку для хранения и извлечения данных.

Способ настройки сервера и jars: сам сервер (spigot.jar) хранится в папке / spigot / и загружается сценарием оболочки, выполняющим команду java. Эта команда использует библиотеку базы данных (и другие необходимые библиотеки) из / spigot / lib / в своем пути к классам. Затем spigot.jar загружает все плагины (также в формате .jar) из /spigot/plugins/.

Используемая мной команда оболочки:

java -verbose:class -server -Xms4G -Xmx4G -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=2 -XX:+AggressiveOpts -cp "spigot.jar:./lib/*" org.bukkit.craftbukkit.Main nogui | tee output.txt

Способ работы базы данных заключается в следующем: я сохранил полное имя класса с пакетом (например, «com.mywebsite.Foo») в виде строки в базе данных. Когда загружается экземпляр Foo, эта строка используется для загрузки класса. Класс загружается с использованием Class.forName(classname); со строкой в ​​качестве параметра.

Раньше эта установка работала в течение нескольких недель, но теперь я недавно сделал много внутренних изменений в коде с недостаточной тщательностью и сломал немало вещей. Я исправил большинство ошибок, которые я делаю, но все равно получаю исключение ClassNotFoundException в строке Class.forName(classname);, хотя я очень уверен, что раньше это работало. Я добавил аргумент -verbose: class в команду оболочки, чтобы загрузить сервер и убедиться, что классы, которые он пытается загрузить, включены и включены.

Sidenote (дополнительная информация о коде, но не напрямую относятся к вопросу):

База данных хранит два типа объектов, объекты, которые реализуют Интерфейс DatabaseObject и объекты, реализующие интерфейс Сериализуемый.

DatabaseObjects предназначены для объектов, которые хранятся в базы данных (например, пользователь класса), и, таким образом, все их значения хранятся в отдельные столбцы, чтобы их можно было легко редактировать.

Сериализуемые объекты предназначены для полей объекта DatabaseObject, которые являются более сложными, чем базовые значения (например, переменная Location внутри Пользователь), и они действуют как обертка вокруг этого поля, так что оно также может храниться и извлекаться. Тем не менее, весь объект хранится как одна строка, поэтому не стоит заменять отдельные значения в этом способ хранения.

Объекты, реализующие DatabaseObject, обычно всегда определяются мной в коде моих плагинов. Тем не менее, объекты, которые должны быть Сериализованные, как правило, определяются не мной, а Spigot API, это еще одна причина, почему я использую эту обертку.

Я нашел какое-то решение для получения значения класса Тип реализации DatabaseObject, сохраняя класс, как он передается к базе данных (что происходит при инициализации базы данных, чтобы он знал какие значения хранить для каждого класса). Поэтому вместо использования Class.forName(), я могу просто сравнить строку с сохраненными классами и получите его оттуда.

Но это решение не распространяется ни на одну из реализаций Сериализуемый, потому что они изначально не передаются в базу данных. Создание обходного пути для этого было бы возможно, но это не чувствуется как чистый код для меня. Учитывая факты, которые: Class.forName() раньше работать раньше, класс загружается в соответствии с подробным аргументом, и что я могу получить типы DatabaseObject, если я на самом деле храню их значения, означает, что должен быть какой-то способ для меня Class.forName() работать снова в этом контексте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...