2016-01-12 3 views
1

У меня вопрос об использовании Java ClassLoader в OSGi.Использование загрузчика классов Java в OSGi

Я написал два пакета OSGi, а именно серверный комплект и клиентский комплект.

В серверном расслоении, я реализовал BundleActivator как:

public class Activator implements BundleActivator { 

    public void start(BundleContext context) { 
     System.out.println("[Server:Activator.java:26] " + Activator.class.getClassLoader()); 
     context.registerService(HelloService.class, new HelloService(), null); 
    } 

    public void stop(BundleContext context) { 
     System.out.println("Stopping the bundle"); 
    } 
} 

И в клиентском расслоении, я реализовал BundleActivator как:

public class Activator implements BundleActivator { 

    public void start(BundleContext context) { 
     ServiceReference<HelloService> ref = context.getServiceReference(HelloService.class); 
     HelloService service = context.getService(ref); 
     System.out.println("[Client:Activator.java:48] " + HelloService.class.getClassLoader()); 
     System.out.println("[Client:Activator.java:49] " + Activator.class.getClassLoader()); 
    } 

    public void stop(BundleContext context) { 
     System.out.println("Stopping the bundle"); 
    } 
} 

И когда я начал OSGi, консольный вывод:

[Сервер: Activator.java: 26] [email protected] [osgi-server: 1.0. 0 (id = 54)] [Клиент: Activator.java: 48] [email protected] [osgi-server: 1.0.0 (id = 54)] [Клиент: активатор. Java: 49] [email protected]a [OSGi-клиент: 1.0.0 (ID = 55)]

Как вы можете видеть, что загрузчик классов загружает HelloService всегда DefaultClassLoader @ 56b161a независимо от того, на стороне сервера или на стороне клиента.

Я не могу этого понять. Насколько мне известно, когда класс B ссылается в классе A, загрузчик классов класса B такой же, как класс loader класса. Но в OSGi это выглядит не так.

Можете ли вы меня просветить? Есть ли что-то, что я пропустил в Java ClassLoader? Или OSGi делает что-то сложное?

манифеста сервер расслоения:

Manifest-Version: 1.0 
Bnd-LastModified: 1452582379580 
Build-Jdk: 1.7.0_45 
Built-By: haoruan 
Bundle-Activator: com.cisco.ruan.server.Activator 
Bundle-Description: osgi-server OSGi bundle project. 
Bundle-ManifestVersion: 2 
Bundle-Name: osgi-server Bundle 
Bundle-SymbolicName: osgi-server 
Bundle-Version: 1.0 
Created-By: Apache Maven Bundle Plugin 
Export-Package: com.cisco.ruan.server;version="1.0";uses:="org.osgi.fram 
ework" 
Import-Package: org.osgi.framework;version="[1.7,2)" 
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.5))" 
Tool: Bnd-3.0.0.201509101326 

манифест клиент расслоения:

Manifest-Version: 1.0 
Bnd-LastModified: 1452582396099 
Build-Jdk: 1.7.0_45 
Built-By: haoruan 
Bundle-Activator: com.cisco.ruan.client.Activator 
Bundle-Description: osgi-client OSGi bundle project. 
Bundle-ManifestVersion: 2 
Bundle-Name: osgi-client Bundle 
Bundle-SymbolicName: osgi-client 
Bundle-Version: 1.0 
Created-By: Apache Maven Bundle Plugin 
Export-Package: com.cisco.ruan.client;version="1.0";uses:="com.cisco.rua 
n.server,org.osgi.framework" 
Import-Package: com.cisco.ruan.server;version="[1.0,2)",org.osgi.framewo 
rk;version="[1.7,2)",org.slf4j;version="[1.7,2)" 
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.5))" 
Tool: Bnd-3.0.0.201509101326 

================== =============================================

Привет, Нил, это эксперимент, который я только что сделал :

У меня есть ClassA и ClassB, а класс Wra pper относится к этим двум классам.

public class Wrapper { 

    public Wrapper() { 
     showInfo(); 
    } 

    public void showInfo() { 
     System.out.println("[Wrapper.java:5] " + ClassA.class.getClassLoader()); 
     System.out.println("[Wrapper.java:8] " + ClassB.class.getClassLoader()); 
    } 
} 

И я написал свой собственный настроенный загрузчик классов MyClassLoader:

class MyClassLoader extends ClassLoader { 
    private ClassLoader haocl; 
    private ClassLoader ruancl; 

