- 浏览: 115055 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
stringsdn:
不懂 你在加载前判断没有404 到加载后是404怎么半
Android WebView处理404等错误 -
zxjlwt:
学习了。http://surenpi.com
如何在console中加入文件连接 -
endison1111:
碰到了同样的问题,使用多页面MultiPage后,切换标签ou ...
Eclipse Multipage Page编辑器同步实践——OutlinePage -
Just2005:
已解决。谢谢。
GMF中控制Figure的大小和位置 -
Just2005:
源码呢 ?
GMF中控制Figure的大小和位置
原文地址:http://www.eclipsezone.com/articles/eclipse-vms/
When starting off with Eclipse plugin development or rich client
platform development, you're more than likely to run into issues like ClassNotFoundException
or problems with the Java command line and properties like java.endorsed.dirs
.
Most often, these problems arise because many Eclipse developers don't realise the magic that lets Eclipse do its work. Amongst these are the fact that there's actually two processes under the covers, and that each bundle has its own classloader. Once you understand how these fit together, debugging problems may be somewhat easier.
Eclipse Boot Process
Why does Eclipse need two processes to run? The simple answer is
that an Eclipse application needs to be run with several system
properties set in order to function properly. (These include parameters
like osgi.configuration.area
and osgi.instance.area
.)
It's a key requirement in the way that Eclipse starts up, because it
needs to know where to put both temporary and persistent data that's
not stored directly in one of your project locations. (Examples include
your preferences and the workbench history, which tracks changes to
files that you have made.)
Many other tools use a shell script to
launch an application with a particular classpath; not only IDEs (like
NetBeans) but also server-side tools (Maven, Ant, CruiseControl ...).
Most of the time, these shell scripts use shell-specific routines to
add entries to a classpath (e.g. for i in lib/*.jar
), and
on the whole, this approach works. But some operating systems aren't as
expressive as others, and unless you have the ability to add other
complex logic to the script via external programs, it may not be
possible to do everything that you'd want. It also means that you
potentially have to test the shell script on other operating systems to
determine whether it's correct or not; though generally if it works on
one Unix system, it will work on others too.
To solve this issue (and others), Eclipse doesn't use a shell script
to boot itself. Instead, it uses a native executable (eclipse.exe
or eclipse
), to parse the command-line arguments (like -vmargs
)
and make them available to the OSGi platform. Importantly, it
calculates defaults for values that aren't overridden. It then fires up
the OSGi platform in a new process
(the platform VM), and
hands the rest of the booting process over.
You
may wonder why it fires up a new process, rather than continuing
booting by incorporating a VM in the same one. There's two reasons for
this: firstly, the OSGi platform that's being launched can call System.exit()
without taking down the launcher (c.f. the JavaDoc task in Ant, or the
fork attribute of the Java task).
The second (perhaps more important) one is that it allows the OSGi
platform to be launched with a different set of parameters -- or even
use a specfic version of the VM. The launcher can run on many versions
of the Java VM, and the launcher can guarantee that your platform code
will run in a known VM (for example, by shipping one with your code and
placing it in the jre/
directory).
The launcher also reads a variety of configuration files; eclipse.ini
,
if present, is a newline separated list of flags that are passed into
the platform VM. The -vmargs
flag is used to pass any
subsequent arguments as VM arguments rather than normal arguments.
All of this means that when launching Eclipse via startup.jar
the arguments and extra options are effectively ignored by the actual
Eclipse runtime instance. You may think that:
eclipse -Xmx1024m
would give you a huge Eclipse memory runtime, but in actual
fact, all you're doing is specifying an argument which is ignored by
the eclipse
launcher. The native launcher deals with some
arguments directly; but otherwise, they're passed on verbatim to the
Java launcher org.eclipse.core.launcher.Main
where the
real work is done. The arguments that the native launcher explicitly
deals with are:
C:\Program
Files\Eclipse
in them. This is available from the eclipse.vmargs
system property, but it cannot be changed once the VM is started.eclipse.vm
system property, but it cannot be
changed once the VM is started.To run Eclipse with a larger memory area, you need to pass the -vmargs
to the launcher, followed by the options that you want:
eclipse arg1 arg2 arg3 -vmargs -Xmx1024m
this instructs the launcher to create the platform VM, passing in
arguments arg1 arg2 arg3
and setting up the platform VM with -Xmx1024m
.
However, we could equally have had a file called eclipse.ini
:
arg1 arg2 arg3 -vmargs -Xmx1024m
which would have the same effect. The launcher looks for application.ini
and eclipse.ini
to derive these parameters, if your
executable is called application.exe
.
The eclipse
launcher then fires up a VM, which uses org.eclipse.core.launcher.Main
(from startup.jar
) to instigate the next phase of the
boot process. The Main
launcher sets up specific areas that are needed by the OSGi platform,
including setting up the properties such as where the configuration
area will be. It then boots the OSGi
platform, which
reads which plugins to start from the osgi.bundles
entry
from the config.ini
, and applies product branding from -product
and OS/Language specific settings from -os
and -nl
.
Once that's running, the Eclipse platform task over which locates and
loads the bundle associated with the -application
or -feature
arguments. Certain plugins (like org.eclipse.core.resources
)
interpret specific command line arguments (like -refresh
),
but this is the exception rather than the rule.
If you want to embed Eclipse into another Java process, you can use
the EclipseStarter
class, as long as you supply the appropriate entries. That will fire up
all the necessary plugin support to kick your application off. There's
also WebStartMain
that can
be used to kick off an Eclipse install via Java WebStart (although with
some limitations
).
There's a full list of the arguments and when they are interpreted in the Eclipse help pages under "runtime options ", and can be summarised as:
|
|
|
|
ClassLoaders, Bundles and Buddies
You may recall that Java uses a ClassLoader
to bring
classes into the VM. Most of the time, you probably don't need to know
anything about how they work (or even that they exist) but every class
in Java is loaded via a ClassLoader
. Its job is to turn a
sequence of bytes into a java.lang.Class
. Where those
bytes come from doesn't really matter; and it's this fact (and the URLClassLoader
)
that brought Java to fame with Applets in the first place. Mostly,
client side applications don't need to worry about the ClassLoader
:
they just set up a classpath
and It Just Works.
Server-side applications (J2EE servers and others like Tomcat) have
long used ClassLoader
s
to enable classes to be loaded on demand from different structures
(like WAR formats). As well as providing a way of accessing the
classes, the ClassLoader
also provides another key
benefit; it separates out classes with the same name. Every class in
Java has an associated ClassLoader
(and you can find out
which by obj.getClass().getClassLoader()
if you want).
Importantly, a class name is unique only within its ClassLoader
.
That means it's possible to have two classes with the same name loaded
into a VM at once, provided that they have two separate ClassLoader
s
that loaded them. Whilst this may sound freaky and unnatural, in fact
it's how application servers like Tomcat can host any Web application
and allow hot deployment. It simply creates a new ClassLoader
,
loads in the classes (again) and runs the new version. Without this
ability, an application server would not be able to reload a web
application without having to restart the server in its entirety.
Eclipse uses this to its advantage. One of the key features of Eclipse 3.0 was the ability to stop and start a bundle whilst the platform continued running. (It's used when you update, and choose the 'Apply changes now' instead of restarting Eclipse, amongst other things.) Perhaps more importantly, Eclipse allows multiple different versions of a bundle to be loaded at one time, which might be useful if you have many parts of your plugin relying either on 2.7.1 or 2.8.0 of Xerces.
To do this, each bundle (OSGi) or plugin (Eclipse) has its own ClassLoader
.
When a bundle is started, it gets given its own ClassLoader
for its lifetime. When it's stopped and restarted, a new ClassLoader
is created. This allows the new bundle to have a different set of
classes than the previous version.
The OSGi platform translates the Manifest.MF
present
in every (OSGi-enabled) plugin into a hierarchy of ClassLoader
s.
When you can't load a class from your plugin directly, the bundle
mechanism searches through all the required bundles to see if it can
find the class there instead. Packages that depend on the same bundles
(e.g. org.eclipse.ui
) will result in the same class being
loaded, because it comes from org.eclipse.ui
's ClassLoader
.
This causes confusion for new developers to the Eclipse platform. It
doesn't matter what's in the CLASSPATH
environment
variable, or what's specified on the -classpath
argument,
because pretty much every ClassLoader
only sees what its Manifest.MF
tells it to see. If there's no dependency at the bundle level, then as
far as Eclipse is concerned, it isn't there. (Incidentally, that's how
the .internal.
packages work; whilst they exist in the
bundles, and can be loaded by the bundle's ClassLoader
,
the Eclipse class loading mechanism hides any package that's not
explicitly mentioned in the Export-Package
header in the Manifest.MF
.
It also doesn't help that the PDE runtime only consults the entries in
the .classpath
when running/debugging inside Eclipse, and
it's only when you try to export the product that the Manifest.MF
is consulted, often resulting in errors. A ClassNotFoundException
during product/plugin exporting is almost always down to the fact that
it's mentioned in the .classpath
(Java Build path) but
not the Manifest.MF
.
A
larger problem occurs when using libraries that expect to be able to
see your code as well as their own. This includes libraries such as log4j
and generator tools such as JibX
that both supply
services and consume code. Because Eclipse uses a partitioned class
loading mechanism, the ClassLoader
of the org.apache.log4j
can't see the classes defined in org.example.myplugin
,
since it's a separate ClassLoader
. As a result, log4j
can't use your supplied class for logging, and complains.
This is the purpose of the buddy class loading
in Eclipse. It is designed to work around the issues that can be found
in this type of problem. (It's quite similar to the options that you
can configure with some of the application servers, such as "parent
first" and "child first" lookup policies.) The buddy policy (specified
with the Eclipse-BuddyPolicy
entry) takes one of:
Export-Package
Figure 1. Buddy classloader diagram
|
Whilst all of these are generally fine, if you want to use a tool
like log4j
then it generally boils down to:
# log4j Manifest.MF Bundle-Name: org.apache.log4j Bundle-Version: 1.2.13 ... Eclipse-BuddyPolicy: registered
This says "If anyone registers with me, and I need to find a class that I can't otherwise find, I'll check with them before failing". You also need to define in your own plugin that you want to register with it:
# myplugin Manifest.MF Bundle-Name: org.example.myplugin Bundle-Version: 1.0.0 Requires-Bundle: org.apache.log4j,... ... Eclipse-RegisterBuddy: org.apache.log4j
This now makes the org.apache.log4j
and org.example.myplugin
buddies. Of course, our org.example.myplugin
always
depended on org.apache.log4j
before, but now we've added
the extra hook back that allows the log4j
to see our
classes as well. In essence, it's like adding Requires-Bundle:
org.example.myplugin
to the org.apache.log4j
bundle, except that obviously you can't do that (it would create a
circular reference) and I doubt that Ceki G?lc? would have had the
foresight to depend on myplugin in advance. But by putting Eclipse-BuddyPolicy:
registered
into the definition, now any future bundle can plug
in and register its code with org.apache.log4j
.
It's probably a pretty good idea to add the Eclipse-BuddyPolicy:
registered
to your plugin now, because in the future someone
might need it.
Native code and classloaders
As well as resolving classes, the ClassLoader
is also
responsible for finding native code in response to a System.loadLibrary()
call. Whilst it doesn't actually perform the loading of the DLL itself,
it does figure out where the DLL is and passes a full path to the
operating system to install the code. In the case of packed OSGi
bundles, this call automatically extracts a copy of the DLL to a
temporary location before passing the location back to the OS.
It's
also worth bearing in mind that the DLL loaded may have other
dependencies. Unfortunately, although Eclipse knows where to look for
further dependencies (e.g. the java.library.path
or the
contents of a packed Jar file), once the operating system only knows
about the PATH
or LD_LIBRARY_PATH
environment variables (depending on your operating system). So if you
have a.dll
which depends on b.dll
, and you
do System.loadLibrary("a")
, it will fail with an UnsatisfiedLinkError
.
That's because although Eclipse knows where to find the dependent dll,
the operating system doesn't know where to look for b.dll
and gives up. Instead, if you did System.loadLibrary("b");
System.loadLibrary("a");
then the DLL is available in memory for
a.dll
to trivially hook up against, and it all works. The moral of the story
is always load the DLLs in the order in which they are dependent.
It's
worth bearing in mind that Windows and Java have some issues when it
comes to loading DLLs. A DLL can only be loaded once in a VM and only
associated with one ClassLoader
. If you have two ClassLoader
s,
and they attempt to load the same DLL, then the second one will fail
and not be able to execute any native code. As a result of this, you
cannot have two bundles that attempt to load the same native code in
Eclipse. This will also apply if the bundle is updated or restarted,
because the old ClassLoader
may retain a reference to the
DLL whilst the new one starts. This is a Windows-specific problem that
doesn't appear to manifest itself on other operating systems.
Lastly, whilst Eclipse 2.1 used a combination of directories (ws/os/arch
,
such as win32/win32/x86/swt1234.dll
)
for storing native code, this is no longer the preferred way of doing
it. Instead, native code should be at the root level of the plugin,
probably with a suffix like swt1234-win32x86.dll. Even better, instead
of doing System.loadLibrary()
, you can define Bundle-NativeCode:
swt1234.dll
and the OSGi platform will load it automatically. You can either
provide per-os fragments, or split them apart and use a platform filter
(such as Eclipse-PlatformFilter: (& (osgi.ws=win32)
(osgi.os=win32) (osgi.arch=x86))
).
Conclusion
Once you understand how the processes work within the Eclipse boot
sequence, and the fact that it utilises many classloaders, some of the ClassNotFoundException
s
become easier to understand. Specifying arguments works on a command
line java
invocation because you're specifying the VM on
the command line (and most of the time, only using one ClassLoader
too). In the Eclipse world, if you want to affect Eclipse's VM, you
need to remember to prefix any arguments with -vmargs
,
either on the command line or on via the eclipse.ini
file.
It's also worth checking when you have ClassNotFoundException
s
when exporting or running an application outside of Eclipse's debugger,
that you have the dependencies listed in Manifest.MF
and
not just in the .classpath
(Java Build Path). In fact,
you shouldn't need to put any extra entries in the .classpath
if you're building a plugin project, because the entries in Manifest.MF
are automatically available in the .classpath
through the
"Plugin Dependencies" classpath container.
Lastly, if you're using native code in an Eclipse application, it's a very good idea to isolate the native code in its own bundle. Any plugin that needs to use that native functionality can then express a dependency on that bundle, which allows it to be shared by as many bundles as need it. That way, if you have any non-native updates to your bundle, you don't need to restart Eclipse to see those changes. Of course, if you have native bundle updates then you have to restart anyway to get the benefit.
发表评论
-
向console中加入文件链接
2010-01-24 22:11 883之前写过一篇文章大概讲了向console中加入文件链接的原理, ... -
如何在console中加入文件连接
2010-01-17 10:59 957使用eclipse的人都知道,在console中打印的异常st ... -
Eclipse Multipage Page编辑器同步实践——PropertyPage
2009-12-20 17:08 1521在MultipageEditor应用中属性页(Property ... -
Eclipse Multipage Page编辑器同步实践——OutlinePage
2009-12-13 14:30 2138最近做个IDE的项目,要将文本编辑器和机遇gef的图形编辑器集 ... -
Run configure方式运行RCP与导出后运行RCP的差异
2009-11-22 21:21 1201前几天开发RCP应用过程中遇到了一个问题(其实也是经常遇到的问 ... -
启用EMF的自动生成UUID功能
2009-11-16 21:54 924原文:http://www.cnblogs.com/bjzha ... -
eclipse对于View的操作
2009-11-11 22:10 1575几个常用的关于View的操作: 1. findView I ... -
emf开发笔记
2009-11-07 11:17 1054原文:http://macrochen.iteye ... -
Draw2D 教程(四)(五)(六)
2009-11-01 15:25 1810原文: http://dev.csdn.net/autho ... -
Draw2D 教程(三)
2009-11-01 15:22 1926原文:http://dev.csdn.net/au ... -
Draw2D教程(二)
2009-11-01 15:21 2996原文:http://dev.csdn.net/aut ... -
Draw2d 教程(一)
2009-11-01 15:19 1555原文:http://dev.csdn.net/aut ... -
Eclipse应用如何获得runtime project的路径
2009-10-29 15:01 1366最近基于gef/emf开发一个图形化工具,用于设计手机屏幕。在 ... -
SWT中嵌入Swing
2009-07-20 15:15 2679原文地址:http://blog.sina.com.cn/s/ ... -
给eclipse viewer增加拖拽支持
2009-07-19 19:48 4262在jface中的viewer体系中(顶层抽象类org.ecli ... -
Eclipse开发中使用资源文件
2009-07-13 09:28 727在开发eclipse插件时,经常用到一些字符串常量,比如定义菜 ... -
eclipse中如何打开一个编辑器
2008-11-25 21:21 2129eclipse中打开一个编辑器要调用 IWorkbenchPa ... -
发现一个jet2的bug
2008-01-30 21:30 878最近在做一个代码生成 ... -
jet2的一些学习笔记(1)
2008-02-15 21:40 924jet的input model和模板集合的关系好比语言和co ... -
自己订制gmf中属性编辑器
2006-04-24 13:37 758在gmf中属性页的支持是由PropertyProvider完成 ...
相关推荐
A Tale of Two Systems, is one of the best, synthesizing Lean manufacturing and product development with agile software concepts in an engaging business novel.
【英文】德银报告:中国电子商务报告China E-commerce:A tale of two camps - and we favor the(72页),资源名称:【英文】德银报告:中国电子商务报告China E-commerce:A tale of two camps - and we favor the...
《OverSave-Tale 0.23.1.rar》是一个压缩包文件,它包含了与“OverSave-Tale”游戏相关的更新版本,版本号为0.23.1。"whm"、"fdy"和"oversave-table"是描述中的关键词,它们可能是游戏内的特定术语或功能模块。在...
信息安全_数据安全_Ransomware A Tale of Two CISOs 安全测试 大数据 企业安全 信息安全 企业安全
基于java的开发源码-Tale Java博客系统.zip 基于java的开发源码-Tale Java博客系统.zip 基于java的开发源码-Tale Java博客系统.zip 基于java的开发源码-Tale Java博客系统.zip 基于java的开发源码-Tale Java博客系统...
结合以上信息,我们可以推测“Tale of Hawk”是一个围绕Windows系统的项目,它可能包括一个独特的视觉设计(Tale-of-Hawks.png),一套定制的字体(Tale of Hawks.ttf),并且在法律合规性上做足了功课(License ...
《双城记》读后感 查尔斯·狄更斯是英国文学史上一颗璀璨的巨星,他的作品以其深刻的现实主义和丰富的想象力闻名于世。《双城记》作为狄更斯的代表作之一,不仅以其跌宕起伏的情节和鲜明的人物形象吸引了无数读者,...
Weil-étale同调是代数几何领域中的一个重要概念,它在理解算术几何对象的性质时扮演了核心角色。这个理论是由Alexander Grothendieck及其合作者发展起来的,作为étale同调的一个扩展,以解决Weil猜想等基本问题。...
Two两个直播的故事:prince_medium-dark_skin_tone: 关于性别不平等,什么是变焦放大学士教给我们的 最初是 和( 。 这也在Medium上。 去年夏天,我们正在寻找十二位女士争夺直播,以争夺总部位于旧金山的投资者...
人工智能技术的飞速发展,尤其在机器翻译领域取得了显著进步。机器翻译,作为人工智能的一个分支,其发展主要分为三个阶段。首先是基于规则的机器翻译,其次是基于语料库的机器翻译,最后是基于神经网络的机器翻译。...
A_Tale_of_two_Data_Sheets_WP
4. 唯品会作为GARP股票:GARP(Growth at a Reasonable Price,合理价格下的成长性股票)意味着公司可以以合理的价格提供良好的增长潜力。报告中提到,唯品会作为GARP股票是被看好的。 5. 对京东的评级为持有:相...
At the very beginning of his book on i, the square root of minus one, Paul Nahin warns his readers: "An Imaginary Tale has a very strong historical component to it, but that does not mean it is a ...
Google开源的JavaScript引擎V8的新一代解释器Turbo的文档介绍说明
《两种定位技术的故事:为低端手机实现精确的低开销WiFi定位》 在现代科技的浪潮中,室内定位已经成为智能手机用户的重要需求。WiFi指纹定位作为主流的室内定位技术之一,其准确性得到了广泛认可。...
提及的几个案例:“The attack of the curious child”,“Tale of the mischievous neighbor”,和“a case of talking televisions”,这些都暗示了智能语音助手可能被恶意利用的情况,比如儿童的好奇心、邻居的...
两个绑定的故事本自述文件概述了与此Ember应用程序进行协作的细节。 此应用程序的简短介绍可以轻松地转到此处。先决条件您需要在计算机上正确安装以下物品。 (带有NPM)安装git clone 此存储库切换到新目录npm ...
【标题】基于Java的源码-博客系统Tale 【描述】Tale是一个简洁而强大的开源博客系统,它采用Java编程语言开发,旨在为个人用户提供轻量级、易部署的博客解决方案。Tale的设计理念是简约至上,注重用户体验,同时在...
行尸走肉:Telltale权威系列游戏摘要 这是一个插图故事,其中包含由罗伯特·柯克曼(Robert Kirkman)编写的《行尸走肉:The Telltale Definitive Series PC》游戏的幻灯片图像 --- 注意事项 滚动被禁用 使用按钮...
【标题】基于Java的开发源码-博客系统Tale 【描述】Tale是一个轻量级的开源博客系统,它采用Java语言编写,为个人或小型团队提供了简单易用、功能丰富的博客搭建方案。这个压缩包包含的是Tale博客系统的全部源代码...