Running Eclipse applications on Windows 8
Reading the title, you might ask why this could be a problem. Good news: in most cases it isn’t. However it can be problem if you use native code in your Eclipse plug-in and run on an older version of Equinox (3.7.2 and earlier). This post describes the problem and possible solutions.
On older Windows versions, our Eclipse RCP/RAP application works fine. On Windows 8 however, the application does not start because one bundle is not resolved and results in the following error message:
!MESSAGE Missing host Bundle-NativeCode_0.0.0.
The problematic bundle references native libraries. There are different native libraries for different operating systems. OSGi defines a way to declare those dependencies, and makes sure that the right library is loaded, depending on the current operating system. According to the OSGi specification, we used the
Bundle-NativeCode header in the
Bundle-NativeCode: helper.dylib; osname=macosx, helper.dll; osname=win32, helper.so; osname=linux
The expected behavior on any Windows version is that OSGi would try to load the
helper.dll. This does not however, work on Windows 8.
When OSGi is trying to resolve the bundle, it is searching for a library whose condition is fulfilled, i.e. at least one of the conditions must evaluate to
true. The message above actually means that OSGi could not find a matching condition and therefore does not resolve the bundle.
As a condition, we have here the
osname property. Its value is compared with the value of the system property
org.osgi.framework.os.name which is usually filled by the Java VM. What makes things more complicated is the fact that Java might return different values for the same operating system. All (currently) known values are listed on this wiki page. Equinox solves the problem of multiple possible values with a mapping table which is maintained in file
org/eclipse/osgi/framework/internal/core/osname.aliases of the bundle
org.eclipse.osgi. As an example, for Windows 7 the row in the mapping table looks like this:
Windows7 "Windows 7" Win7 Win32 # Microsoft
This entry makes sure that a condition
osname=Win32 even resolves if Java reports
Windows7 as the operating system name.
The reason why this mechanism fails with our application is simple. We are using an old version of Equinox (3.7.2) whose mapping table does not contain a row for Windows 8 because it was not released at that time and it was not possible to anticipate which values the Java VM would provide. BTW, the row was introduced with the Juno release (3.8).
Basically there are three possible solutions:
- Upgrade to a newer Equinox version: probably the best solution. However, it is not a trivial change and is only possible if you can change the application.
- Add conditions to the manifest:
Bundle-NativeCode: helper.dylib; osname=macosx, helper.dll; osname=win32; osname=Windows8; osname=Windows 8; osname=Win8, helper.so; osname=linux
This change is much smaller and less intrusive, but quite ugly, and you still need to be able to change the application.
- Manipulate the system property: start your Java VM with the system property
There is no need to change the application here, but you might compromise code which relies on the original OS name coming from the Java VM.
Problem solved, case closed – until Windows Blue comes out.