2

AdoptOpenJDK の Java 11 と ant をビルド目的で使用する 2 つのプロジェクトがあります。どちらも命名を除いて同じコードベースを使用しています。

1 つ目は、名前のないモジュールにコードを含む非モジュール プロジェクトです。これは例外なしで実行され、期待どおりにライブラリを追加します。

これは、メイン クラスのコードです。

package nonmodularsampleproject;

import java.lang.reflect.Field;
import java.util.Arrays;

/**
 *
 * @author Robert
 */
public class NonModularSampleProject {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String installationDirectory = System.getProperty("user.dir");
        String pathToAdd = installationDirectory + "\\" + "natives" + "\\" + "displays";
        try {
            addLibraryPath(pathToAdd);
        } catch (Exception ex) {
            System.err.println("Error while add the Native-Library-Path to the System.");
        }

        System.loadLibrary("displays");        
    }
    
    private static void addLibraryPath(String pathToAdd) throws Exception { 
        Module baseModule = ClassLoader.class.getModule(), unnamedModule = NonModularSampleProject.class.getModule();
        System.out.println("ClassLoader.class.getModule() "  + ClassLoader.class.getModule());
        System.out.println("ModularSampleProject.class.getModule() "  + NonModularSampleProject.class.getModule());
        System.out.println("module names: " + baseModule.getName() + " " + unnamedModule.getName());
        
        try {               
            baseModule.addOpens("java.lang", unnamedModule);
        } catch (IllegalCallerException ex) {
            System.err.println("IllegalCallerException " + ex);
        }
        
        final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
        usrPathsField.setAccessible(true);

        //get array of paths
        final String[] paths = (String[]) usrPathsField.get(null);

        //check if the path to add is already present
        for (String path : paths) {
            if (path.equals(pathToAdd)) {
                return;
            }
        }

        //add the new path
        final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
        newPaths[newPaths.length - 1] = pathToAdd;
        usrPathsField.set(null, newPaths);
        
    }        
    
}

2 つ目は、名前付きモジュールにコードを含むモジュラー プロジェクトです。これは例外をスローします。ライブラリの追加に失敗します。

これはモジュール情報のコードです:

module ModularSampleProject {
    requires java.base;
}

これは、メイン クラスのコードです。

package modularsampleproject;

import java.lang.reflect.Field;
import java.util.Arrays;

/**
 *
 * @author Robert
 */
public class ModularSampleProject {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String installationDirectory = System.getProperty("user.dir");
        String pathToAdd = installationDirectory + "\\" + "natives" + "\\" + "displays";
        try {
            addLibraryPath(pathToAdd);
        } catch (Exception ex) {
            System.err.println("Error while add the Native-Library-Path to the System.");
        }

        System.loadLibrary("displays");        
    }
    
    private static void addLibraryPath(String pathToAdd) throws Exception { 
        Module baseModule = ClassLoader.class.getModule(), namedModule = ModularSampleProject.class.getModule();
        System.out.println("ClassLoader.class.getModule() "  + ClassLoader.class.getModule());
        System.out.println("ModularSampleProject.class.getModule() "  + ModularSampleProject.class.getModule());
        System.out.println("Module names: " + baseModule.getName() + " " + namedModule.getName());
        
        try {               
            baseModule.addOpens("java.lang", namedModule);
        } catch (IllegalCallerException ex) {
            System.err.println("IllegalCallerException " + ex);
        }
        
        final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
        usrPathsField.setAccessible(true);

        //get array of paths
        final String[] paths = (String[]) usrPathsField.get(null);

        //check if the path to add is already present
        for (String path : paths) {
            if (path.equals(pathToAdd)) {
                return;
            }
        }

        //add the new path
        final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
        newPaths[newPaths.length - 1] = pathToAdd;
        usrPathsField.set(null, newPaths);
    }    
    
}

このアプローチは、stackoverflow に関するこれら 2 つの他の優れた投稿に基づいています。
Java で実行時にネイティブ ライブラリの新しいパスを追加する
Java 13+ で java.library.path を動的に設定するにはどうすればよいですか?

この投稿も大いに役立ちました。
http://fahdshariff.blogspot.de/2011/08/ching-java-library-path-at-runtime.html

モジュラー プロジェクトでは baseModule.addOpens("java.lang", namedModule) を呼び出すと IllegalCallerException がスローされますが、非モジュラー プロジェクトではすべてがスムーズに機能します。

これは例外スタック トレースです。

SCHWERWIEGEND: Error while open the package java.lang of the module java.base to the module ModularSampleProject
java.lang.IllegalCallerException: java.lang is not open to module ModularSampleProject
    at java.base/java.lang.Module.addOpens(Module.java:762)
    at ModularSampleProject/modularsampleproject.ModularSampleProject.addLibraryPath(ModularSampleProject.java:44)
    at ModularSampleProject/modularsampleproject.ModularSampleProject.main(ModularSampleProject.java:28)

モジュラー プロジェクトの何が問題になっていますか?

4

0 に答える 0