上一篇我们讲了,怎么用javadoc和Doclet配合解析自己想要的注释(链接)。既然是一个工具,自然就要生成可执行的jar包。这貌似是一个很合理的要求,然后坑就来了。
我上篇说的是直接复制的tool.jar到lib包下面,添加进资源包就可以了,但是maven项目肯定不能这样做的,这样不规范。我在网上去搜索了tools.jar的依赖教程。

<dependency>
            <groupId>com.sun</groupId>
            <artifactId>tools</artifactId>
            <version>1.8</version>
            <scope>system</scope>
            <systemPath>${java.home}/../lib/tools.jar</systemPath>
  </dependency>

常规操作,pom.xml的

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.popcorn.gmtool.GMWrite</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.10</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
   </build>

这个maven打包配置很常见,具体可以自行网上搜素,我这个也是从网上copy的,这段代码大致就是说的把我自己的代码打包成一个可执行的jar文件,把我的依赖打包放在lib目录下面。mainClass这个标签要写成自己的程序入口,即你包含main()的类。执行mvn cleanmvn package两个命令,前者清空打包,后者打包,不懂这个两个命令小伙伴的自行google。

打包效果如下图

tools maven引入 maven tools.jar_java


好像一切按照预期的执行,达到了预期的效果,来执行java -jar target/gm-txt-tool-1.0-SNAPSHOT.jar命令来检测。是不是感觉完美解决了。呵呵,如果真的这么简单,我就不写了。

tools maven引入 maven tools.jar_java_02

找不到这个类???明明打包成功,还按照预期输出的,为什么找不到?心里充满了愤怒,充满了不解,感觉我在忽悠你是不是。打开gm-txt-tool-1.0-SNAPSHOT.jar找到MTEA-INF下面的MANIFEST.MF文件,打开,看到如下

tools maven引入 maven tools.jar_jar_03


有经验的小伙伴就发现问题了,缺少了Class-Path。这个是重点,因为我们源码和依赖包是分开的,所以这个清单里面应该有一个属性指定我们写的源码依赖的。附上一张正常的打包结果

tools maven引入 maven tools.jar_jar_04


看见没有,这个才是正常的清单文件。你问我后面这个是怎么来的?其实和上面的打包方式一样,只是修改了一下程序入口的,也就是mainClass的参数。为什么会出现这样的差异?

相信你们也猜到原因了,没错就是我的tools.jar的依赖问题,tools.jar是jdk/lib下面自带的包。好像这个和我们说的问题没有关系吧,但是这个界面你一定很熟悉。

tools maven引入 maven tools.jar_tools maven引入_05


JAVA是号称跨平台语言,语言跨平台,但没说JVM虚拟机跨平台。我咨询的一位大佬告诉我,native方法,在不同的操作系统有不同的实现。这个我没有研究,如果说错了,欢迎留言指教。

你这里说了半天,还是没有说这个问题应该怎么解决的啊?你到底会不会解决啊?
不着急,重点来了,解决方案
java -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.ext.dirs=${JAVA_HOME}/lib -jar target/gm-txt-tool-1.0-SNAPSHOT.jar

这就是我的完美解决方案。

把之前的命令修改成现在这样,指定文件编码和jvm虚拟机编码为utf-8,因为java项目默认编码为gbk的,稍微有点了解的都应该知道这个编码问题的。
-Djava.ext.dirs=${JAVA_HOME}/lib
这个是指定依赖的本地包,这个命令无论你是Linux或者Windows系统都行的,环境变量你都要配置。如果你有多个包Windows下面用分号;隔开,Linux下面用:号隔开,具体用法可以自行google。
事情到这里就完全结束了。关于这个的一点思考,Java语言是跨平台的,但是JVM不是跨平台的。