Formula
パッケージにあるクラスがありjavaapplication4
、URLClassLoaderを使用してロードします。ただし、同じパッケージにある別のクラスから呼び出すとTest1
、デフォルトのアクセス修飾子を持つメソッドにアクセスできません(パブリックメソッドにアクセスできます)。
次の例外が発生します。
java.lang.IllegalAccessException:クラスjavaapplication4.Test1は、修飾子""を使用してクラスjavaapplication4.Formulaのメンバーにアクセスできません。
同じパッケージから実行時にロードされたクラスのパッケージプライベートメソッドにアクセスするにはどうすればよいですか?
別のクラスローダーを使用することに問題があると思いますが、理由はわかりません(URLClassLoaderの親を設定しました)。
問題を再現するSSCCE(Windowsパス)-問題はloadClass
メソッドにあると思います:
public class Test1 {
private static final Path TEMP_PATH = Paths.get("C:/temp/");
public static void main(String[] args) throws Exception {
String thisPackage = Test1.class.getPackage().getName();
String className = thisPackage + ".Formula"; //javaapplication4.Formula
String body = "package " + thisPackage + "; "
+ "public class Formula { "
+ " double calculateFails() { "
+ " return 123; "
+ " } "
+ " public double calculate() {"
+ " return 123; "
+ " } "
+ "} ";
compile(className, body, TEMP_PATH);
Class<?> formulaClass = loadClass(className, TEMP_PATH);
Method calculate = formulaClass.getDeclaredMethod("calculate");
double value = (double) calculate.invoke(formulaClass.newInstance());
//next line prints 123
System.out.println("value = " + value);
Method calculateFails = formulaClass.getDeclaredMethod("calculateFails");
//next line throws exception:
double valueFails = (double) calculateFails.invoke(formulaClass.newInstance());
System.out.println("valueFails = " + valueFails);
}
private static Class<?> loadClass(String className, Path path) throws Exception {
URLClassLoader loader = new URLClassLoader(new URL[]{path.toUri().toURL()}, Test1.class.getClassLoader());
return loader.loadClass(className);
}
private static void compile(String className, String body, Path path) throws Exception {
List<JavaSourceFromString> sourceCode = Arrays.asList(new JavaSourceFromString(className, body));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(path.toFile()));
boolean ok = compiler.getTask(null, fileManager, null, null, null, sourceCode).call();
System.out.println("compilation ok = " + ok);
}
public static class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.', '/') + JavaFileObject.Kind.SOURCE.extension),
JavaFileObject.Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
}