惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
Cloudbric
Cloudbric
P
Palo Alto Networks Blog
T
Threatpost
T
Tor Project blog
T
Tenable Blog
AWS News Blog
AWS News Blog
Project Zero
Project Zero
L
LangChain Blog
Cyberwarzone
Cyberwarzone
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
C
CERT Recently Published Vulnerability Notes
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Security Latest
Security Latest
云风的 BLOG
云风的 BLOG
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Proofpoint News Feed
A
Arctic Wolf
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google DeepMind News
Google DeepMind News
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
MongoDB | Blog
MongoDB | Blog
aimingoo的专栏
aimingoo的专栏
K
Kaspersky official blog
Jina AI
Jina AI
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
D
DataBreaches.Net
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Secure Thoughts
TaoSecurity Blog
TaoSecurity Blog
P
Privacy & Cybersecurity Law Blog
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
IT之家
IT之家
Forbes - Security
Forbes - Security
The Hacker News
The Hacker News
Last Week in AI
Last Week in AI
T
Threat Research - Cisco Blogs
Y
Y Combinator Blog

博客园 - Rookie.Zhang

搬家到CSDN通知 百度网盘推荐 推荐使用金山快盘,15G超大免费空间 Jboss的SSL的配置【转】 VC7(VS2003.net)中开发ActiveX控件相关【转】 腾讯:将收购Riot Games多数股权 谷歌换帅 佩奇将接任CEO[转] FreeMarker笔记 2011年熱門電子產品搶先看 【转】dom4j通过xpath查询xml - Rookie.Zhang - 博客园 【转】 利用 Java dump 进行 JVM 故障诊断 【转】java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结 桌面拖动的图标不消失如何处理? 蘋果將推出速度更快的新操作系統 Flex开源了【保留】 IE7、8不能使用Oracle EBS的问题解决 蘋果iPhone 3G S更出色 关于Java压缩时中文文件名处理 今天和大家分享一些有关高级Oracle数据库(4)收藏
【转】关于eclipse和javac编译结果不一致的问题的分析与解决
Rookie.Zhang · 2010-05-24 · via 博客园 - Rookie.Zhang

问题:

下面一个简单的类:

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环境的编译器我没有独立验证过)