Большой большой большой отказ от ответственности здесь! Не делай этого !!!!
Вы не должны устанавливать корневой каталог после его установки. Я не совсем уверен, в чем здесь философия дизайна, но я предполагаю, что это связано с безопасностью и не позволяет вредоносному коду заставить ваше приложение делать что-то неожиданное. Тем не менее, есть способы, которыми мы можем обойти это, используя некоторые неприятные размышления.
Я добился этого взлома путем отладки, когда класс Paths
находит каталог по умолчанию и загружает файлы. Я использую отражение для редактирования значений класса FileSystem
, который, как я видел, он использует. Этот хак будет зависеть от операционной системы, так как он редактирует экземпляр FileSystem
. Это также может быть изменено, поскольку нет гарантии, что экземпляр не будет обновлен. Вы должны будете проверить его на всех целевых системах, так как они будут иметь различные FileSystem
реализации (НО ПОЖАЛУЙСТА, НЕ ДЕЛАЙТЕ НАСТОЯЩЕГО ЭТОГО) .
Кроме того, с новыми изменениями в Java 9 вы не сможете легко заставить этот хак работать (они не разрешают использовать отражение для редактирования классов, не представленных «модулем»). Лучше всего раскрутить новый экземпляр JVM и сделать вызов с переданным свойством -Droot
. Это не очень хорошее решение, но и кодовая база, с которой вы работаете. Вы должны активно пытаться исправить это более разумным способом. (Может быть, лучше всего переписать библиотеку, если бизнес-функция действительно важна)
Рабочая демонстрация с файлом в моем рабочем каталоге и файлом в моем C:\\
:
public static void main(final String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Files.readAllLines(new File("foo.txt").toPath()).forEach(System.out::println);
final Class windowsFileSystemClass = Thread.currentThread().getContextClassLoader().loadClass("sun.nio.fs.WindowsFileSystem");
final Field windowsFileSystemClassField = windowsFileSystemClass.getDeclaredField("defaultDirectory");
windowsFileSystemClassField.setAccessible(true);
final Class windowsPathClass = Thread.currentThread().getContextClassLoader().loadClass("sun.nio.fs.WindowsPath");
final Field windowsPathFsField = windowsPathClass.getDeclaredField("fs");
windowsPathFsField.setAccessible(true);
// Hack that uses a path instance to grab reference to the shared FileSystem instance.
final Object fileSystem = windowsPathFsField.get(Paths.get(""));
windowsFileSystemClassField.set(fileSystem, "C:\\");
Files.readAllLines(new File("foo.txt").toPath()).forEach(System.out::println);
}
Это выводит:
I'm in the working directory
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.Main (file:/C:/Users/calve/IdeaProjects/untitled1/out/production/untitled1/) to field sun.nio.fs.WindowsFileSystem.defaultDirectory
WARNING: Please consider reporting this to the maintainers of com.Main
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
I'm in C: now
Обратите внимание и прислушайтесь к предупреждениям, только что выданным JVM.