为什么我无法访问另一个 jar(未密封)中的包私有 class?

Why I cannot access a package-private class in another jar (NOT sealed)?

我遇到了 Java classloader:

的奇怪行为

假设我向集群提交了一个 Apache Spark jar,其中包含 HiveServer2 的扩展:

package org.apache.hive.service.server;
public class MyOP2 extends HiveServer2.ServerOptionsProcessor(
  String var) {
...

class HiveServer2.ServerOptionsProcessor 已经预加载到集群上(作为 Spark 依赖项),但被声明为 package-private。

package org.apache.hive.service.server;
public class HiveServer2 extends CompositeService {
...

  static interface ServerOptionsExecutor {
  ...
  }
}

此 class 在设置集群时首先加载 JVM。然后我的 class(在另一个 jar 中)在提交我的应用程序时由同一个 JVM 加载。

此时我得到以下错误:

Exception in thread "main" java.lang.IllegalAccessError: class org.apache.hive.service.server.DPServerOptionsProcessor cannot access its superclass org.apache.hive.service.server.HiveServer2$ServerOptionsProcessor at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access0(URLClassLoader.java:73) at java.net.URLClassLoader.run(URLClassLoader.java:368) at java.net.URLClassLoader.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.apache.spark.sql.hive.thriftserver.DPHiveThriftServer2$.main(DPHiveThriftServer2.scala:26) at org.apache.spark.sql.hive.thriftserver.DPHiveThriftServer2.main(DPHiveThriftServer2.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:731) at org.apache.spark.deploy.SparkSubmit$.doRunMain(SparkSubmit.scala:181) at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206) at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121) at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

我的印象是 package-private class 可以被同一包中的任何其他 class 访问。我仔细检查了 Spark 罐子中的清单文件,其中 none 声明 org.apache.hive.service.server 为密封包。那么为什么 JVM classloader 给我这个错误呢? JVM使用什么条件触发异常?

由于这 2 个包由不同的 ClassLoader 加载,它们被视为 2 个不同的包,因此这意味着包私有方法不可访问,导致错误消息

More Info