liumang20091 2009-04-15 12:25
浏览 208

JAVA6动态编译的问题

在使用JAVA6动态编译时遇到的一个问题,动态编译方法已经写就。通过main方法调用的动态编译时,编译通过,并可以使用编译生成的类。但是,在Tomcat下调用同样的方法进行动态编译时,编译无法通过。其原因是找不到对应的包。因为动态生成的类中import了其他的一些类。我猜是tomcat的某些加载机制影响了动态编译过程,导致动态编译找不引用的类。请问各位,是否有方法解决?
[b]问题补充:[/b]
补充代码:
参数 files是一个JavaFile类型的数组,其中包含了Java类的源文件
[code="java"]

public static Class[] complie(JavaFile[] files) throws Exception
{
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    //ClassLoader clsLoader=ToolProvider.getSystemToolClassLoader();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();


    MemoryFileManager filemanage = new MemoryFileManager(compiler
            .getStandardFileManager(diagnostics, null, null));
    //MemoryFileManager filemanage = new MemoryFileManager(compiler
            //.getStandardFileManager(diagnostics, null, null));
    //Log.info("Location\t"+filemanage.)
    ArrayList<JavaFileObject> clsFiles=new ArrayList<JavaFileObject>();

    for(JavaFile file:files)
    {
        JavaFileObject clsfile = MemoryFileManager.makeSource(file
                .getFileName(), file.toString());
        clsFiles.add(clsfile);
        Log.info("compile:"+file.getFileName()+"\t"+clsfile.getName()+"\t"+clsfile.getKind()+"\t"+clsfile.toUri());
    } 
    Iterable<? extends JavaFileObject> compilationUnits=clsFiles;

    JavaCompiler.CompilationTask task = compiler.getTask(null, filemanage,
            diagnostics, null, options.getClassNames(), compilationUnits);

    boolean success=false;
    try
    {
        success = task.call();
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    Class[] clazz=new Class[files.length];
    if(success)
    {
        for(int i=0;i<clazz.length;i++)
        {
            clazz[i] = filemanage.getClassLoader(null).loadClass(files[i].getFileName());
        }
    } 
    else
    {
        for (Diagnostic diagnostic : diagnostics.getDiagnostics())
            System.out.printf(
            "Code: %s%n" +
            "Kind: %s%n" +
            "Position: %s%n" +
            "Start Position: %s%n" +
            "End Position: %s%n" +
            "Source: %s%n" +
            "Message: %s%n",
            diagnostic.getCode(), diagnostic.getKind(),
            diagnostic.getPosition(), diagnostic.getStartPosition(),
            diagnostic.getEndPosition(), diagnostic.getSource(),
            diagnostic.getMessage(null));

    }
    filemanage.close();
    return clazz;
}

[/code]
[b]问题补充:[/b]

TOMCAT下的编译诊断信息:
[code="java"]
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 0
Start Position: 0
End Position: 0
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:1: 软件包 com.youngor.dboperator 不存在
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 104
Start Position: 78
End Position: 112
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:4: 软件包 com.youngor.webcore.entity 不存在
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 146
Start Position: 124
End Position: 156
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:6: 软件包 com.youngor.dboperator 不存在
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 202
Start Position: 180
End Position: 212
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:9: 软件包 com.youngor.dboperator 不存在
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 239
Start Position: 213
End Position: 251
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:9: 软件包 com.youngor.webcore.entity 不存在
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 0
Start Position: 0
End Position: 0
Source: mfm:///RuntimeEntitySysPosition.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysPosition.java:1: 软件包 com.youngor.dboperator 不存在
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 108
Start Position: 82
End Position: 120
Source: mfm:///RuntimeEntitySysPosition.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysPosition.java:4: 软件包 com.youngor.webcore.entity 不存在
Code: compiler.err.cant.resolve.location
Kind: ERROR
Position: 328
Start Position: 328
End Position: 337
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:14: 找不到符号
符号: 类 EntitySet
位置: 类 RuntimeEntitySysUser
Code: compiler.err.cant.resolve.location
Kind: ERROR
Position: 383
Start Position: 383
End Position: 392
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:14: 找不到符号
符号: 变量 DefaultDB
位置: 类 RuntimeEntitySysUser
Code: compiler.err.doesnt.exist
Kind: ERROR
Position: 436
Start Position: 410
End Position: 448
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:14: 软件包 com.youngor.webcore.entity 不存在
Code: compiler.err.cant.resolve.location
Kind: ERROR
Position: 619
Start Position: 619
End Position: -1
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:16: 找不到符号
符号: 变量 super
位置: 类 RuntimeEntitySysUser
Code: compiler.err.cant.resolve.location
Kind: ERROR
Position: 667
Start Position: 667
End Position: -1
Source: mfm:///RuntimeEntitySysUser.java from JavaSourceFromString
Message: mfm:///RuntimeEntitySysUser.java:18: 找不到符号
符号: 变量 super
位置: 类 RuntimeEntitySysUser
[/code]

Tomcat输出的异常信息:
[code="java"]
java.lang.NullPointerException
at com.youngor.dboperator.EntityUtil.getInstance(EntityUtil.java:36)
at com.youngor.dboperator.Entity.getInstance(Entity.java:103)
at com.youngor.dboperator.SQLServer2000Adaptor.getEntitySetBySQL(SQLServer2000Adaptor.java:283)
at com.youngor.dboperator.SQLServer2000Adaptor.getEntitySet(SQLServer2000Adaptor.java:220)
at com.youngor.dboperator.InnerDBOperator.getEntitySet(InnerDBOperator.java:451)
at com.youngor.dboperator.DBOperator.getEntitySet(DBOperator.java:350)
at com.youngor.dboperator.DefaultDB.getEntitySet(DefaultDB.java:147)
at com.youngor.dboperator.DefaultDB.getEntitySet(DefaultDB.java:213)
at com.youngor.webcore.entity.SysUser.getEntitySet(SysUser.java:501)
at com.youngor.webcore.entity.SysUser.doTest(SysUser.java:610)
at org.apache.jsp.login_jsp._jspService(login_jsp.java:66)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:857)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:565)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1509)
at java.lang.Thread.run(Thread.java:619)
java.lang.NullPointerException
at com.youngor.dboperator.SQLServer2000Adaptor.getEntitySetBySQL(SQLServer2000Adaptor.java:284)
at com.youngor.dboperator.SQLServer2000Adaptor.getEntitySet(SQLServer2000Adaptor.java:220)
at com.youngor.dboperator.InnerDBOperator.getEntitySet(InnerDBOperator.java:451)
at com.youngor.dboperator.DBOperator.getEntitySet(DBOperator.java:350)
at com.youngor.dboperator.DefaultDB.getEntitySet(DefaultDB.java:147)
at com.youngor.dboperator.DefaultDB.getEntitySet(DefaultDB.java:213)
at com.youngor.webcore.entity.SysUser.getEntitySet(SysUser.java:501)
at com.youngor.webcore.entity.SysUser.doTest(SysUser.java:610)
at org.apache.jsp.login_jsp._jspService(login_jsp.java:66)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:857)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:565)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1509)
at java.lang.Thread.run(Thread.java:619)

