How can I make lazy/delay loading work in Linux?

2019-05-28 09:17发布

问题:

I got this working great on Windows -- application loads my plugin (C++, Qt), my plugin does a smart search to find an installed JRE, sets the library search path accordingly, and then calls a function in the JVM which forces the jvm.dll to be loaded at that point. (Previous question: How can I deploy a mixed C++/Java (JNI) application?)

Now I'm trying to get it working on Linux. From what I read, lazy linking/loading was the default, so I thought it would just work.... doesn't seem like it.

I'd like to avoid dlopen() and dlsym(), LD_LIBRARY_PATH, ldconfig, etc. The idea is that users of this plugin shouldn't have to know how any of that works, they just put the plugin.so in the right place, and when it's loaded, the plugin has the smarts to find the JRE (or tell the user to install a JRE).

Can this be done?

EDIT

Just to be clear... the error I get when the plugin is loaded: "Cannot load library /home/dan/blah/blah/libMyPlugin.so: (libjawt.so: cannot open shared object file: No such file or directory)"

EDIT

If it matters... this needs to work on Ubuntu 10.10 and up, on CentOS 5.4, and OSX 10.6+.

On Ubuntu 10.10, I did apt-get install openjdk-6-jdk and then to get things to run correctly I had to

export LD_LIBRARY_PATH=
  /usr/lib/jvm/java-6-openjdk/jre/lib/i386:
  /usr/lib/jvm/java-6-openjdk/jre/lib/i386/client:
  /usr/lib/jvm/java-6-openjdk/jre/lib/i386/xawt

(newlines for legibility)

But if someone had a different JDK installed (e.g., Sun's) then the directories would probably differ (?).

回答1:

How did you conduct the smart search on windows? There are a couple of "normal" places to look in Linux.

A lot of times the $JAVA_HOME environment variable is set to the current JRE.

I don't have ready access to all of the systems you listed, but on some distros, you have a symlink /usr/java/latest which will point to the latest installed version.

In general, if there's a JRE installed, it will probably be in one of /usr/lib/jvm*, /usr/java*, /usr/lib/java*, or possibly one of the lib64 varieties of the above.

Of course, the above methods will most likely point you to a JRE. Deciding which to use might be tricky, but if your code doesn't rely on the latest and greatest, it will probably be okay.

I suppose as part of asking your user to install a JRE if one can't be found, you could ask them to set $JAVA_HOME as that's fairly standard practice.

I don't know of a sure fire way for it to work on all distros, since part of the problem stems from the nature of *nix distributions. There may be an additional convention that I'm missing, however.



回答2:

If your program simply runs java /path/to/foo.jar then the solution is easy on Debian-derived systems:

$ ls -l /usr/bin/java /etc/alternatives/java /usr/lib/jvm/java-6-sun/jre/bin/java | awk '{print $1, $8, $9, $10}'
lrwxrwxrwx /etc/alternatives/java -> /usr/lib/jvm/java-6-sun/jre/bin/java
lrwxrwxrwx /usr/bin/java -> /etc/alternatives/java
-rwxr-xr-x /usr/lib/jvm/java-6-sun/jre/bin/java  
$ 

The java in /usr/bin/java is a symlink to a symlink to the real JRE.