最近在使用Ant自動化編譯打包一個Java項目,執行時總是報有class找不到:
[javac] Compiling 46 source files to /A/B/C/D/build/staging/bin
[javac] .../ChangePassWordTool.java:5: package com.sun.org.apache.xml.internal.security.utils does not exist
[javac] import com.sun.org.apache.xml.internal.security.utils.Base64;
[javac] ^
[javac] .../ChangePassWordTool.java:39: cannot find symbol
[javac] symbol : variable Base64
[javac] location: class com.xxx.ChangePassWordTool
[javac] passWord = Base64.encode(passWord.getBytes());
[javac] ^
[javac] 2 errors
由於在eclipse中使用ant插件編譯打包該項目沒有問題,納悶爲啥出現該異常。
首先定位該類:com.sun.org.apache.xml.internal.security.utils.Base64,發現是在jre/rt.jar中,因此第一步懷疑是ant的配置文件有問題,將build.xml中的文件調整如下:
- <project default="prod" basedir=".">
- ...
- <property environment="env" />
- <property name="java.jre.lib.dir" value="${env.JAVA_HOME}/jre/lib" />
- <!-- classpath used for javac -->
- <path id="classpath">
- <fileset dir="lib" includes="*.jar"/>
- <fileset dir="${java.jre.lib.dir}">
- <include name="*.jar" />
- </fileset>
- </path>
- ...
- <target name="compile" depends="init">
- <javac
- srcdir="src"
- destdir="${staging}/bin"
- encoding="UTF-8"
- source="1.6"
- target="1.6"
- nowarn="on"
- debug="on"
- optimize="on"
- includeantruntime="false">
- <classpath refid="classpath" />
- </javac>
- </target>
- </project>
但是調整之後,編譯打包還是報上述錯誤, 後查詢資料發現, 是由於javac編譯代碼的行爲所致。
javac在編譯代碼時,當他嘗試從rt.jar中找尋對應的類文件時,他會默認從對應的符號表文件ct.sym (同樣在jre/lib/下)中查找該類是否存在,由於ct.sym中有意或無意的遺失了部分rt.jar中的類,包括我使用的com.sun.org.apache.xml.internal.security.utils.Base64,因此導致編譯報錯。
解決方法就是通知javac編譯器,在編譯代碼時,忽略該符號表ct.sym, 直接查找rt.jar,通過給javac傳入對應的參數完成:-XDignore.symbol.file
在配置文件中即爲:
- <javac
- srcdir="src"
- destdir="${staging}/bin"
- encoding="UTF-8"
- source="1.6"
- target="1.6"
- nowarn="on"
- debug="on"
- optimize="on"
- includeantruntime="false">
- <compilerarg value="-XDignore.symbol.file"/>
- <classpath refid="classpath" />
- </javac>
編譯成功