`
huangxx
  • 浏览: 315826 次
  • 来自: ...
社区版块
存档分类
最新评论

java 编译非文本形式的文件

阅读更多

http://www.ibm.com/developerworks/cn/java/j-lo-jse64/

 

编译非文本形式的文件

JDK 6 的编译器 API 的另外一个强大之处在于,它可以编译的源文件的形式并不局限于文本文件。JavaCompiler 类依靠文件管理服务可以编译多种形式的源文件。比如直接由内存中的字符串构造的文件,或者是从数据库中取出的文件。这种服务是由 JavaFileManager 类提供的。通常的编译过程分为以下几个步骤:

  1. 解析 javac 的参数;
  2. 在 source path 和/或 CLASSPATH 中查找源文件或者 jar 包;
  3. 处理输入,输出文件;

在这个过程中,JavaFileManager 类可以起到创建输出文件,读入并缓存输出文件的作用。由于它可以读入并缓存输入文件,这就使得读入各种形式的输入文件成为可能。JDK 提供的命令行工具,处理机制也大致相似,在未来的版本中,其它的工具处理各种形式的源文件也成为可能。为此,新的 JDK 定义了 javax.tools.FileObjectjavax.tools.JavaFileObject 接口。任何类,只要实现了这个接口,就可以被 JavaFileManager 识别。

如果要使用 JavaFileManager,就必须构造 CompilationTask。JDK 6 提供了 JavaCompiler.CompilationTask 类来封装一个编译操作。这个类可以通过:

JavaCompiler.getTask (
    Writer out, 
    JavaFileManager fileManager,
    DiagnosticListener<? super JavaFileObject> diagnosticListener,
    Iterable<String> options,
    Iterable<String> classes,
    Iterable<? extends JavaFileObject> compilationUnits
)

方法得到。关于每个参数的含义,请参见 JDK 文档。传递不同的参数,会得到不同的 CompilationTask。通过构造这个类,一个编译过程可以被分成多步。进一步,CompilationTask 提供了 setProcessors(Iterable<? extends Processor>processors) 方法,用户可以制定处理 annotation 的处理器。图 1 展示了通过 CompilationTask 进行编译的过程:


图 1. 使用 CompilationTask 进行编译
使用 CompilationTask 进行编译

下面的例子通过构造 CompilationTask 分多步编译一组 Java 源文件。


清单 2. 构造 CompilationTask 进行编译

01 package math;

02 public class Calculator {
03     public int multiply(int multiplicand, int multiplier) {
04         return multiplicand * multiplier;
05     }
06 }

07 package compile;
08 import javax.tools.*;
09 import java.io.FileOutputStream;
10 import java.util.Arrays;
11 public class Compiler {
12   public static void main(String[] args) throws Exception{
13     String fullQuanlifiedFileName = "math" + java.io.File.separator +"Calculator.java";
14     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
15     StandardJavaFileManager fileManager  =
           compiler.getStandardFileManager(null, null, null);

16     Iterable<? extends JavaFileObject> files =
             fileManager.getJavaFileObjectsFromStrings(
             Arrays.asList(fullQuanlifiedFileName));
17     JavaCompiler.CompilationTask task = compiler.getTask(
             null, fileManager, null, null, null, files);

18     Boolean result = task.call();
19     if( result == true ) {
20       System.out.println("Succeeded");
21     }
22   }
23 }
   

以上是第一步,通过构造一个 CompilationTask 编译了一个 Java 文件。14-17 行实现了主要逻辑。第 14 行,首先取得一个编译器对象。由于仅仅需要编译普通文件,因此第 15 行中通过编译器对象取得了一个标准文件管理器。16 行,将需要编译的文件构造成了一个 Iterable 对象。最后将文件管理器和 Iterable 对象传递给 JavaCompilergetTask 方法,取得了 JavaCompiler.CompilationTask 对象。

接下来第二步,开发者希望生成 Calculator 的一个测试类,而不是手工编写。使用 compiler API,可以将内存中的一段字符串,编译成一个 CLASS 文件。


清单 3. 定制 JavaFileObject 对象

01 package math;
02 import java.net.URI;
03 public class StringObject extends SimpleJavaFileObject{
04     private String contents = null;
05     public StringObject(String className, String contents) throws Exception{
06         super(new URI(className), Kind.SOURCE);
07         this.contents = contents;
08     }

09     public CharSequence getCharContent(boolean ignoreEncodingErrors) 
             throws IOException {
10         return contents;
11     }
12 }
   

SimpleJavaFileObjectJavaFileObject 的子类,它提供了默认的实现。继承 SimpleJavaObject 之后,只需要实现 getCharContent 方法。如 清单 3 中的 9-11 行所示。接下来,在内存中构造 Calculator 的测试类 CalculatorTest,并将代表该类的字符串放置到 StringObject 中,传递给 JavaCompilergetTask 方法。清单 4 展现了这些步骤。


清单 4. 编译非文本形式的源文件

01 package math;
02 import javax.tools.*;
03 import java.io.FileOutputStream;
04 import java.util.Arrays;
05 public class AdvancedCompiler {
06   public static void main(String[] args) throws Exception{

07     // Steps used to compile Calculator
08     // Steps used to compile StringObject

09     // construct CalculatorTest in memory
10     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
11     StandardJavaFileManager fileManager  =
           compiler.getStandardFileManager(null, null, null);
12         JavaFileObject file = constructTestor();
13         Iterable<? extends JavaFileObject> files = Arrays.asList(file);
14         JavaCompiler.CompilationTask task = compiler.getTask (
                 null, fileManager, null, null, null, files);

15         Boolean result = task.call();
16         if( result == true ) {
17           System.out.println("Succeeded");
18         }
19   }

20   private static SimpleJavaFileObject constructTestor() {
21     StringBuilder contents = new StringBuilder(
           "package math;" +
           "class CalculatorTest {\n" +
      	   "  public void testMultiply() {\n" +
		   "    Calculator c = new Calculator();\n" +
		   "    System.out.println(c.multiply(2, 4));\n" +
		   "  }\n" +
		   "  public static void main(String[] args) {\n" +
		   "    CalculatorTest ct = new CalculatorTest();\n" +
		   "    ct.testMultiply();\n" +
		   "  }\n" +
		   "}\n");
22      StringObject so = null;
23      try {
24        so = new StringObject("math.CalculatorTest", contents.toString());
25      } catch(Exception exception) {
26        exception.printStackTrace();
27      }
28      return so;
29    }
30 }

实现逻辑和 清单 2 相似。不同的是在 20-30 行,程序在内存中构造了 CalculatorTest 类,并且通过 StringObject 的构造函数,将内存中的字符串,转换成了 JavaFileObject 对象。

分享到:
评论
2 楼 郭玉成 2013-04-23  
你好, 我已经找到原因了!
1 楼 郭玉成 2013-04-23  
你好! 我在编译一个项目的时候,我是逐个文件编译的,但是当有的类导入其他包中的类而且被导入包中的类还没用编译,这样就会造成:“找不到符号
符号: 类 JavaCompilerWorker
位置: 软件包 parser
import parser.JavaCompilerWorker;”
这个错误! 有什么办法能更好的动态编译吗?

相关推荐

    DJ Java Decompiler 3.12.12.96 老朽痴拙汉化版(JAVA反编译)

    你可以反编译class文件并且可以保存为文本文件或其它格式。 DJ非常容易使用。选择你想反编译的class文件(路径勿含中文),或者只是双击想反编译的class文件(建立关联)。 DJ同时支持在界面上拖拽的方式来反编译class...

    java反编译工具 Java Decompiler

    DJ Java Decompiler是一款强大易用的java反编译器,使用DJ Java Decompiler你可以反编译class文件并且可以保存为文本文件或其它格式,它可以从已经编译的二进制class文件重新创建最初的源代码(比如说Java applets)。

    DJ Java Decompiler2.9.9.57老朽痴拙汉化版(JAVA反编译器)

    使用DJ Java Decompiler你可以反编译class文件并且可以保存为文本文件或其它格式,它很容易使用。DJ Java Decompiler是Windows 2000,Windows XP,Windows 2003,Windows Vista,Windows 7环境下的反编译器,它可以...

    java android 反编译工具大全

    作用:将apk反编译成java源码(classes.dex转化成jar文件) jd-gui 作用:查看APK中classes.dex转化成出的jar文件,即源码文件、 smali-1.2.6.jar 用途:.smali文件 转成 classes.dex文件 说明:.smali文件,...

    DJ Java Decompiler 3.12.12.100(破解)

    使用DJ Java Decompiler你可以反编译class文件并且可以保存为文本文件或其它格式,它很容易使用。DJ Java Decompiler是Windows 2000,Windows XP,Windows 2003,Windows Vista,Windows 7环境下的反编译器,它可以...

    JAVA上百实例源码以及开源项目

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码,...

    java源码包---java 源码 大量 实例

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码,...

    DJ Java Decompiler 3.12.12.96汉化版图样

    使用DJ Java Decompiler你可以反编译class文件并且可以保存为文本文件或其它格式,它很容易使用。 可用於 2000,XP,2003,Vista,Windows 7环境下的反编译器, DJ可以从已经编译的二进制class文件重新创建最初的源...

    java源码包4

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码...

    java源码包3

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码...

    JAVA上百实例源码以及开源项目源代码

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码,...

    java源码包2

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码...

    文件/文件夹操作(读取,删除,添加)

    6、 编写一个Java应用程序,文件名为Folder.java,编译后执行结果如下图所示,实现指定文件夹下目录和文件的文本形式的树状结构显示。要求: 1. 输入: java Folder,显示当前文件夹下的目录和文件的文本形式树状...

    linux平台使用JAVA提取各种文件(office, pdf, eml, rtf, html, wps)内容文本

    按照压缩包中的使用示例编译即可 ...K: 邮件格式文件 ".eml", 注:默认提取前5个附件 L: 部分思维导图格式文件 ".emmx", "xmind", "gmind" M:UTF8编码, Unicode编码, Ansi编码的文本文件 O: 压缩文件 ".zip

    java做的文件分割器小程序

    在山西太原做过的,加密算法不太完美,可以改进,源代码看不到,但是我这有个小小反编译,想看源代码就用它打开看看吧···~

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码,文件操作,压缩包查看 Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码...

    Java开发技术大全(500个源代码).

    HelloNative.java 准备调用C函数的java文件 HelloNative.lib 用VC编译生成的静态库文件 HelloNative.obj 用VB编译生成的目标文件 HelloNativeTest.java 测试本地化是否成功的类文件 instanceVar.java 定义一个...

    Java核心技术II(第8版)

    1.2.3 以文本格式存储对象 1.2.4 字符集 1.3 读入和写出二进制数据 1.3.1 随机访问文件 1.4 ZIP文档 1.5 对象流与序列化 1.5.1 理解对象序列化的文件格式 1.5.2 修改缺省的序列化机制 1.5.3 序列化单例和类型安全的...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码,文件操作,压缩包查看 Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码...

Global site tag (gtag.js) - Google Analytics