В некоторых структур, относящихся к файлам внутри JAR-можно сделать с помощью префикса classpath:
.
Я сомневаюсь, что URLClassLoader поддерживает его изначально, но стоит попробовать (например,
classpath:/my/app/sub/package/h2.jar
).
Но так как это не работает с URLClassLoader, здесь и другие способы:
Один из способов сделать это было бы написать свой собственный ClassLoader, который считывает файл JAR из пути к классам (используя getResourceAsStream), распаковывает его (используя ZipInputStream) в память (например, карту массивов байтов) и загружает классы оттуда.
Другой, немного более простой способ - прочитать JAR-файл из пути к классам и записать его во временный файл. Затем вы можете использовать простой URLClassLoader для загрузки классов из него. Это имеет тот недостаток, что файл должен быть записан в файл, и файл, вероятно, не может быть удален до выхода JVM (unless using Java 7 или выше).
Я использую второй подход (копирование во временный файл) in one project, хотя я использую его для launch an external process. Мне было бы интересно узнать, почему у вас есть такое требование. Если это всего лишь вопрос о наличии всего приложения в одном JAR, для этого есть множество простых методов (Maven Assembly Plugin, Maven Shade Plugin, Jar Jar Links, One-JAR, чтобы назвать несколько).
Нет это не не домашнее задание, но онлайн система сборки, которая использует свои классы под моим/приложение/* и несколько других классов (не от меня), чтобы автоматически создать все решение. Во всяком случае, я не могу дать вам более подробную информацию о внутренних компонентах этой системы, поскольку я их не знаю. Как уже говорилось, я просто жить с этим, и именно поэтому я прошу здесь ...
Похоже, вы работаете в WTF среде (у него есть имя?), так вот несколько способов начать взломать его:
Узнайте больше о вашей среде, особенно абсолютных путей к файлу: каталог, в котором хранятся исходные файлы, каталог, в котором сохранены сгенерированные файлы .class, и текущий рабочий каталог при запуске программы.
Если вы можете получить какой-либо вывод о том, что ваша программа печатает во время выполнения, вы можете добавить в свое приложение код отладки, в котором вы используете File.listFiles() для сканирования дерева каталогов машины. Если вы можете получить вывод только из того, что происходит при компиляции, возможно, вы сможете выполнить свой собственный код во время компиляции, создав свой собственный annotation processor (apt является частью javac с Java 6), хотя я не уверен, должен ли обработчик аннотации сначала составляться.
Рабочий каталог можно прочитать из системного свойства user.dir
, и расположение файлов классов может быть, вероятно, получено из системного свойства java.class.path
(если не используются специальные загрузчики классов). Нет никакой гарантии, что файл JAR в исходном каталоге будет скопирован в путь к классам, поэтому вам может потребоваться некоторое время оглядеться.
Затем, когда вы знаете путь к файлу JAR-файла, вы можете получить URL-адрес, используя new File("path/to/h2.jar").toURI().toURL()
, который затем можно передать URLClassLoader.
Если ничего не работает, загрузите исходный код библиотек и скомпилируйте их вместе с вашим проектом.
В конечном итоге попробуйте заменить среду сборки WTF той, которая использует стандартный инструмент сборки (например, Maven) и общий сервер CI (например, Jenkins). Обычно для проектов есть множество зависимостей между библиотеками, поэтому вам не нужно взламывать среду сборки, чтобы использовать их.
Вы попробовали jar: файл: my/app/sub/package/h2.jar? – kosa
«Странная настройка», которую вы описываете, является довольно обычной структурой каталогов. Нет причин помещать файлы JAR в папку 'src'. Похоже, вы просто не используете 'h2.jar' в своем пути к классам. –
@thinksteep: да, попробовал, но это не сработало. – Matthias