您的位置:首页 > 编程语言 > Java开发

【转】关于eclipse和javac编译结果不一致的问题的分析与解决

2010-05-24 14:50 627 查看
问题:

下面一个简单的类:

public class MyTest {

private static String className = String.class.getName(); //红色部分是下面问题的关键

public static void main(String[] args){

System.out.println(className);

}

}

经eclipse3.1.1编译后(指定类兼容性版本为1.4),再反编译的结果是:

public class MyTest

{

public MyTest()

{

}

public static void main(String args[])

{

System.out.println(className);

}

private static String className;

static

{

className = java.lang.String.class.getName();

}

}

而经过sun javac(或者ant, antx)编译后(JDK版本1.4,或者JDK1.5,但是编译结果指定版本为1.4),再反编译的结果是:

public class MyTest

{

public MyTest()

{

}

public static void main(String args[])

{

System.out.println(className);

}

static Class _mthclass$(String x0)

{

return Class.forName(x0);

ClassNotFoundException x1;

x1;

throw (new NoClassDefFoundError()).initCause(x1);

}

private static String className;

static

{

className = (java.lang.String.class).getName();

}

}

也就是说sun javac编译出来的结果里面多了一个_mthclass$方法,这个通常不会有什么问题,不过在使用hot swap技术(例如Antx eclipse plugin中的快速部署插件利用hot swap来实现类的热替换,或者某些类序列化的地方,这个就成为问题了。

用_mthclass$在google上搜一把,结果不多,比较有价值的是这一篇:http://coding.derkeiler.com/Archive/Java/comp.lang.java.softwaretools/2004-01/0138.html

按照这个说法,这个问题是由于Sun本身没有遵循规范,而eclipse compiler遵循规范导致的,而且eclipse compiler是没有办法替换的。

尝试将JDK版本换成1.5,sun javac生成出来的_mthclass$是不见了,不过,这回奇怪的是eclipse的编译结果中多了一个成员变量class$0,

下面是经eclipse3.1.1编译后(指定类兼容性版本为5.0),再反编译的结果:

public class MyTest

{

public MyTest()

{

}

public static void main(String args[])

{

System.out.println(className);

}

private static String className = java/lang/String.getName();

static Class class$0;

}

而经过sun javac(或者ant, antx)编译后(JDK版本1.5),再反编译的结果是:

public class MyTest

{

public MyTest()

{

}

public static void main(String args[])

{

System.out.println(className);

}

private static String className = java/lang/String.getName();

}

再在goole上搜了一把,发现了Eclipse3.2有两个比较重要的特征:

1.与javac的兼容性更好。

2.提供了单独的编译器,可以在eclipse外部使用,包括ant中使用。

于是下载eclipse3.2版本,首先验证一下其与sun javac的兼容性如何,

使用JDK1.4版本的时候,还是老样子,sun javac编译出来的_mthclass$方法在eclipse3.2的编译结果中还是不存在,所以还是不兼容的。

不过使用JDK1.5版本的时候,这会eclipse 3.2的编译结果总算和sun javac一致了。

虽然,用JDK1.5加上eclipse 3.2已经保证了这个类在两种编译器下的兼容性,不过总觉得不踏实:

1.谁知道这两个编译器还有没有其它不兼容的地方呢?

2.版本要求太严格,很多由于各种原因没有使用这些版本的很麻烦。

因此,还是从根本上解决这个问题比较合适:根本上解决最好就是不要使用两种不同的编译器,而使用同一种。

由于eclipse环境下的编译器是不可替换的,所以企图都使用sun javac的方式不太可行,那么统一使用eclipse自带的编译器如何呢?

刚才提到的eclipse3.2的第二个比较重要的特性就派上用场了。

独立的eclipse编译器(1M大小而已)可以在如下地址下载:http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.2-200606291905/ecj.jar

这个独立的编译器在antx下的使用也很简单:(关于该编译器的独立使用或者ant下面的使用可以参看this help section: JDT Plug-in Developer Guide>Programmer's Guide>JDT Core>Compiling Java code)

1.将下载下来的编译器放在ANTX_HOME/lib目录下面。

2.在总控项目文件的project.xml增加这么一行即可:<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

这样就保证了通过antx打包的类也是用eclipse的编译器编译出来的,当然就不应该存在类不兼容的情况了。

实际上,eclipse3.1.1版本也已经提供了独立的eclipse编译器,不过当时并没有单独提供独立的包下载,如果希望使用3.1.1版本的eclipse编译器,可以使用org.eclipse.jdt.core_3.1.1.jar以及其中包含的jdtCompilerAdapter.jar。(eclipse3.1.1环境的编译器我没有独立验证过)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