javac编译错误: 程序包 com.sun.xxx 不存在
运行环境
-
Java版本:java version “1.8.0_281” 操作系统:Windows 10
一、问题描述
com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;
-
单独写一个测试类TestMimeUtility.java研究下…
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility; public class TestMimeUtility { public static void main(String[] args) { System.out.println("TestMimeUtility"); System.out.println(MimeUtility.ALL); } }
-
使用javac编译直接报错
二、探究过程
-
首先,该类属于基础类库 rt.jar 包下的类 这时候用 -verbose 看看类文件搜索路径是不是出了问题 可以得出类文件搜索路径已经包含了rt.jar(题外话:网上说CLASSPATH环境变量添加rt.jar其实多此一举了,至少在Java8是不用加的,之前版本没试过),但是还意外看到这么个输出信息: 也就是说javac编译时还和%JAVA_HOME%libct.sym这个文件有关系,于是我用相应解压缩软件打开,发现并没有com.sun.xml包,所以说未找到这个类的原因来自于这里,问题定位到ct.sym文件
三、原因
于是我网上找到相应的issue查了下原因,大致如下:
-
在JDK6以及以后的版本【版本我没有去确认】,JDK在目录下新增了一个链接文件${JDK_HOME}/lib/ct.sym。在使用javac命令进行编译代码时,默认使用该文件进行编译时class类的检查和链接,而不是直接使用%JAVA_HOME%/jre/lib/rt.jar 该文件保存了JDK建议使用的类描述信息。com.sun.*包和sun.*包,以及新的jdk.*都不是Open的API,这些类的接口可能在之后的版本变动,也不保证平台移植性。【编译时会有警告或者是找不到类】 事实上,JDK提供的Public API,仅有三个包:java.*、javax.*、org.*。它们是官方支持的公共接口
四、解决方式
1. 如果是自己写的类依赖了这些类,建议进行重写替换,避免后续系统升级给其他维护人员带来麻烦! 2. 如果一定要编译,可以在编译时添加忽略链接文件选项:-XDignore.symbol.file
-
javac
javac -XDignore.symbol.file TestMimeUtility.java
-
Maven
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <compilerArgs> <arg>-XDignore.symbol.file</arg> </compilerArgs> <fork>true</fork> </configuration> </plugin> </plugins> </build>
-
Ant
<target name="compile"> <javac destdir="${build.dir}" encoding="UTF-8" source="1.8" target="1.8" > <src path="${src.dir}"/> <compilerarg value="-XDignore.symbol.file"/> <classpath refid="classpath" /> </javac> </target>
3.类文件搜索路径添加另一个rt.jar的路径
网上好像挺多人用这个方式的,直接把rt.jar替换掉,但其实知道怎么回事后还不如直接使用 -XDignore.symbol.file 选项呢… 另外要注意的是另一个rt.jar路径不能是%JAVA_HOME%jrelib t.jar,类搜索路径已经有了该路径并且已经 被列入黑名单了,加上去和没加一样
javac -classpath YOUR_PATH t.jar TestMimeUtility.java
-
执行结果:
五、总结
-
建议不要使用 "sun.*"或"com.sun."包中的类,避免在项目迁移出现问题,因为它们不是Java API中的一部分 IDEA,Eclipse工具竟然可以正确!正常!编译这些代码,好歹给个警告啊,就这么纵容吗~