gembin

OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

HBase, Hadoop, ZooKeeper, Cassandra

Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

About Me

 

equinox环境下开发bundle不需要引入java.*包而需要引入javax.*包的的原因

ClassLoader(类加载器)是Java提供的抽象类,它是负责加载类的对象。ClassLoader 做的工作就是在JVM 中将类装入内存。 当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 返回一个表示这个类的 Class 对象。

一、前提知识 ClassLoader


ClassLoader(类 加载器)是Java提供的抽象类,它是负责加载类的对象。ClassLoader 做的工作就是在JVM 中将类装入内存。 当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 返回一个表示这个类的 Class 对象。


所有java.*包内的类都是由ClassLoader完成加载的,而且在执行java命令的时候ClassLoaer就已经被装入内存中。通常在开发过程中使用java.*包内的类的时候,不再需要import 这些类了。


二、Bundle中的ClassLoader


在equinox环境下,每一个bundle都有独立的classLoader,对应的类名为BundleLoader。

每个bundle的classLoader都有parent,这个parent(父classLoader)就是类的委派模型中的上一层的classLoader。对应的类名为ParentClassLoader,它是这样定义的



private static class ParentClassLoader extends ClassLoader {

 
protected ParentClassLoader() {

  
super(null);

 }

}


这是一个空的classloader,它直接继承了java.lang.ClassLoader 。java包中的所有类都是由java.lang.ClassLoader载入的,根据类的委派模型可以知道,继承了ClassLoader就可以直接获得需要的java类。



            if (name.startsWith(JAVA_PACKAGE))

              
// 1) if startsWith "java." delegate to parent and terminate search

              
// we want to throw ClassNotFoundExceptions if a java.* class cannot be loaded from the parent.

                return parent.loadClass(name);


上面代码是bundle加载class的流程图中的第一步,通过parentClassLoader获得所需java.*包中的类,如下图所示。



 这就是bundle中不需要引入java.*包的原因。


三、如何知道java.*这些类已经被装载了呢?


1、写一个类如下:



public class  A

{

    
public static void main(String[] args) 

    {

        System.out.println(
"Hello World!");

    }

}



2、编译



javac A.java


3、运行



java -verbose A


显示的部分内容如下:



[Loaded java.lang.Object from shared objects file]

[Loaded java.io.Serializable from shared objects file]

[Loaded java.lang.Comparable from shared objects file]

[Loaded java.lang.CharSequence from shared objects file]

[Loaded java.lang.String from shared objects file]

[Loaded java.lang.reflect.GenericDeclaration from shared objects file]

[Loaded java.lang.reflect.Type from shared objects file]

[Loaded java.lang.reflect.AnnotatedElement from shared objects file]

[Loaded java.lang.Class from shared objects file]

[Loaded java.lang.Cloneable from shared objects file]

[Loaded java.lang.ClassLoader from shared objects file]

... (后面还有很多,不一一列举)


 


四、为什么需要引入javax.*包


下面的代码是另一篇文章 equinox实现Class Loader机制的代码解读  提过的,bundle类载入的流程图片段代码。



  ...

  String pkgName 
= getPackageName(name);

        
// follow the OSGi delegation model

        if (checkParent && parent != null) ...{

            
if (name.startsWith(JAVA_PACKAGE))

              
// 1) if startsWith "java." delegate to parent and terminate search

              
// we want to throw ClassNotFoundExceptions if a java.* class cannot be loaded from the parent.

                return parent.loadClass(name);

            
else if (isBootDelegationPackage(pkgName))

                
// 2) if part of the bootdelegation list then delegate to parent and continue of failure

                try ...{

                    
return parent.loadClass(name);

                } 
catch (ClassNotFoundException cnfe) ...{

                    
// we want to continue

                }

        }

 ...


从上面的代码可以看出,如果不是第一种情况(包名不是以java.开始的)就使用第二个判断条件。


isBootDelegationPackage(pkgName)返回的是true(这个配置在以后再说),所以执行的是


parent.loadClass(name);


这 行代码和第一个条件的代码是一样的,即还是使用parentClassLoader去加载javax.*的包。由于ClassLoader只加载了 java.*的包,所以这里是不能得到javax.*包中的类的,会导致 ClassNotFoundException 的错误。从上面的代码可以知道,代码中对ClassNotFoundException 没有处理,而是 继续执行了。分别从import package、required bundles、bundle内部classpath和dynamic import 获取javax.*的包。


通常情况下,这些javax.*的包作为required bundle提供,而且只需要提供一次,并避免在其他的bundle中再次/重复提供(export)。



        PackageSource source = findImportedSource(pkgName);

        if (source != null) {

            
// 3) found import source terminate search at the source

            result = source.loadClass(name);

            
if (result != null)

                
return result;

            
throw new ClassNotFoundException(name);

        }

        
// 4) search the required bundles

        source = findRequiredSource(pkgName);

        
if (source != null)

            
// 4) attempt to load from source but continue on failure

            result = source.loadClass(name);

        
// 5) search the local bundle

        if (result == null)

            result 
= findLocalClass(name);

        
if (result != null)

            
return result;

        
// 6) attempt to find a dynamic import source; only do this if a required source was not found

        if (source == null) {

            source 
= findDynamicSource(pkgName);


这就是需要引入javax.*包的原因。

posted on 2008-05-05 10:26 gembin 阅读(959) 评论(0)  编辑  收藏 所属分类: OSGi


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(6)

随笔分类(440)

随笔档案(378)

文章档案(6)

新闻档案(1)

相册

收藏夹(9)

Adobe

Android

AS3

Blog-Links

Build

Design Pattern

Eclipse

Favorite Links

Flickr

Game Dev

HBase

Identity Management

IT resources

JEE

Language

OpenID

OSGi

SOA

Version Control

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜

free counters