Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Equinox » Classloading differences between eclipse and standalone Equinox
Classloading differences between eclipse and standalone Equinox [message #98271] Tue, 25 September 2007 18:56 Go to next message
Michael Furtak is currently offline Michael FurtakFriend
Messages: 5
Registered: July 2009
Junior Member
I have been developing some Equinox powered code using Eclipse. This code uses Swing heavily. Recently, I've been putting together an external deployment shell so that the application can be run without Eclipse. I am running into some problems with code that works when run through Eclipse, but not when run standalone with Equinox.

Just to clarify, when running standalone with Equinox, I mean invoking <i>java -jar org.eclipse.osgi_3.3.0.v20070530.jar</i> with the appropriate <i>config.ini</i> on hand.

Here's a short example that illustrates my problems:

First, I have some third party library that does some Swing specific stuff. This is packaged into a standard Java JAR called <b>third-party.jar</b>.

package com.cra.example;

import javax.swing.UIManager;

import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;


public class ThirdPartyLib
{
  public static boolean isWindowsLAF()
  {
    return UIManager.getLookAndFeel() instanceof WindowsLookAndFeel;
  }
}


I also have an Eclipse plug-in project targeted for Equinox with the following activator and manifest file:

package com.cra.example;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator
{
  public void start(BundleContext context) throws Exception
  {
    System.out.println(ThirdPartyLib.isWindowsLAF());
  }

  public void stop(BundleContext context) throws Exception
  {
  }
}


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Problem_plug_in Plug-in
Bundle-SymbolicName: problem_plug_in
Bundle-Version: 1.0.0
Bundle-ClassPath: lib/third-party.jar,
 .
Bundle-Activator: com.cra.example.Activator
Import-Package: org.osgi.framework;version="1.4.0"



Eclipse will run this plugin with no problem and print <b>false</b> on the console. When run with Equinox from the command line, it will die with the following cause:

Caused by: java.lang.NoClassDefFoundError: javax/swing/UIManager
	at com.cra.example.ThirdPartyLib.isWindowsLAF(ThirdPartyLib.java:17)
	at com.cra.example.Activator.start(Activator.java:17)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$2.run(BundleContextImpl.java:999)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:993)
	... 10 more


Ok, so that package can't be found. When I add javax.swing to the imports, the Eclipse run still works, but the command line method fails again with a different class - this time over the WindowsLookAndFeel.

Caused by: java.lang.NoClassDefFoundError: com/sun/java/swing/plaf/windows/WindowsLookAndFeel
	at com.cra.example.ThirdPartyLib.isWindowsLAF(ThirdPartyLib.java:17)
	at com.cra.example.Activator.start(Activator.java:17)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$2.run(BundleContextImpl.java:999)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:993)
	... 10 more


Hmm.. now I've hit a snag, because I can't import that package through the Eclipse PDE. I try adding DynamicImport-Package: * to the manifest file, but that does not help. What does seem to help, though, is adding the following to my config.ini file:

org.osgi.framework.bootdelegation=*


From the Eclipse documentation:
"To revert back to the behavior in 3.2 the configuration property "org.osgi.framework.bootdelegation=*" can be added to the config.ini file."
"In 3.2 the boot (parent) class loader is always delegated to first. This provides no isolation from the classes provided by the VM. It also affects performance because the boot class loader must be delegated to for every load even though it is known that the class or resource is located in a bundle."

So, my question is this: What is Eclipse doing differently than the standalone Equinox? Both are running from the same copy of the framework JAR file (that ships with Eclipse 3.3). The bootdelegation trick fixes my problem, but I don't like the idea of introducing the performance penalty if it's not necessary.

Any help would be appreciated. Thanks,
-Mike
Re: Classloading differences between eclipse and standalone Equinox [message #98289 is a reply to message #98271] Wed, 26 September 2007 03:02 Go to previous messageGo to next message
Thomas Watson is currently offline Thomas WatsonFriend
Messages: 503
Registered: July 2009
Senior Member
Hi Mike,

Unfortunately equinox only knows about spec'ed packages from the JRE for
a given JSE level. These spec'ed packages are automatically exported by
the Equinox system.bundle depending on the execution environment level
you are at (e.g. J2SE-1.3, J2SE-1.4 etc.) The package
com.sun.java.swing.plaf.windows is specific to the VM you are running
and may not exist on other VMs at the same execution environment level.
Because of this equinox does not automatically export this package for
consumption by the bundles. When running in the stand-alone launch
(i.e. java -jar org.eclipse.osgi ...) the framework is configured to use
a "strict" OSGi parent delegation model. This means you do not get
anything for free from the VM, you must make specific OSGi constraints
(e.g. Import-Package: com.sun...).

When using the eclipse native launcher or when launching eclipse from a
development environment we use a backwards compatibility option
osgi.compatibility.bootdelegation=true. This is a bit different than
setting org.osgi.framework.bootdelegation=* because it uses a
parent-last delegation instead of parent-first. This allows for us to
provide a level of backwards compatibility WRT to getting this "for
free" from the boot classpath but also allowing bundles to provide their
own implementations of packages from the boot classpath (outside the
java.* namespace). This is why your example works in that env.

Now how to solve your issue in a "standard" OSGi way that will work
across all R4 OSGi complaint implementations? You need to get the
system.bundle to export the additional packages that you require from
the specific VM you are using. I usually recommend you use a
system.bundle fragment to add the export to the system.bundle. This
fragment is really just a shell bundle that has no code, it is only
inserting additional metadata, in the form of an Export-Package
statement, to the system.bundle to export an additional package from the
VM in your particular environment. This fragment bundle manifest would
look something like this:

Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.sun.javax.stuff
Bundle-Version: 1.0.0
Fragment-Host: system.bundle
Export-Package: com.sun.java.swing.plaf.windows

The important parts are the Fragment-Host which attaches this fragment
to the framework's system.bundle and Export-Package which tells the
framework what additional packages should be exported by the system
bundle. This should allow you to Import the
com.sun.java.swing.plaf.windows package an both development time in PDE
and at runtime in a standard OSGi R4 framework (like equinox).

HTH.

Tom.
Re: Classloading differences between eclipse and standalone Equinox [message #98333 is a reply to message #98289] Wed, 26 September 2007 19:33 Go to previous message
Michael Furtak is currently offline Michael FurtakFriend
Messages: 5
Registered: July 2009
Junior Member
Hi Tom,

Thank you very much for your explanation of the differences in the boot classloading processes. That made things much clearer.

I have tried the various options you mentioned...

osgi.compatibility.bootdelegation=true in my config.ini does not seem to work (where org.osgi.framework.bootdelegation=* did), but including it as a VM arg at launch (-Dosgi.compatibility.bootdelegation=true) worked as stated.

Since I expect developers to be creating and debugging plugins for my system through Eclipse for Equinox, I will probably leave it at that, so that they have a consistent experience in development and deployment. Just to be 100% clear, though, that flag is Equinox only (not part of the OSGi spec,) right?

Still, I checked out the other solution as well...

The Fragment approach worked, but requires some extra work, because it seems that the Eclipse PDE will not allow you to specify Export-Package for packages not on the bundle classpath. (e.g. com.sun.java.swing.plaf.windows) Since it's treated as an error, you can't build the JAR with the Export utility, making for some manual JAR construction. Is this known/intended behavior?

Thanks,
-Mike
Previous Topic:Tracking of multiple services
Next Topic:Can a dependent bundle trigger activation of a bundle it depends on?
Goto Forum:
  


Current Time: Fri Apr 26 19:02:16 GMT 2024

Powered by FUDForum. Page generated in 0.03743 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top