2

在我的项目中,我可以看到所有 JUnit 测试用例都是用 eclipse 片段而不是 eclipse 插件编写的。我们确实将每个测试类作为 JUnit 插件运行。我对这些概念不是很清楚。我对这个概念比较陌生。

我只是用谷歌搜索以获得关于使用片段而不是插件进行测试的更好的知识。我的理解是,片段和主机插件共享同一个类加载器。如果我的理解有误,请纠正我。

但是我不明白下面一行的含义。

如果我们在 eclipse 插件中创建测试,测试类将由单独的类加载器加载,因此无法访问被测类的非公共方法。

为什么它无法访问非公共方法?任何人都可以通过简单的例子帮助我理解上述含义吗?

4

1 回答 1

2

要理解这一点,您需要了解类和类加载在 Java 中的实际工作方式。通常我们会根据“类路径”来考虑加载,但这是对工作方式的极大简化。在许多 Java SE 环境中,这只是工作,但在像 OSGi 这样的多租户环境中,它变得更加复杂。

本质上,在 Java 中,类的作用域包括三件事:

  1. 姓名
  2. 包裹
  3. 类加载器

完全有可能在 JVM 中多次加载 myPackage.MyClass 的两个实例,您只需要多个类加载器。即使这些类可以从相同的 .class 文件中加载,它们在运行时也会有所不同。当您编写这样的代码时,这可能会引起很多混乱:

MyClass c = (MyClass)obj;

并得到一个ClassNotFoundException: MyClass.

类存在于包中,并且有与之相关的特殊可见性规则。没有明确可见性的类型、方法和字段对同一包中的所有类型都是可见的。当一个类被加载时,它与一个 java.lang.reflect.Package 相关联,可见性规则通过检查这些类是否与同一个 java.lang.reflect.Package 实例相关联来解决。因此,对于 mypackage.MyClass,如果您使用两个不同的类加载器加载它两次,您将获得 mypackage 的两个 Package 实例。

OSGi 旨在支持多租户类加载,这允许您在同一个 JVM 中同时拥有两个不同版本的类或包。这解决了如果您有不同的版本依赖关系而导致的许多问题。它通过为每个包使用不同的类加载器来实现这一点。片段的工作方式与捆绑包不同,因为它们与捆绑包相关联,并且其中的类由捆绑包的类加载器加载,而不是拥有自己的类加载器。

如果你把你的junit测试放在一个包中(而不是一个片段),把这个与你原来的问题联系起来,你的类将由不同的类加载器加载,因此它将与java.lang.reflect的不同实例相关联。打包以便当 JVM 测试成员可访问性时它会失败。

于 2015-06-11T23:45:39.923 回答