On 1/2/11 20:03, Bjorn Roche wrote:

On Dec 31, 2010, at 12:26 PM, Richard S. Hall wrote:

On 12/31/10 11:28, Bjorn Roche wrote:
On Dec 30, 2010, at 2:51 PM, Richard S. Hall wrote:

On 12/30/10 14:41, Bjorn Roche wrote:

On Dec 28, 2010, at 4:54 PM, Richard S. Hall wrote:

On 12/28/10 13:58, Bjorn Roche wrote:

On Dec 28, 2010, at 12:24 PM, Richard S. Hall wrote:

That's gotten me some distance. The app actually launches to a point. I'm still having two problems, though:

A. My app won't load any JNI stuff no matter what I do.
B. Putting that aside, I get this error:

Caused by: java.lang.NoClassDefFoundError: com/apple/eawt/ApplicationListener

I don't know about this either. There are some issues with Java and the Mac Java GUI implementation, something about needing to use the right thread or something. Maybe it is related...

Hmmm, well I'd love to know what that is exactly, otherwise I may be SOL. In the meantime, I will try the "exploded bundle" thing and see if that works any better.

Yeah, maybe someone else knows more.

-> richard


Okay, so I tried your suggestion of building using the exploded bundle. It works about as well as the "assembly:" and "wrap:" trick, and both techniques seem to have their pros and cons. I got stuck at the same point: java.lang.NoClassDefFoundError: com/apple/eawt/ApplicationListener

