On Jan 2, 2011, at 10:58 PM, Richard S. Hall wrote:
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.
when I ran felix, it would create cache directories in both my home
and current directories. I verified this by deleting "felix-cache" in
both the current and home dir, running felix once, and locating these
directories again. It built the felix-cache/bundle3/version0.0/xowave-
lib/0/native/ tree in my home directory, but then complained that it
couldn't find it. It put everything else in the current directory. The
solution to this issue seemed to be to specify the
org.osgi.framework.storage variable from the command line rather than
the configuration file, but I'm not really sure.
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.
I'm not really sure what the issue here was -- I only used
java.library.path to discover what was going on and it may only have
been related incidentally. Perhaps the issue has to do with the
$DYLD_LIBRARY_PATH variable -- it must at least indirectly since
that's what I changed to get it working.
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.
I will see what I can do.
bjorn
-----------------------------
Bjorn Roche
http://www.xonami.com
Audio Collaboration
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]