「解决方案」JDK11环境下的Android/Java项目中导入tools.jar包依赖

  首先,来说一下今天写这篇文章的目的。从JDK9开始,JDK安装包中就不再包含tools.jar包了,那么之前所使用的依赖方式就失效了,那么我们应该如何在新版本中去解决这个以来问题,从而不影响我们的项目正常编译呢?
  在开发时,我们可能会在编译前或编译后通过一些手段去修改Java生成的字节码。比如使用JavaParser生成或修改源代码,使用Javapoet生成Java类,又或者通过Javassist修改class字节码文件。各种各样的方法层出不穷,我们可以根据自己的场景去选取合适工具。而在一些情况下,我们可能希望在编译前通过修改Java的抽象语法树来改变编译所生成的class字节码文件。这个时候我们就可以考虑使用JDK中的tools.jar来处理这个问题了。
  那么,在项目中我们要怎么去依赖/引入tools.jar包呢?这里我会分别从JDK8/JDK11和Gradle项目和纯Java项目这几个维度去说明如何引入tools.jar依赖包,并且本文中使用的IDE是Intellij IDEA。毕竟买了正版软件,不用起来就浪费了。

JDK8 & Gradle

  在项目的build.gradle中添加如下依赖。

1
2
3
dependencies {
implementation files('C:\\Program Files\\Java\\jdk1.8.0_251\\lib\\tools.jar')
}

  如果你已经配置了环境变量,则可以使用以下方式进行依赖。

1
2
3
4
dependencies {
// implementation files('C:\\Program Files\\Java\\jdk1.8.0_251\\lib\\tools.jar')
implementation files(System.getenv('JAVA_HOME') + '/lib/tools.jar')
}

  JDK8下的配置应该问题不大,身为开发者应该都知道怎么去依赖。

JDK8 & Java

  修改项目根目录下的.iml文件,在原有文件的后面加上如下配置:

1
2
3
4
5
6
7
8
9
10
11
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://C:/Program Files/Java/jdk1.8.0_251/lib/tools.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://C:/Program Files/Java/jdk1.8.0_251/lib/tools.jar!/" />
</SOURCES>
</library>
</orderEntry>

  当然,你也可以通过Intellij IDEA右上角的“Project Structure”或快捷键”Ctrl+Alt+Shift+S“打开Project Structure配置面板。选中”Project Settings“->”Modules“,然后选中你需要引入tools.jar的module,然后在右侧上方的tab选项卡中选中“Dependencies“->”Add”->“1 JARs or directories…”,然后选择JDK8安装目录下的tools.jar即完成依赖包的引入。如下图:
「解决方案」JDK11环境下的Android/Java项目中导入tools.jar包依赖

JDK11 & Gradle

  修改项目下的build.gradle文件,添加sourceCompatibility和targetCompatibility。

1
2
3
4
5
6
7
8
9
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
// implementation files('C:\\Program Files\\Java\\jdk1.8.0_251\\lib\\tools.jar')
// implementation files(System.getenv('JAVA_HOME') + '/lib/tools.jar')
}

  顺便提一嘴,Android Studio中的Java Module配置和此一样。

JDK11 & Java

  将项目根目录下的.iml从<orderEntry type="inheritedJdk" />修改成<orderEntry type="jdk" jdkName="8" jdkType="JavaSDK" />。如下图:
「解决方案」JDK11环境下的Android/Java项目中导入tools.jar包依赖

  或者通过Project Structure面板进行修改同样可行。
「解决方案」JDK11环境下的Android/Java项目中导入tools.jar包依赖

总结

  综上所述,其实配置方式挺简单的。以上也是个人开发中遇到并寻求解决方案过程中得到的结果。JDK9之后,像tools.jar、dt.jar等JDK安装目录中lib下的jar包都被移除了。相应的,增加了jmods文件夹,文件夹下jdk.compiler.jmod对应着之前的tools.jar。使用解压软件打开jdk.compiler.jmod,可以发现jdk.compiler.jmod中的classes目录下的文件和tools.jar几乎是一样的,oracle将其分模块进行隔离,旨在提高其安全性等方面原因。而之所以使用JDK11时在项目中配置目标版本为8时,就可以使用其中的诸如tools.jar包里面的类,我想是为了兼容可能吧。
  如有疑问/建议,可以给我留言,我们共同成长!