Я написал библиотеку базы данных 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()
работать снова в этом контексте.