我想在weblogic 10.3服务器中在运行时编译和加载新类。类加载似乎有点简单:
class ClassFileManager
extends ForwardingJavaFileManager<StandardJavaFileManager> {
Map<String, JavaClassObject> classes = new HashMap<String, JavaClassObject>();
public ClassFileManager(StandardJavaFileManager standardManager) {
super(standardManager);
}
@Override
public ClassLoader getClassLoader(Location location) {
return new SecureClassLoader(currentThread().getContextClassLoader()) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] b = classes.get(name).getBytes();
return super.defineClass(name, b, 0, b.length);
}
};
}
@Override
public JavaFileObject getJavaFileForOutput(
Location location, String className, Kind kind, FileObject sibling)
throws IOException {
JavaClassObject result = new JavaClassObject(className, kind);
classes.put(className, result);
return result;
}
}
执行类加载的最简单方法似乎是初始化SecureClassLoader
并让它使用contextClassLoader
作为父级。
但是当为JDK的运行时编译器设置-classpath
选项时,我似乎无法找到&#34;上下文类路径&#34;以字符串形式。以下是一个有效的工作&#34;足够好&#34; :
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
ClassFileManager fileManager =
new ClassFileManager(compiler.getStandardFileManager(null, null, null));
List<String> options = new ArrayList<String>();
options.add("-classpath");
options.add(System.getProperty("java.class.path") + ";" +
getClass().getProtectionDomain()
.getCodeSource().getLocation()
.toURI().toString()
.replace("file:/", "").replace("/", "\\"));
但它没有生成上下文类加载器的完整类路径。我怎么能可靠地做到这一点?我可以吗?
答案 0 :(得分:2)
WebLogic 10.3.6具有相当复杂的ClassLoader
实现。幸运的是,用于Web应用程序的类加载器公开了getClassPath
方法。
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String classPath = ((weblogic.utils.classloaders.GenericClassLoader)cl).getClassPath();
// Once we have a classpath it's standard procedure
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager sfm = compiler.getStandardFileManager(null, null, null);
List<String> optionList = new ArrayList<String>();
optionList.addAll(Arrays.asList("-classpath", classPath));
compiler.getTask(null, sfm, null, optionList, null, sources).call();
答案 1 :(得分:1)
也许这可以帮到你。它适用于我在WebLogic上的项目。
String getClassPath() {
final String BASE_PATH = "<your_project_folder_name>";
String path = "";
String classPathProperty = System.getProperty("java.class.path");
if (classPathProperty != null) {
path = classPathProperty + File.pathSeparator;
}
URL classLocation = this.getClass().getProtectionDomain().getCodeSource().getLocation();
URL classesLocation = this.getClass().getClassLoader().getResource("/");
if (classesLocation == null) {
path = path + classLocation.getPath();
}
else {
String classesLocationPath = classesLocation.getPath();
String libsLocationPath = classesLocationPath + "../lib";
File libsLocation = new File(libsLocationPath);
if (libsLocation.exists() == false) {
libsLocationPath = URLDecoder.decode(classesLocationPath + "../" + BASE_PATH + "/WEB-INF/lib/");
libsLocation = new File(libsLocationPath);
}
File[] filesInLibraryPath = libsLocation.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
if (filesInLibraryPath != null) {
for (File libraryFile : filesInLibraryPath) {
libsLocationPath += File.pathSeparator + URLDecoder.decode(libraryFile.getAbsolutePath());
}
}
path = path +
classLocation.getPath() + File.pathSeparator +
classesLocationPath + File.pathSeparator +
libsLocationPath;
path = URLDecoder.decode(path);
}
return path;
}
答案 2 :(得分:1)
Tomcat interrogates context URLClassLoader使用的开源Jasper JSP编译器,用于生成传递给编译器的类路径字符串。
如果WebLogic没有公开getURLs
方法,则另一种方法是使用JavaFileManager
的自定义实现,该实现使用上下文类加载器getResource()
方法来获取类文件。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaFileManager customFileManager = ...
compiler.getTask(null, customFileManager, null, null, null, sources).call();
有一个完整的示例here。
答案 3 :(得分:1)
我建议您让自定义JavaFileManager
了解上下文类加载器,并将其指定为JavaCompiler.getTask
的参数,与@ anttix的想法一致。
有关详细信息和示例实现(包括解释)(此处重复过于冗长)请参阅博文Using built-in JavaCompiler with a custom classloader。
答案 4 :(得分:0)
由于&#34; WebApplicationClassLoader&#34; 是一种&#34; URLClassLoader&#34; ,您可以使用此代码段。
ClassLoader classLoader = getClass().getClassLoader();
System.out.println("ClassLoader: " + classLoader);
URLClassLoader urlClassLoader = (URLClassLoader)classLoader;
URL[] urls = urlClassLoader.getURLs();
for (URL u : urls) {
System.out.println("url: " + u);
}
此代码列出了类路径中的所有jar和目录。