搜索

此内容没有您所选择的语言版本。

1.2. Conflicting Classes

download PDF

Overview

One of the main aims of the OSGi class loading architecture is to avoid loading conflicting class definitions into the same bundle class space. This section explains how such conflicts can arise in practice.

Symbolic references

To explain the difficulties that can be caused by having multiple copies of a loaded class, we need the concept of a symbolic reference to a class or interface. A symbolic reference is a point in your code where a class name is used, except the actual definition of the class. For example, when a class name is used to specify a return type, a parameter type, or a variable type, the class name is a symbolic reference.
At run time, the JVM must resolve each symbolic reference by linking it to a specific instance of a loaded class. Symbolic references are resolved using the same class loader as the class in which they appear. For example, Example 1.1, “Symbolic Reference Used in a Class Cast” shows the definition of the TestHello class, which is loaded by the class loader, A.

Example 1.1. Symbolic Reference Used in a Class Cast

// Java
package org.bar;

// TestHello loaded by ClassLoader 'A'
public class TestHello {
    public void useHelloObj(Object hello) {
        org.foo.Hello h = (org.foo.Hello) hello;
        System.out.println(h.getGreeting());
    }
}
Important
Although the symbolic reference, org.foo.Hello, is initially loaded by class loader A, this does not imply that the symbolic references must be resolved to A/org.foo.Hello. If the initial class loader A decides to delegate to another class loader, B, the symbolic reference could be resolved to B/org.foo.Hello instead (so that B is the effective class loader). The delegation mechanism is crucial, because it enables an OSGi bundle to re-use existing loaded classes and avoid class space inconsistencies.

Class cast exceptions

When multiple class loaders are used in parallel (as happens in OSGi), there is a danger that a class could be loaded more than once. This is undesirable, because it almost inevitably causes class cast exceptions at run time.
For example, consider the TestHello class shown in Example 1.1, “Symbolic Reference Used in a Class Cast”, where the org.foo.Hello symbolic reference has been resolved to A/org.foo.Hello. If you also have a Hello object that is an instance of B/org.foo.Hello type, you will get a class cast exception when you pass this object to the TestHello.useHelloObj(Object) method. Specifically, in the line of code that performs the following cast:
org.foo.Hello h = (org.foo.Hello) hello;
The org.foo.Hello symbolic reference has been resolved to the A/org.foo.Hello type, but the hello object is of B/org.foo.Hello type. Because the types do not match, you get the class cast exception.
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.