java 类加载 编译_java类加载器和运行时编译

本文探讨了在Java 6 Tomcat 6环境中,如何在运行时动态生成Java代码并编译时遇到的问题。作者遇到的挑战是代码依赖已加载的jar包,导致编译错误。文章详细展示了如何使用内存类加载器尝试解决,并解释了为何编译失败可能的原因。
摘要由CSDN通过智能技术生成

尽管警告会放弃我目前的行动方案,但我目前看不到更好的方法来解决我的问题.我必须在运行时生成

Java代码,然后编译它,加载它并引用它.

问题是生成的代码导入已经由系统类加载器加载的代码(我想) – 也就是代码存在于我的类路径中的一个jar中.

(我在Java 6上运行Tomcat 6 Web容器.)您可能会问自己为什么这是一个问题 – 我确定不知道 – 但事实是我遇到了编译错误:

/W:/…/parser/v0.5/AssignELParser.java:6:

package com.xxx.yyy.zzz.configuration

does not exist

下面是一些关于互联网的例子,我定义了以下类:

class MemoryClassLoader extends ChainedAction {

private static final Logger LOG = Logger.getLogger(MemoryClassLoader.class);

private LoaderImpl impl;

private class LoaderImpl extends ClassLoader {

// The compiler tool

private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

// Compiler options

private final Iterable options = Arrays.asList("-verbose");

// DiagnosticCollector, for collecting compilation problems

private final DiagnosticCollector diagnostics = new DiagnosticCollector();

// Our FileManager

private final MemoryFileManager manager = new MemoryFileManager(this.compiler);

public LoaderImpl(File sourceDirectory) {

List list = new ArrayList();

File[] files = sourceDirectory.listFiles(new FilenameFilter() {

@Override

public boolean accept(File dir, String name) {

return name.endsWith(Kind.SOURCE.extension);

}

});

for (File file : files) {

list.add(new Source(file));

}

CompilationTask task = compiler.getTask(null, manager, diagnostics, options, null, list);

Boolean compilationSuccessful = task.call();

LOG.info("Compilation has " + ((compilationSuccessful) ? "concluded successfully" : "failed"));

// report on all errors to screen

for (Diagnostic extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {

LOG.warn(diagnostic.getMessage(null));

}

}

@Override

protected Class> findClass(String name) throws ClassNotFoundException {

synchronized (this.manager) {

Output output = manager.map.remove(name);

if (output != null) {

byte[] array = output.toByteArray();

return defineClass(name, array, 0, array.length);

}

}

return super.findClass(name);

}

}

@Override

protected void run() {

impl = new LoaderImpl(new File(/* Some directory path */));

}

}

class MemoryFileManager extends ForwardingJavaFileManager {

final Map map = new HashMap();

MemoryFileManager(JavaCompiler compiler) {

super(compiler.getStandardFileManager(null, null, null));

}

@Override

public Output getJavaFileForOutput(Location location, String name, Kind kind, FileObject source) {

Output output = new Output(name, kind);

map.put(name, output);

return output;

}

}

class Output extends SimpleJavaFileObject {

private final ByteArrayOutputStream baos = new ByteArrayOutputStream();

Output(String name, Kind kind) {

super(URI.create("memo:///" + name.replace('.', '/') + kind.extension), kind);

}

byte[] toByteArray() {

return this.baos.toByteArray();

}

@Override

public ByteArrayOutputStream openOutputStream() {

return this.baos;

}

}

class Source extends SimpleJavaFileObject {

public Source(File file) {

super(file.toURI(), Kind.SOURCE);

}

@Override

public CharSequence getCharContent(boolean ignoreEncodingErrors) {

StringBuilder sb = new StringBuilder("");

try {

File file = new File(uri);

FileReader fr = new FileReader(file);

BufferedReader br = new BufferedReader(fr);

sb = new StringBuilder((int) file.length());

String line = "";

while ((line = br.readLine()) != null) {

sb.append(line);

sb.append("\n");

}

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return sb.toString();

}

}

看来内部类LoaderImpl通过扩展ClassLoader类并且不调用显式超级构造函数,应该引用系统类加载器作为其父类加载器.

如果它这样做那么为什么我得到“运行时”编译错误 – 上面?为什么找不到导入类的代码?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值