У меня вопрос об использовании 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? Правильно?
Можете ли вы показать, как вы .bnd файл или манифест или pom? Возможно, у вас установлен неправильный класс активатора пакетов. – amkz