#java #classloader #glassfish-4 #java-compiler-api
#java #загрузчик классов #glassfish-4 #java-compiler-api
Вопрос:
использование glassfish4, ошибки jdk1.7 в методе task.call(),
>compiler.err.cant.resolve.location.args
>padm.exforms.MemoryFileManager$JavaSourceFromString[mfm:///CM.java]]]
>cannot find symbol
symbol: method getVal(int,int)
location: class padm.exforms.CM]
and etc...
в клиенте j2se этот код работает нормально, на сервере glassfish возникают ошибки
пример кода;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector();
String className = "CM";
Class<?>_class = getClassFromString(compiler, diagnostics, Arrays.asList("-g:none", "-classpath", System.getProperty("java.class.path")), className, getClassCode(className));
private Class<?> getClassFromString(JavaCompiler compiler, DiagnosticListener<JavaFileObject> listener, List<String> flags, String className, String classCode) {
MemoryFileManager mfm = new MemoryFileManager(compiler.getStandardFileManager(listener, null, null));
JavaFileObject fileObject = MemoryFileManager.makeSource(className, classCode);
CompilationTask task = compiler.getTask(null, mfm, listener, flags, null, Arrays.asList(fileObject));
if (task.call()) { //error in this call
ClassLoader cl = mfm.getClassLoader(StandardLocation.CLASS_OUTPUT);
try {
return cl.loadClass(className);
} catch (ClassNotFoundException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "err:" e);
return null;
}
} else
return null;
}
private String getClassCode(String className) {
StringBuilder sb = new StringBuilder();
sb.append("package padm.exforms;"); //also tried without this line
sb.append("import java.math.*; import java.sql.*; public class ");
sb.append(className);
sb.append(" extends ");
sb.append(ConditionManager.class.getCanonicalName());
sb.append("{public ");
sb.append(className);
sb.append("(){}");
}
как использовать javacompiler в glassfish4?
я также попытался установить делегат загрузчика классов =false в sun-web.xml , но после этого компоненты ejb не работают
Спасибо
Ответ №1:
Вы можете попробовать следующее:
Создайте новый ArrayList
:
List<JavaFileObject> classes = new ArrayList<JavaFileObject>();
Добавьте свой fileObject
:
classes.add(new SimpleJavaFileObject(new URI(PATH_TO_JAVA_FILE),JavaFileObject.Kind.SOURCE));
Передайте ArrayList
getTask()
методу:
CompilationTask task = compiler.getTask(null, mfm, listener, flags, null, classes);
Другой способ:
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> classes = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(new File(PATH_TO_JAVA_FILE)));
CompilationTask task = compiler.getTask(null, mfm, listener, flags, null, classes);
Комментарии:
1. что должно быть установлено в PATH_TO_JAVA_FILE ? файл java является строкой
2. Как следует из названия переменной, путь к вашему java-файлу.
3. у меня нет файла java, исходный код java находится в объекте String, возврат из метода getClassCode()
Ответ №2:
чем это отличается от используемой версии? этот класс MemoryFileManager;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.*;
import javax.tools.JavaFileObject.Kind;
/**
* A file manager for compiling strings to byte arrays. This file manager
* delegates to another file manager to lookup classes on boot class path.
* <p/>
* <p>
* <b>This is NOT part of any supported API. If you write code that depends on
* this, you do so at your own risk. This code and its internal interfaces are
* subject to change or deletion without notice.</b>
* </p>
*
* @author Peter von der Ahamp;eacute;
*/
public final class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
/**
* Maps binary class names to class files stored as byte arrays.
*/
private Map<String, byte[]> classes;
/**
* Creates a JavaFileObject representing the given compilation unit.
*
* @param name a NAME representing this source code, for example, the NAME
* of a class
* @param code a compilation unit (source code for a Java program)
* @return a JavaFileObject represtenting the given compilation unit
*/
public static JavaFileObject makeSource(String name, String code) {
return new JavaSourceFromString(name, code);
}
/**
* Construct a memory file manager which delegates to the specified file
* manager for unknown sources.
*
* @param fileManager a file manager used to look up class files on class
* path, etc.
*/
public MemoryFileManager(JavaFileManager fileManager) {
super(fileManager);
classes = new HashMap();
}
/**
* Get a class loader which first search the classes stored by this file
* mananger.
*
* @return a class loader for compiled files
*/
@Override
public ClassLoader getClassLoader(Location location) {
Enumeration<URL> e = null;
try {
e = MemoryFileManager.class.getClassLoader().getResources("");
} catch (IOException e1) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "error:" e1);
}
assert e != null;
while (e.hasMoreElements()) {
System.out.println("ClassLoader Resource: " e.nextElement());
}
System.out.println("Class Resource: " MemoryFileManager.class.getResource("/"));
return new ByteArrayClassLoader(classes);
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String name, Kind kind, FileObject originatingSource) throws UnsupportedOperationException {
if (originatingSource instanceof JavaSourceFromString)
return new JavaClassInArray(name);
else
throw new UnsupportedOperationException();
}
protected static URI uriFromString(String uri) {
try {
return new URI(uri);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
/**
* A file object representing a Java class file stored in a byte array.
*/
private class JavaClassInArray extends SimpleJavaFileObject {
private String name;
/**
* Constructs a JavaClassInArray object.
*
* @param name binary NAME of the class to be stored in this file object
*/
JavaClassInArray(String name) {
super(uriFromString("mfm:///" name.replace('.', '/') Kind.CLASS.extension), Kind.CLASS);
this.name = name;
}
@Override
public OutputStream openOutputStream() {
return new FilterOutputStream(new ByteArrayOutputStream()) {
@Override
public void close() throws IOException {
out.close();
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
classes.put(name, bos.toByteArray());
}
};
}
}
/**
* A file object used to represent source coming from a string.
*/
private static class JavaSourceFromString extends SimpleJavaFileObject {
/**
* The source code of this "file".
*/
final String code;
/**
* Constructs a new JavaSourceFromString.
*
* @param name the NAME of the compilation unit represented by this file
* object
* @param code the source code for the compilation unit represented by
* this file object
*/
JavaSourceFromString(String name, String code) {
super(uriFromString("mfm:///" name.replace('.', '/') Kind.SOURCE.extension), Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
}