- 浏览: 3502444 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
wanglf1207:
EJB的确是个不错的产品,只是因为用起来有点门槛,招来太多人吐 ...
weblogic-ejb-jar.xml的元素解析 -
qwfys200:
总结的不错。
Spring Web Flow 2.0 入门 -
u011577913:
u011577913 写道也能给我发一份翻译文档? 邮件437 ...
Hazelcast 参考文档-4 -
u011577913:
也能给我发一份翻译文档?
Hazelcast 参考文档-4 -
songzj001:
DbUnit入门实战
http://wiki.eclipse.org/index.php/Context_Class_Loader_Enhancements
Contents
[hide ]<script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
Overview
This design defines the behavior of the context class loader in the Equinox OSGi Framework. Many java libraries exist that use the context class loader. In an OSGi Framework environment the context class loader is not defined. This leads to class loading issues when trying to package such libraries into bundles. This document describes the solutions offered by the Equinox OSGi Framework to solve some of these issues.
Terminology
Context Class Loader
A context class loader is associated with a Thread. This class loader is provided by the thread creator to code running in the thread for the purpose loading classes and resources. This class loader is useful for loading classes and resources that are not always available to the class loader which loaded the code running in the thread.
Context Switch
For the purpose of this design a Context Switch is defined as the point in an execution sequence when a component boundary is crossed from one component to the next.
Class forName
A classic Java mechanism for dynamic class discovery and loading. It uses the current classloader to look for and load the requested class. The current classloader is the classloader that loaded the class containing the method executing the forName(String) call.
Context Finder
A special class loader that finds that first Bundle classloader on that stack and delegates load requests to that classloader.
Buddy Policy
A policy that allows a bundle to declare it needs help from other bundles to load classes. This type of policy does not cause a hard dependency wire to be used to load the classes from a buddy.
Problem Description
Most OSGi-biased developers will concede that the majority of java libraries out there are not currently shipped as OSGi bundles and are not aware of the Modular Layer in the OSGi Framework. Many existing java libraries are designed to run inside a container (J2EE container, Applet container etc). Such containers explicitly define execution boundaries between the various components running within the container. The container controls the execution boundaries and knows when a boundary is being crossed from one component to the next.
This level of boundary control allows a container to switch the context of a thread when a component boundary is crossed. Typically when a container detects a context switch it will set the context class loader on the thread to a class loader associated with the component which is being entered. When the component is exited then the container will switch the context class loader back to the previous context class loader.
The OSGi Framework specification does not define what the context class loader should be set to and does not define when it should be switched. Part of the problem is the Framework is not always aware of when a component boundary is crossed. For some operations the Framework is aware of component boundaries, for example, when calling out to BundleActivators and event listeners. Switching the context class loader when calling out to these types of objects will not solve a large number of usecases.
Consider the following example:
- Bundle W exports a package “some.foo.library”. This package contains code which uses the context class loader to load additional classes. Imagine it has some SPI like behavior where it loads classes based on some properties file similar to how javax.xml.parsers package works.
- Bundle X exports a package “some.foo.stuff”. This package contains a service interface “some.foo.stuff.BarService”.
- Bundle Y imports the “some.foo.stuff” package and registers a “BarService” implementation with the service registry.
- Bundle Y also imports the “some.foo.library” and expects the exporter to be able to load classes from bundle Y. Bundle Y uses the “some.foo.library” package in its implementation of the “BarService”.
- Bundle Z imports the “some.foo.stuff” package and gets the “BarService” from the service registry and uses it.
In this scenario imagine the framework sets the context class loader to Bundle Z’s class loader before calling its BundleActivator to start the bundle. In the BundleActivator of Z it gets the BarService if it is available and start making calls to it. At this point code in Bundle Y will get executed because it contains the implementation of the BarService. The implementation of the BarService then uses the package “some.foo.library”. This will cause the code in Bundle W to run that uses the context class loader. At this point the context class loader will be set to Bundle Z’s class loader. This class loader does not have access to the content in Bundle Y and will result in Bundle W’s library code not being able to load classes from Bundle Y.
As a work around to this issue Bundle Y could wrap all calls to code in the package “some.foo.library” with context class loader switches, but this puts a great burden on any developer using the package “some.foo.library”. This also calls into question the purpose of the Framework switching the context class loader at all (to Bundle Z’s class loader in the example above). Any time more than one component boundary is crossed the original context class loader will likely not be the one that is needed.
This design specifies a behavior for the context class loader that should help solve some of these issues.
Requirements
- The solution MUST reduce or illiminate the need for code packaged in a bundle to call Thread.setContextClassLoader while calling library code
- Library bundles MUST be able to use the context class loader to access classes needed by the library
- other reqs ...
Technical Solution
To solve the requirements this design introduces the buddy class loading and context finder concepts
Buddy Class Loading
Buddy class loading offers an integration strategy that does not require modifying the Java code of existing libraries that use the Class.forName(String) approach to dynamically discover and load classes. The mechanism works as follows:
- A Bundle declares that it needs the help of other bundles to load classes
- The Bundle identifies the kind of help they need by specifying a buddy policy. The policy defines what kind of bundles will be considered to be buddies.
- When a bundle class loader fails to find a desired class through the normal OSGi delegation model (i.e. Import-Package, Require-Bundle, and local classpath), its buddy policy is invoked
- The invoked buddy policy discovers a set of buddies and consults each one in turn until either the class is found or the list is exhausted.
Search Order
The following is a modified class/resource search order:
Frameworks must adhere to the following rules for class or resource loading. When a bundle’s class loader is requested to load a class or find a resource, the search must be performed in the following order:
- If the class or resource is in a java.* package, the request is delegated to the parent class loader; otherwise, the search continues with the next step. If the request is delegated to the parent class loader and the class or resource is not found, then the search terminates and the request fails.
- If the class or resource is from a package included in the boot delegation list (org.osgi.framework.bootdelegation), then the request is delegated to the parent class loader. If the class or resource is found there, the search ends.
- If the class or resource is in a package that is imported using Import-Package or was imported dynamically in a previous load, then the request is delegated to the exporting bundle’s class loader; otherwise the search continues with the next step. If the request is delegated to an exporting class loader and the class or resource is not found, then the search terminates and the request fails.
- If the class or resource is in a package that is imported from one or more other bundles using Require-Bundle, the request is delegated to the class loaders of the other bundles, in the order in which they are specified in this bundle’s manifest. If the class or resource is not found, then the search continues with the next step.
- The bundle’s own internal bundle class path is searched. If the class or resource is not found, then the search continues with the next step.
- Each attached fragment’s internal bundle class path is searched. The fragments are searched in ascending bundle ID order. If the class or resource is not found, then the search continues with the next step.
- If the class or resource is in a package that is exported by the bundle or the package is imported by the bundle (using Import-Package or Require-Bundle), then the search ends and the class or resource is not found.
- Otherwise, if the class or resource is in a package that is imported using DynamicImport-Package, then a dynamic import of the package is now attempted. An exporter must conform to any implied package constraints. If an appropriate exporter is found, a wire is established so that future loads of the package are handled in Step 3. If a dynamic wire is not established, then the search continues to step 10.
- If the dynamic import of the package is established, the request is delegated to the exporting bundle’s class loader. If the request is delegated to an exporting class loader and the class or resource is not found, then the search terminates and the request fails.
- If the bundle has declared a buddy policy then the request is delegated to each buddy bundle class loader until either the class or resource is found or all of the buddy bundle class loaders have been delegated too.
When delegating to another bundle class loader, the delegated request enters this algorithm at step 4 and exits at step 9. The buddy policy is not used when delegating to another bundle class loader.
Buddy Policy
A buddy policy defines a policy for selecting buddies that will be used to for buddy class loading. Currently Equinox defines a number of built-in Buddy policies. The following are the buddy policies available in Equinox
- dependent - Consults all bundles that directly or indirectly depend on the bundle. An indirect dependency can be introduced by bundles that use Require-Bundle with the visibility directive set to reexport. Note that this casts a rather wide net and may introduce performance problems as the number of bundles increase.
- registered - Consults all dependent bundles that explicitly register themselves as buddies to the bundle. This is similar to the dependent policy but scopes down the number of bundles that will be consulted as buddies.
- global - Consults the available packages exported in the global pool of exported packages.
- app - Consults the application classloader.
- ext - Consults the extension classloader.
- boot - Consults the boot classloader.
Note when using the above policies all packages available from the source buddy will be available. In the case of dependent , and registered , all packages from the bundle are available even if the package is not exported. There is no way to scope down the available packages from the buddy sources.
Eclipse-BuddyPolicy Header
The Eclipse-BuddyPolicy header allows a bundle to declare a comma-separated list of buddy loading policy names that are to be used for the bundle.
The syntax of the Eclipse-BuddyPolicy header is the following
Eclipse-BuddyPolicy ::= buddy-policy ( ',' buddy-policy )* buddy-policy ::= ('dependent' | 'registered' | 'global' | 'app' | 'ext' | 'boot')
Eclipse-RegisterBuddy
The Eclipse-RegisterBuddy header is used to declare a comma-separated list of symbolic names of bundles that this bundle should be a registered buddy to. The bundles with the specified symbolic names must use the registered buddy policy in order for this bundle to be a registered buddy.
Note that the following conditions must be met before a bundle X can become a registered buddy of another bundle Y :
- The bundle Y must specify the registered buddy policy (i.e. Eclipse-BuddyPolicy: registered)
- The bundle X must specify the symbolic name of Y in the Eclipse-RegisterBuddy header (i.e Eclipse-RegisterBuddy: Y)
- The bundle X must be dependent on a package exported by bundle Y . This can happen through either a Require-Bundle or Import-Package constraint.
The syntax of the Eclipse-RegisterBuddy header is the following:
Eclipse-RegisterBuddy ::= bundle-symbolic-name ( ',' bundle-symbolic-name )*
Context Class Loader
Since Java 1.2, the Class.forName(String) mechanism has been largely superseded by context classloading. As such, most modern class libraries use a context classloader. This section descibes how the use of a context class loader can be transparently converted into something equivalent to Class.forName(String). Doing this allows the buddy loading mechanism described above (and DynamicImport-Package) to be used to eliminate ClassNotFoundExceptions and NoClassDefFoundErrors.
Each Java Thread has an associated context classloader field that contains a classloader. The classloader in this field is set, typically by the application container, to match the context of this current execution. That is, the field contains a classloader that has access to the classes related to the current execution (e.g., Web request being processed). Libraries such as log4j access and use the context classloader with the updated AppenderHelper code pattern below:
public class AppenderHelper { private Appender createAppender(String appenderName) { ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class appenderClass = loader.loadClass(appenderName); return (Appender)appenderClass.newInstance(); } }
By default, the context classloader is set to be the normal Java application classloader. That is, the use of the context classloader in normal Java application scenarios is equivalent to using Class.forName(String) and there is only one classloader, the application classloader. When running inside the Framework, however, the code pattern outlined above fails because:
- By default, the Framework does not consult the application classloader. OSGi-based applications put their code in bundles and export particular packages instead of placing all the code on the normal Java application classpath.
- The Framework cannot detect bundle context switches and set the context classloader as required. That is, there is no way to tell when execution context shifts from one bundle to the next as is done in Web application servers.
These characteristics, combined with the compositional nature of OSGi, mean that the value of the context classloader field is seldom useful.
Clients can, however, explicitly set the context classloader before calling libraries that use the context classloader. The snippet below shows an example of calling log4j using this approach:
Thread thread = Thread.currentThread(); ClassLoader loader = thread.getContextClassLoader(); thread.setContextClassLoader(this.getClass().getClassLoader()); try { ... log4j library call that calls AppenderHelper.createAppender() ... } finally { thread.setContextClassLoader(loader); }
First the current context classloader is saved. The context classloader is then set to an appropriate value for the current execution and log4j is called. log4j’s AppenderHelper uses the context classloader, so in this case, it uses the client’s classloader (e.g., this.getClass().getClassLoader()). When the operation is finished, the original context classloader is restored.
The assumption here is that the client’s classloader is able to load all required classes. This may or may not be true. Even if it can, the coding pattern is cumbersome to use and hard to maintain for any significant number of library calls. Ideally, log4j would be able to dynamically discover the context relevant to a particular classloading operation. The 'context finder' enables this.
Context Finder
The context finder is a kind of ClassLoader that is installed by the Equinox Framework as the default context classloader. When invoked, it searches down the Java execution stack for a classloader other than the system classloader. In the AppenderHelper example above, it finds the log4j bundle’s classloader (the one that loaded AppenderHelper). The context finder then delegates the load request to the discovered classloader.
This mechanism transforms log4j’s call to getContextClassLoader().loadClass(String) to the equivalent Class.forName(String) call using log4j’s classloader to load the given class. Now the buddy classloading techniques can be applied to help log4j load the needed appender classes.
The net effect is that clients of log4j do not have to use the cumbersome coding pattern outlined above even though the libraries they call use the context classloader. This approach generalizes to other context classloading situations.
发表评论
-
字符串分割--java中String.split()用法
2013-03-06 14:25 74151在java.lang包中有String.sp ... -
用 HttpServletResponseWrapper 实现 Etag 过滤器
2012-07-09 16:58 3758原文出处:http://blog.chenlb.com/200 ... -
Fitnesse使用
2012-05-05 13:27 23494Fitnesse 的使用 一,介绍 Fitnesse是一种 ... -
Customizing the new FitNesse parser
2012-05-05 13:13 2134FitNesse began its life using ... -
java application中内嵌ActiveX控件
2011-11-14 15:57 5524我这里用的是SWT/JFace开发application,SW ... -
Google Java Developer Tools Downloads
2011-08-09 00:04 2346WindowBuilder Pro原来叫WindowB ... -
Jalita
2011-08-06 00:49 1565Jalita (Java light terminal ada ... -
【转】用Java写字符终端界面
2011-07-29 13:13 2121终端界面GUI开源项目charva。 这个框架让你可以用开发 ... -
[转]mybatis下的分页,支持所有的数据库
2011-07-21 13:21 14841大 家都知道,mybatis的自带分页方法只是逻 ... -
Java framework for text- & console-based forms?
2011-07-21 01:06 1711charva jcurses JNA , ... -
JNA(Java Native Access)学习入门
2011-07-21 01:04 22621Java Native Access 项目 在 ... -
JAVA上加密算法的实现用例
2011-06-25 12:38 4883来源:www.ibm.com ... -
如何将GlassFish作为Windows服务运行
2011-05-18 23:21 2374本文档来自GlassFish官方网站,详细介绍了将 G ... -
JAVA UDP打洞必备知识点---NAT
2011-05-05 12:56 8698一、引言 RFCl631 ... -
Keystore概念,Keytool工具使用
2011-04-28 16:20 2906近来由于项目需要做Single Sign On, 研究了一 ... -
利用Eclipse Profile Plugin监控分析Tomcat性能
2011-04-18 16:14 3702目前新版本的Eclipse在启动应用服务器的时候有一个新的选 ... -
m2eclipse: Eclipse is running in a JRE, but a JDK is required
2011-02-04 23:43 2541Eclipse 安装了Maven插件,启动Eclipse ... -
利用JNative实现Java调用动态库
2010-10-18 00:43 2099由于项目要求,需要用J ... -
RHEL5支持大内存
2010-10-08 16:19 3005安装 RHEL 5 ,硬件为 4G 内存,安装完成 ... -
Windows Server 2003 和 Windows 2000 提供大内存支持
2010-10-08 16:19 1854本文介绍物理地址扩展 ...
相关推荐
"SideBar Enhancements" 是一个针对Sublime Text编辑器的插件,主要目的是增强和扩展其默认侧边栏的功能。Sublime Text是一款流行的代码编辑器,因其轻量级、高效和高度可定制性而受到开发者喜爱。SideBar ...
SideBarEnhancements是一款针对Sublime Text 3的强大增强插件,它扩展了默认侧边栏的功能,提供了更多方便用户管理和操作文件及项目的选项。Sublime Text是一款广受欢迎的代码编辑器,以其轻量级、高性能和高度可...
SideBarEnhancements是一款针对Sublime Text 3的强大增强插件,旨在扩展其侧边栏功能,提供更加便捷的文件和项目管理。Sublime Text 3是一款广受欢迎的文本编辑器,以其高性能、丰富的自定义性和多语言支持而受到...
个人汉化的sidebarenhancements目录,大部分的文字已翻译,替换相应的文件即可。
Sublime Text3文件右键增加插件 SideBarEnhancements汉化版 下载解压后放到插件packages目录重启Sublime Text3即可 文件右键出现添加文件 添加文件夹 复制 重命名 删除等操作 上传不了图片 如这链接所示...
Emmet允许开发者使用简短的语法快速生成复杂的HTML结构,比如`div>ul>li*5`可以瞬间生成五个`<li>`元素嵌套在`<ul>`内,`div#header.class`则能创建一个带有ID和类名的`<div>`元素。这种语法大大减少了手动输入的...
Sublime Text一个小插件——SideBarEnhancements 搜索“SideBarEnhancements”,还是第一个,直接回车确认。骚等一会儿就安装成功了。 如果无法在线安装,可以尝试通过下载安装包,放到Packages目录。...
SideBarEnhancements 是 sublime IDE 的一个侧边栏增强插件 , 安装方法详见:https://blog.csdn.net/PY0312/article/details/89529640
SideBarEnhancements-st3 是专为Sublime Text3设计的一款强大插件,旨在增强原生侧边栏的功能,提供更为高效和便捷的文件管理体验。Sublime Text是一款广受欢迎的文本编辑器,以其轻量级、高度可定制化以及丰富的...
The Verilog 2001 Standard includes a number of enhancements that are targeted at simplifying designs improving designs and reducing design errors This paper details important enhancements that were ...
在这个“sublime text2 coffeescript perl SideBarEnhancements 等配置”的主题中,我们将探讨如何为Sublime Text 2配置CoffeeScript和Perl编程环境,以及如何利用SideBarEnhancements插件优化左侧树菜单。...
由于ST3现在SideBarEnhancements已经在ST2的install package菜单中找不到了 此为sublime text2的版本 解压出来的目录放到Packages下,运行SideBar.py文件即可
5G R15到R16演进及R17展望
Sublime Text 2的插件SideBarEnhancements不好找,我找了好久的哦! 现在Sublime Text 2扩展安装包里没有SideBarEnhancements插件了,只好手动安装。 -------------------------- -------------------------- ...
Web Services Enhancements (WSE) 是微软为.NET框架提供的一系列增强工具,旨在提升Web服务的安全性和功能性。WSE3.0是其中的一个版本,它着重于改进和扩展了基本的SOAP(简单对象访问协议)服务的安全性。在这个...
Positioning in CSS Layout Enhancements for the Web 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
Wi-Fi 6 Standard - Enhancements for High Efficiency WLAN.zip
BeyondCode\EloquentEnhancements\EloquentEnhancementsServiceProvider::class, ``` 为了启用特定功能,可能还需要在模型中继承相应的类或使用 traits。 3. **关联预加载优化** Eloquent Enhancements 支持预...
SAP BC425 Enhancements and Modifications
public class Person { public string Name { get; set; } public int Age { get; set; } } ``` #### 对象与集合初始化器 (Object and Collection Initializers) 对象与集合初始化器提供了一种更加直观的方式来...