【问题标题】:Why I cannot access a package-private class in another jar (NOT sealed)?为什么我无法访问另一个 jar(未密封)中的包私有类?
【发布时间】:2017-09-09 17:39:40
【问题描述】:

我遇到了 Java 类加载器的奇怪行为:

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

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

HiveServer2.ServerOptionsProcessor 类已经预加载到集群上(作为 Spark 依赖项),但被声明为包私有。

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

  static interface ServerOptionsExecutor {
  ...
  }
}

这个类在集群建立时首先加载到 JVM 中。然后我的类(在另一个 jar 中)在我的应用程序提交时由同一个 JVM 加载。

此时我收到以下错误:

线程“主”java.lang.IllegalAccessError 中的异常:类 org.apache.hive.service.server.DPServerOptionsProcessor 无法访问 它的超类 org.apache.hive.service.server.HiveServer2$ServerOptionsProcessor 位于 java.lang.ClassLoader.defineClass1(本机方法)在 java.lang.ClassLoader.defineClass(ClassLoader.java:763) 在 java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 在 java.net.URLClassLoader.defineClass(URLClassLoader.java:467) 在 java.net.URLClassLoader.access$100(URLClassLoader.java:73) 在 java.net.URLClassLoader$1.run(URLClassLoader.java:368) 在 java.net.URLClassLoader$1.run(URLClassLoader.java:362) 在 java.security.AccessController.doPrivileged(Native Method) 在 java.net.URLClassLoader.findClass(URLClassLoader.java:361) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:424) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:357) 在 org.apache.spark.sql.hive.thriftserver.DPHiveThriftServer2$.main(DPHiveThriftServer2.scala:26) 在 org.apache.spark.sql.hive.thriftserver.DPHiveThriftServer2.main(DPHiveThriftServer2.scala) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:731) 在 org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:181) 在 org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206) 在 org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121) 在 org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

我的印象是包私有类可以被同一个包中的任何其他类访问。而且我已经仔细检查了 Spark 罐子中的清单文件,它们都没有将 org.apache.hive.service.server 声明为密封包。那么为什么 JVM 类加载器给了我这个错误呢? JVM 使用什么条件触发异常?

【问题讨论】:

  • 你能检查一下哪些类加载器加载了这两个类
  • 从堆栈跟踪,似乎是普通的旧 URLClassLoader。
  • 它们是同一个类加载器吗?
  • 不确定,但第二个类加载器(引发错误的那个)肯定可以访问超类和子类

标签: java classloader package-private


【解决方案1】:

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

More Info

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-22
    • 2016-02-21
    • 2016-03-14
    • 2012-07-23
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多