参考
- 大体排查思路参考
- -Djava.ext.dirs 参数究竟是什么东西
- JDK8 中使用 -Djava.ext.dirs 参数来在运行 Jar 包中导入其他 Jar
- 在运行 Jar 包中导入其他 Jar 的常用方法
自己的碰到的问题
折腾 Appium 的时候要看 APP 的页面元素嘛; 然后就是用 Uiautomatorviewer 来看,结果闪退无法打开, 我自己装的是 JDK11 绿色版,还挺喜欢这个版本,又不想换 JDK8,然后就开始折腾,主要遇到的问题有两个:
- -Djava.ext.dirs not support,意思是这个参数在 JDK11 不再支持了, 要求你使用 -classpath/–class-path 参数,然后如果你用了这个参数会出现下面的第二个问题
- 无法初始化主类问题
解决问题
虽然看不懂 .bat,但是还是硬着头皮看了,我给你们大体分析下
...
这是原版的代码,我加了几行打印语句调试,顺便提一句 rem 在 .bat 中应该是注释的意思, echo 就是打印,懂得都懂
前面的代码大体就干了两件事,找 Java,找各种各样的路径,为了最后一行代码执行真正的程序做准备的
rem lib\x86_64;lib
echo %javaextdirs%
rem D:\Dev\SDKTools-r24.4.1\tools
echo %prog_dir%
rem lib\uiautomatorviewer.jar
echo %jarpath%
call "%java_exe%" "-Djava.ext.dirs=%javaextdirs%" "-Dcom.android.uiautomator.bindir=%prog_dir%" -jar %jarpath% %*
所以上面的最后一行代码,其实是想执行这样一条 java 命令
java -Djava.ext.dirs=lib\x86_64;lib -Dcom.android.uiautomator.bindir=D:\Dev\SDKTools-r24.4.1\tools -jar lib\uiautomatorviewer.jar
// 我解释一下这条命令
// 先看第二个 -D,意思是给 JVM 设置启动参数
// -jar 说明它是想 Java 执行一个封装好的 Jar 文件
// 在看第一个 -D,意思也是给 JVM 设置启动参数,但是这个参数非同凡响,可以做到运行的 Jar 导入依赖的 Jar, 详细可以看参考链接 2,3
// 所以这整句命令的意思是:
// 运行 lib\uiautomatorviewer.jar ,并从 lib\x86_64;lib 目录中找到该 Jar 所依赖的 Jar
想法很美好,但是有一个问题, -Djava.ext.dirs 参数在 JDK8 以上应该是失效的,因此一个直接的结果就是 -Djava.ext.dirs not support
, 网上有一个针对此项的改法,改成 --class-path=
, 但是,这种改法是错误的,参见参考链接4,引用原话如下:
java -classpath some.jar -jar test.jar
这种方式是不行的,因为使用 classpath 指定的 jar 是由 AppClassloader 来加载,java 命令加了-jar 参数以后,AppClassloader 就只关注 test.jar 范围内的 class 了,classpath 参数失效。那该怎么引用其他的 jar 包呢?
简而言之,classpath 指定的是运行 jar 的寻找路径,而不是添加其所依赖 jar 的依赖,这句话我瞎蒙的,但是应该就是这样
那么到底怎么添加其所缺少的 swt.jar 呢?
我根据链接4选择了我认为的最简单一种方法: 修改 Jar 中 META-INF/MANIFEST.MF 文件
原文件如下:
Manifest-Version: 1.0
Main-Class: com.android.uiautomator.UiAutomatorViewer
Class-Path: org-eclipse-jface-3.6.2.jar ddmlib.jar org-eclipse-core-c
ommands-3.6.0.jar org-eclipse-equinox-common-3.6.0.jar osgi-4.0.0.jar
common.jar kxml2-2.3.0.jar annotations.jar guava-17.0.jar
我们只需要在末尾添加 swt.jar 的相对路径即可, 其他 Jar 都在同级目录下真是帮大忙了,修改如下:
Manifest-Version: 1.0
Main-Class: com.android.uiautomator.UiAutomatorViewer
Class-Path: org-eclipse-jface-3.6.2.jar ddmlib.jar org-eclipse-core-c
ommands-3.6.0.jar org-eclipse-equinox-common-3.6.0.jar osgi-4.0.0.jar
common.jar kxml2-2.3.0.jar annotations.jar guava-17.0.jar x86_64/swt.jar
然后由于我们手动显式添加了 swt.jar,并且其他 jar 都在同级目录,因此 java 命令中就可以直接运行,不需要加什么参数了,.bat 文件修改如下:
call "%java_exe%" "-Dcom.android.uiautomator.bindir=%prog_dir%" -jar %jarpath% %*
大功告成
写在最后
捣鼓了挺久,希望能帮助大家,或者给大家提供一点思路