[/code]
[b]问题补充:[/b]
public static Class[] complie(JavaFile[] files) throws Exception 这个方法是用main(String[] args)方法测试成功。放到JSP页面中调用输错。错误信息已经在上面给出。
[b]问题补充:[/b]
把com.youngor.*之类的类文件,放到tomcat下的common或shared下对应的classes或lib下,应该就不会报这个异常 或许可以解决问题。但是这不太符合Web应用部署的常规做法,不知“lovewhzlq”是否还有其他可行方法,不吝赐教。
[b]问题补充:[/b]
问题基本解决,需要为编译过程指定编译的类路径;
[code="java"]
C:\myproject>javac -help
用法:javac <选项> <源文件>
其中,可能的选项包括:
-g 生成所有调试信息
-g:none 不生成任何调试信息
-g:{lines,vars,source} 只生成某些调试信息
-nowarn 不生成任何警告
-verbose 输出有关编译器正在执行的操作的消息
-deprecation 输出使用已过时的 API 的源位置
-classpath <路径> 指定查找用户类文件的位置
-cp <路径> 指定查找用户类文件的位置
-sourcepath <路径> 指定查找输入源文件的位置
-bootclasspath <路径> 覆盖引导类文件的位置
-extdirs <目录> 覆盖安装的扩展目录的位置
-endorseddirs <目录> 覆盖签名的标准路径的位置
-d <目录> 指定存放生成的类文件的位置
-encoding <编码> 指定源文件使用的字符编码
-source <版本> 提供与指定版本的源兼容性
-target <版本> 生成特定 VM 版本的类文件
-version 版本信息
-help 输出标准选项的提要
-X 输出非标准选项的提要
-J<标志> 直接将 <标志> 传递给运行时系统
[/code]

修改部分代码如下:
[code="java"]
String cp=PathTool.get(AdvancedCompilerAPIDemo.class);
Log.info(cp);
int i=cp.indexOf("/WEB-INF/classes/");
cp=cp.substring(0, i+17);
Log.info(cp);
Iterable options = Arrays.asList("-d", cp,"-cp",cp); // 编译选项,将编译产生的类文件放在当前目录下
CompilationTask task = compiler.getTask(null, fileManager,
diagnostics, options, null, sourcefiles);
[/code]
这里找到了WEb应用的classes目录并设置为编译输出目录和类路径。编译通过并可以使用了。

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
    • ¥15 C#调用python代码(python带有库)
    • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
    • ¥15 活动选择题。最多可以参加几个项目?
    • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
    • ¥15 vs2019中数据导出问题
    • ¥20 云服务Linux系统TCP-MSS值修改?
    • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
    • ¥20 怎么在stm32门禁成品上增加查询记录功能
    • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面