关于类路径:除非在引导类路径中包含.jar,否则无法编译

Unable to compile unless .jar is included in bootclasspath

我正在尝试使用gradle构建一个android项目:这是一个具有ndk风格的库项目,由外部.jar增补,由Unity提供。

我真的不认为有关gradle文件的详细信息很重要,足以说明我将外部jar文件(由Unity提供)包含在以下内容中:

1
2
3
  dependencies {
    compile files('libs/unity.jar')
  }

实际上似乎有效,就像在Java编译期间一样,gradle发出了以下命令:

1
2
3
4
5
6
7
8
9
10
BASE="<Some directory>"
javac -d"${BASE}/PluginsSources/Android/libproject/build/intermediates/classes/fat/debug" \\
    -g -encoding UTF-8 \\
    -bootclasspath /Users/myusername/Applications/adt/sdk/platforms/android-23/android.jar \\
    -sourcepath"${BASE}/PluginsSources/Android/libproject/build/tmp/compileFatDebugJavaWithJavac/emptySourcePathRef" \\
    -classpath"${BASE}/PluginsSources/Android/libproject/libs/unity.jar" \\
   "${BASE}/PluginsSources/Android/libproject/src/main/java/org/example/ScriptBridge/JavaClass.java" \\
   "${BASE}/PluginsSources/Android/libproject/build/generated/source/r/fat/debug/org/example/ScriptBridge/R.java" \\
   "${BASE}/PluginsSources/Android/libproject/build/generated/source/buildConfig/fat/debug/org/example/ScriptBridge/BuildConfig.java" \\
    -XDuseUnsharedTable=true

缩进和您真正添加的BASE变量。请注意,unity.jar是类路径条目。

问题是,编译失败,因为javac在编译时显然无法在unity.jar中找到类,除非将该jar放在-bootclasspath选项(!!)中。

为什么会这样? AFAIK,类的搜索路径应该是分层的,并且在bootclasspath之后,javac应该搜索类路径。

是否可以告诉gradle将一些jar粘贴到bootclasspath中(这会很笨拙地解决问题)?

有没有更清洁/更好的方法?

感谢您的见解!


编辑:

经过更仔细的审查,看来classpath起作用了(惊奇!),Unity Technologies并没有创建一个具有突变类路径弹性的jar,因为这毕竟是接管世界的第一步。

问题出在compile语句的路径中,用正确的jar相对路径替换它后,一切都按预期工作。

问题的答案是:

问题1:为什么会这样?

因为Java无法在不存在的jar中找到类

Q2:是否可以告诉gradle将一些jar粘贴到bootclasspath中?

见下面的答案

Q3:有没有更清洁/更好的方法?

是的:确保您所链接的任何内容的路径都是正确的开始:)

请注意,gradle不会为丢失jar发出任何错误,即使在调试模式下也不行(这是一个臭名昭著的恕我直言)。


老答案

我必须以某种方式自己解决问题(我认为我的解决方法不是最佳的,但是鉴于对这个问题的关注,我想它会和它一样好...)

问题1:为什么会这样?

据我了解,没有任何翻转的理由。

该文件:

如何找到类(Oracle Canon)

明确指定引导程序中的类为:

Bootstrap classes are the classes that implement the Java 2 Platform.

即用于实现平台的类。这就是为什么android.jar存在而unity.jar不存在的原因。

Q2:是否可以告诉gradle将一些jar粘贴到bootclasspath中?

是!以下链接详细说明了如何:

修改编译器args中的bootclasspath(Gradle论坛)

那就是:

1
2
3
4
5
6
7
allprojects {
  gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
      options.compilerArgs <<"Xbootclasspath/a:src/main/libs/unity.jar"
    }
  }
}

在我的项目中,它映射为在Android库之后的unity.jar档案库中加载unity.jar档案库。

Q3:有没有更清洁/更好的方法?

我不这么认为,至少在不理解为何首先需要将jar放在引导程序中的情况下(这会使这里的大多数问题变得毫无意义):更改引导程序类路径并不是高级程序员应该做的事情,所以我不希望gradle提供更简洁的捷径。

我仍在等待对这个问题有一些见解的人(我不能花更多的时间在这个问题上),但是我希望无论如何这将对某人有所帮助。