如何使用Java13+动态设置java.library.path?

muk1a3rh  于 2021-06-29  发布在  Java
关注(0)|答案(0)|浏览(389)

所以基本上我在一个jar文件中有几个本机文件,我需要动态地提取并添加到类路径/模块路径。本机文件类似于.dll、.pak的语言文件等。因此,默认的system.load/system.loadlibrary将不适用于非dll
那么我们尝试了什么:使用java.lang.reflection usr.paths 变数,似乎是显而易见的方法:

Field userPathsField = ClassLoader.class.getDeclaredField("usr_paths");
userPathsField.setAccessible(true);
String[] paths = (String[]) userPathsField.get(null);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < paths.length; i++) {
    if (libraryPath.equals(paths[i])) {
        continue;
    }
    sb.append(paths[i]).append(File.pathSeparatorChar);
}
sb.append(libraryPath);
System.setProperty("java.library.path", sb.toString());

但不幸的是,由于 java.lang.reflect 过滤:https://bugs.openjdk.java.net/browse/jdk-8210522
同一篇文章似乎提出了一个选择 MethodHandle.Lookup 比如:

static {
        Module java_base = Field.class.getModule(), unnamed = CefHelper.class.getModule(); 
        //System.out.println("module name: "+unnamed.getName());
        java_base.addOpens("java.lang.reflect", unnamed); 
        java_base.addOpens("java.util", unnamed);
        try {
            var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
            String[] paths = (String[])lookup.findVarHandle(Field.class, "usr_paths", String[].class).get();
          //for loop goes here to add the paths to StringBuilder...
        } catch (IllegalAccessException | NoSuchFieldException ex) {
            throw new RuntimeException(ex);
         }
    }

但仍然不是香草,因为即使我显式地将其放入静态块(如上图所示)或将其添加到pom.xml中:

<build>
   <plugins>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.8.0</version>
         <configuration>
            <release>11</release>
             <compilerArgs>
                <arg>--add-opens</arg><arg>java.base/java.lang=ALL-UNNAMED </arg>
                <arg>--add-opens</arg><arg>java.base/java.lang.reflect=ALL-UNNAMED</arg>
                <arg>--add-opens</arg><arg>java.base/java.io=ALL-UNNAMED</arg>
             </compilerArgs>
        </configuration>
     </plugin>
     <plugin>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-maven-plugin</artifactId>
        <version>0.0.3</version>
        <configuration>
           <mainClass>foo.bar.App</mainClass> 
           <options>
              <option>--add-opens</option><option>java.base/java.lang=ALL-UNNAMED</option>
              <option>--add-opens</option><option>java.base/java.lang.reflect=ALL-UNNAMED</option>
              <option>--add-opens</option><option>java.base/java.io=ALL-UNNAMED</option>
            </options>        
       </configuration>
   </plugin>
  </plugins>
</build>

它仍然不允许我获取usr.paths,因此我可以将我的本机路径添加到已经存在的路径中。
例外情况:

Caused by: java.lang.IllegalCallerException: java.lang.reflect is not open to module foo.bar.xxx
    at java.base/java.lang.Module.addOpens(Module.java:762)
    at foo.bar.ReflectionHelper.<clinit>(ReflectionHelper.java:22)
    ... 19 more

所以即使我添加addopens部分,它也不会打开它看起来。。。?
有人能给我出个解决办法吗。。。?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题