javax.tools.JavaCompiler ClassLoader question
Hi
I am using the brand new javax.tools.JavaCompiler feature to compile on the fly some source code. However using the library under web start becomes cery tricky.
1) The compiler tries to read the java.endorsed.dirs system property and it fails. The only solution I have found so far is to grant all permission on the client javaws.policy file (which is the more than bad solution. I have posted a thread here too: http://forum.java.sun.com/thread.jspa?messageID=9620391 )
2) If I solve problem 1, then the compilation fails again because the new class I am creating implements an Interface which is normally found in the class path. However that is no more true on web start since application jars are loaded by a custom class loader, and the JavaCompiler (even though called from within the classloader who knows the required interface) is not able to find the interface.
Now the question is: is there a reason why JavaCompiler uses a class loader whose parent is not taken from the instantiating method but rather the system class loader is used directly? Or is there something I am missing?
Thanks
Vito Impagliazzo
# 1
The compiler is loaded from tools.jar and ToolProvider needs to create a class loader that searches tools.jar. If you have configured your system so that tools.jar is on the class path, then ToolProvider does not need to create a class loader.
However, I suggest that you report this as a bug at bugs.sun.com. We did not really anticipate using the compiler API in webstart applications, but I guess it should work, nonetheless.
# 2
Thanks for the answer... I don't know how to refer to the jre path from within web start. I have solved problem ii) by passing a -cp option to the compiler. Here it is a sample code:
ClassLocader cl = OnTheFlyCompiler.class.getClassLoader();
List<URL> classpath = new ArrayList<URL>();
if ( cl instanceof URLClassLoader ) {
URLClassLoader cl2 = (URLClassLoader)cl;
for (URL jar : cl2.getURLs()) {
classpath.add(jar);
}
}
String classPath = System.getProperty("java.class.path");
for (String path : classPath.split(File.pathSeparator)) {
try {
classpath.add(new URL("file:"+path));
} catch (MalformedURLException e) {
System.err.println("Wrong url: "+e.getMessage());
e.printStackTrace();
}
}
StringBuffer sb = new StringBuffer();
for (URL jar : classpath) {
sb.append(jar.getPath());
sb.append(File.pathSeparatorChar);
}
String ops[] = new String[] {"-cp" , sb.toString() };
This along with disabling security does the trick for me. However I had to use NetX jnlp implementation, since when doing this trick the sun version returns the original urls (like http://internal/webstart/build.jar), whereas NetX returns the path of the downloaded files (e.g. /tmp/build.jar).
I will accept your suggestion and post to bugs.sun.com.
Ciao.