Need preliminary reviewers: Solaris/Linux shared library version changes
Long story, but the background may be important. It's not a slam dunk that
these changes will
go into JDK7, we may decide to do this in JDK8. I recognize it is late to be
doing this in JDK7.
If you have any experience with native shared library versioning or JNI usage,
I would really
appreciate you taking the time to look at this.
Background:
A while back, the JDK7 launchers were changed to NOT set LD_LIBRARY_PATH in
the
environment or use it in anyway to launch the jdk. This was and still is
considered a good
thing for us to have done. No applications should rely on LD_LIBRARY_PATH,
it's a
workaround mechanism and comes with some old baggage. But it comes with a
cost.
Low and behold, what we discovered was that a JDK6 process, if doing an exec
of a JDK7
launcher, or anything that might cause an exec of a JDK7, was leaving the
LD_LIBRARY_PATH
settings for JDK6 libraries in the environment for the JDK7 process to find.
And, low and behold, it found the JDK6 shared libraries in some cases.
So the JDK7 process would be running with a mix of JDK7 shared libraries and
JDK6 shared libraries.
This is considered a very very bad thing, but sometimes things appeared to
work, and
sometimes things would crash, missing newer extern symbols.
Workaround:
The workaround/solution has been to unset LD_LIBRARY_PATH in the appropriate
place, if you have
an appropriate place. The difficulty arises when LD_LIBRARY_PATH is being
used for some
other reason or tool, so just unsetting it needs to be done with care.
After running into a situation where the build utility ant (a popular Java
application)
was running JDK6, and after doing a build of some Java code with JDK7
crashed, I decided
to see what could be done to guarantee no mixing happened.
Goal/Approach:
My goal here is to prevent the mixing of JDK7 shared libraries with those of
other JDK releases.
My approach was to use shared library versioning to see I could group all the
JDK7 shared libraries
with the same version, a unique version for this release, and then have any
shared library dependencies
between them insist on that same shared library version.
Any mixing would trigger a runtime linker error.
Proposed Changes:
There are 2 webrevs here, one for hotspot and one for the jdk.
7021644: Consider using a new version name on all jdk7 shared libraries
http://cr.openjdk.java.net/~ohair/openjdk7/jdk7-build-jdk-mapfile/webrev/
http://cr.openjdk.java.net/~ohair/openjdk7/jdk7-build-hotspot-mapfile/webrev/
The libjvm.so and libjawt.so libraries will also provide the older version
name.
Mapfiles:
Sometimes called version scripts, do lots of things, or can, the only part of
the mapfiles
of interest here is the version name. When you link, the version names of the
shared
libraries used and seen at link time are baked into your executable or shared
library
so that at runtime, the runtime linker will make sure you run with the right
versions.
The error message may be a cryptic runtime linker error, but it will refuse
to run.
Issues:
* On the question of JNI usage, and user's JNI shared libraries being
dependent on the older
shared library version names from JDK6 and older. The JNI book references:
http://java.sun.com/docs/books/jni/html/invoke.html#4944
http://java.sun.com/docs/books/jni/html/invoke.html#24891
Implies that any explicit shared library dependencies on libjvm.so or
libjava.so would result
in a JNI shared library that is tied to that particular implementation.
It recommends using dynamic linking if multiple JDKs would be used.
My proposal does not impact dynamic linking, but could catch problems where
the dynamic
linking was done with LD_LIBRARY_PATH set to other JDKs.
It is an accepted fact that not everyone followed this advice, as good as
it was.
* Native apps linking directly to libjvm.so or any JDK shared library.
The JDK is not a native library interface provider, with a few exceptions,
libjawt.so and libjvm.so,
all the extern symbols in the JDK shared libraries are not public
interfaces.
Having said that, I'm sure there are some people who may have purposely or
accidently
become dependent on certain extern symbols in our libraries.
* Dynamic linking, which is usually the way most of our shared libraries get
loaded
into the process, is not an issue here. However, if the shared library has
a dependency on
another JDK7 shared library, that is where LD_LIBRARY_PATH could kick in
and cause
the wrong one to be loaded.
So you might think that the answer would be to dynamically link everything,
and in fact
that might be the direction we go with JDK8, that remains to be seen.
But that effort is much more work that this person was willing to do.
Please, if you read this far, please send me comments.
-kto