    public MyClassLoader() { 
     this.haocl = new HaoClassLoader(); 
     this.ruancl = new RuanClassLoader(); 
    } 

    @Override 
    public Class<?> loadClass(String name) throws ClassNotFoundException { 

     if (name.endsWith("com.cisco.ruan.classloader.ClassA")) { 
      return haocl.loadClass(name); 
     } 

     if (name.endsWith("com.cisco.ruan.classloader.ClassB")) { 
      return ruancl.loadClass(name); 
     } 

     if (name.endsWith("Wrapper")) { 
      InputStream is = null; 
      try { 
       is = new FileInputStream("/Users/haoruan/Desktop/Projects/cl-test/target/classes/com/cisco/ruan/classloader/Wrapper.class"); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      byte[] bytes = null; 
      try { 
       bytes = ByteStreams.toByteArray(is); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      return defineClass(name, bytes, 0, bytes.length); 
     } 

     return super.loadClass(name); 

    } 
} 

Тогда я назвал Class.forName("com.cisco.ruan.classloader.Wrapper", true, mcl).newInstance(); и консольных выходы:

[Wrapper.java:5] com.cisco. [email protected] [Wrapper.java:8] [email protected]

Итак, можно предположить, что ClassA и ClassB сначала загружаются MyClassLoader, а затем фактически загружаются HaoClassLoader и RuanClassLoader. И я думаю, что этот эксперимент может показаться очень простой реализацией механизма загрузчика классов OSGi? Правильно?

+0

Можете ли вы показать, как вы .bnd файл или манифест или pom? Возможно, у вас установлен неправильный класс активатора пакетов. – amkz

ответ

8

Это абсолютно нормально в OSGi. В OSGi есть один загрузчик классов для каждого пакета. Этот загрузчик классов обслуживает все классы, которые расположены в комплекте. Для всех классов вне пакета существуют определения Import-Package. Во время выполнения каждый импорт пакета подключается к пакету, который экспортирует пакет. Когда класс из такого пакета загружается, загрузка делегируется другому загрузчику классов bundles.

Давайте рассмотрим ваш сценарий.

Bundle osgi-server содержит класс com.cisco.ruan.server.HelloService, он также экспортирует пакет com.cisco.ruan.server. Bundle osgi-client импортирует пакет com.cisco.ruan.server. Когда вы загружаете класс HelloService в Activator osgi-client, загрузчик класса osgi-client запрашивает загрузку класса. Он находит делегацию для пакета и делегирует загрузку загрузчика классов osgi-сервера. Этот загрузчик классов является пользователем для загрузки класса.

Это поведение по умолчанию в OSGi, и если вы думаете, что это с ним, это имеет большой смысл.

2

Вы сказали: «Насколько я знаю, когда класс B ссылается в классе A, загрузчик классов класса B такой же, как класс загрузчика класса A. Но в OSGi это выглядит не так».

Это не истинное утверждение о загрузчиках классов Java ... независимо от того, используете ли вы OSGi или нет.

Например, каждый класс, который вы пишете, находится от java.lang.Object. Ваш класс загружается загрузчиком классов приложений, но java.lang.Object загружается загрузчиком классов. Это работает из-за делегирования: один загрузчик классов может попросить другого загрузчика классов загрузить класс от его имени.

В OSGi это точно то же самое. В каждом пакете есть загрузчик классов, и когда вы импортируете пакет из другого пакета, этот загрузчик классов другого класса используется для их загрузки.

+0

Я не думаю, что вы правы в том, что «каждый класс, который вы пишете, выходит из java.lang.Object. Ваш класс загружается загрузчиком класса приложения». Это потому, что «Мой класс» все еще находится в пути к классу, и System ClassLoader может его найти, поэтому загрузчик классов оказывается загрузчиком классов приложений. Если «мой класс» не находится под курсом класса, и только мой настраиваемый загрузчик классов может его найти, то загрузчик классов «мой класс» не должен быть загрузчиком классов приложений. – ruanhao

+0

Эй Я кодировал Java 18 лет и написал книгу о OSGi; Я прав. В случае, если у вас есть пользовательский загрузчик классов, у этого загрузчика классов все еще есть родительский элемент и он по-прежнему делегирует загрузчику класса загрузки. –

+0

Привет, Бартлетт, не обижайтесь. Я не знаю, правильно ли я сказал. Но я только что написал код об этом вопросе, и я обнаружил, что загрузчик классов может быть «унаследован». Позвольте мне опубликовать код и посмотреть, есть ли что-то неправильно :) – ruanhao

Смежные вопросы