To belabor the point, here's the code that failed:

      if (os == MAC_OS_X) {
          try {
Class<?> osxAdapter = ResourceUtil.getClass(app,"xowave.util.OSXAdapter");
              Class<?>[] defArgs = { OSXApp.class };
Constructor<?> constructor = osxAdapter.getConstructor(defArgs);
              if (constructor != null) {
                  Object[] args = { app };
                  constructor.newInstance(args);
              }
          } catch (Exception e) {
              ...
          }


Now xowave.util.OSXAdapter implements com.apple.eawt.ApplicationListener, which is only available on mac OS X, so if the class were loaded directly, it would cause class-loading problems on non-OSX platforms, so I added the dynamic loading code. (I don't recall if this is exactly the approach recommended by apple, but something like it.)

And your bundle imports the "xowave.util" package?

xowave.util is part of the bundle.

Does the mentioned class have a direct dependency on com.apple.eawt.ApplicationListener? If so, is the bundle importing that package?


I was able to get around this by following Richard's hunch: I simply by putting the above code in the swing thread with a call to SwingUtilities.invokeLater().

This strikes me as a bug in OSGi because I should not need to be in a particular thread to implement an interface no matter what the interface is.

I don't know if this is the issue, but if it is, the way I understood it, it is a limitation of the Mac implementation of AWT or something.

It works fine outside of OSGi.

That's doesn't mean that it isn't a Mac implementation issue. I'm not saying it is or it isn't, though. Here is one example:

   http://www.eclipsezone.com/eclipse/forums/m92141277.html


I am still stuck loading native code, though. I added this to my MANIFEST.MF:

Bundle-NativeCode: native/libXOengine-DOUBLE.jnilib ; native/libXOengine-FLOAT.jnilib ; native/libquaqua.jnilib ;
 processor=x86 ;
 processor=ppc ;
 osname=mac os x

where the paths are relative to my bundle. I have some indication that this is correct because if I deliberately type change something I get

Native library does not exist
or
No matching native libraries found.

but when my code calls

System.loadLibrary( "XOengine-FLOAT" );

I get

Caused by: java.lang.UnsatisfiedLinkError: no XOengine-FLOAT in java.library.path

Not sure. It should work. If you can create a simple bundle that fails, I can try it, since I work on a Mac. Send it to me privately.

If I can reproduce on a small scale, I will, thank you. In the meantime, I just noticed I am getting this, apparently from felix:

ERROR: Unable to create library directory.

What's more, System.load() works, where System.loadLibrary fails.

Some googling suggested that the install name of the library might be the issue, but I mucked with that without any luck.

Well, it should work. Let me know.


It's my understanding that java.library.path is not used -- at least directly -- during normal Felix/OSGi operation, but I thought I'd see what its value was right before calling System.loadLibrary to get a hint. When I run my code outside of OSGi I get:

.:/Users/bjorn/Library/Java/Extensions:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

which seams reasonable. I use -Djava.library.path to set it to just the path I care about with my native libs so that they will load, and that's always worked.

Inside felix/OSGi, the same line of code gives:

:/usr/local/ImageMagick-6.3.9//lib:.:/Users/bjorn/Library/Java/Extensions:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

which seemed whack, at least the part before the what I get out of OSGi. It turned out my .profile was setting that ImageMagick line, and, moreover, it was totally bogus:

.profile:MAGICK_HOME="/usr/local/ImageMagick-6.3.9/" ; export MAGICK_HOME
arigato:~ bjorn$ grep MAGICK_HOME .*
.profile:MAGICK_HOME="/usr/local/ImageMagick-6.3.9/" ; export MAGICK_HOME
.profile:#MAGICK_HOME="/usr/local/" ; export MAGICK_HOME
.profile:PATH="$PATH:$MAGICK_HOME/bin:":~/bin: ; export PATH
.profile:DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$MAGICK_HOME/lib" ; export DYLD_LIBRARY_PATH

arigato:~ bjorn$ ls /usr/local/ImageMagick-6.3.9/
ls: /usr/local/ImageMagick-6.3.9/: No such file or directory

Once I removed that (I think this was from a failed gallery remote install) and restarted my shell I got something reasonable out of java.library.path, even inside OSGi:

.:/Users/bjorn/Library/Java/Extensions:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

Once that's fixed, I get a slightly different error when I run my app:

ERROR: Extracting native library. (java.io.FileNotFoundException: ./felix-cache/bundle3/version0.0/xowave-lib/0/native/libXOengine-FLOAT.jnilib (No such file or directory)) java.io.FileNotFoundException: ./felix-cache/bundle3/version0.0/xowave-lib/0/native/libXOengine-FLOAT.jnilib (No such file or directory) java.io.FileNotFoundException: ./felix-cache/bundle3/version0.0/xowave-lib/0/native/libXOengine-FLOAT.jnilib (No such file or directory)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:131)
at org.apache.felix.framework.util.SecureAction.getFileOutputStream(SecureAction.java:461) at org.apache.felix.framework.cache.BundleCache.copyStreamToFile(BundleCache.java:310) at org.apache.felix.framework.cache.DirectoryContent.getEntryAsNativeLibrary(DirectoryContent.java:266) at org.apache.felix.framework.ModuleImpl$ModuleClassLoader.findLibrary(ModuleImpl.java:2081)

After I did a little digging I found the directory tree it claimed to be looking for (felix-cache/bundle3/version0.0/xowave-lib/0/native/), but it wasn't in the current directory; it was in my home directory. By deleting the caches directory and rerunning, I realized that felix is building two caches every time I run it, one in my home dir and one in the current dir. There seems to be some bug relating to this. Setting the temporary dir explicitly to my home dir:

org.osgi.framework.storage=/Users/bjorn/felix-cache

works! Also works when I set the storage dir from the command line rather than the conf file:

-Dorg.osgi.framework.storage=/tmp/$USER/felix-cache


Great, so I have a solution. Still, it seems there is a problem with locating the cache dir (is it in the home dir or current dir?). Also, it seems to me that even if a bogus path is added to DYLD_LIBRARY_PATH, that shouldn't change anything.

If no cache directory is specified, the Felix framework will create a "felix-cache" directory in the current directory (i.e., the directory you are in when you launch the framework). So, if you are starting the framework from different directories, you'll see it get created in different places. I don't think there is any way a single execution of the framework will create multiple copies of the cache.

Regarding the java.library.path, the framework doesn't look at this at all. This should only impact the JVM. The only thing the framework does is create a custom class loader that overrides findLibrary() and waits for the JVM to call it when a class loaded by the class loader needs a native library.

Other than that, I'm not sure what to tell you. Again, if you can get me an example bundle and a set of steps to reproduce any issues you are seeing, I'd gladly look into it.

-> richard


    bjorn

-----------------------------
Bjorn Roche
http://www.xonami.com
Audio Collaboration



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to