There are multiple issues surrounding libstdc++.so, moving to use a different
gcc to build JDK doesn't solve all of the problems - unless we can provide
binaries for every possible gcc version. We'd like to keep a single binary
build to simplify testing and deployment, so that's not what we want to do.
We've implemented a couple of changes in 1.4.2 to solve the compatibility
issues and they were put back by different bug IDs. But since this bug is
one of the top bugs on JDC, here I'll explain the changes and possible
workarounds before 1.4.2 is released:
1. JDK requires libstdc++-libc6.1-1.so.2
JDK is linked with libstdc++-libc6.1-1.so.2, and many new Linux distributions
do not have this library installed by default. As the result, you'll see
error message similar to this:
Error: failed ../jre/lib/i386/client/libjvm.so. because libstdc++-libc6.1-1.so.2: cannot open shared object file: No such file or directory.
To fix this, we statically link libstdc++.so in JDK, so there is no requirement
on user side to have the library installed. It is implemented for HotSpot VM
in 1.4.1 and for the rest of JDK in 1.4.2.
User has to install libstdc++-libc6.1-1.so.2 manually. For example, Redhat
Linux has this library in the "compat-libstdc++" package.
2. Incompatibility in C++ ABI
The binary interface of libstdc++ has been constantly changing in the past
two years, if user JNI code is written in C++ and not compiled by the same
compiler we used to build JDK (i.e. egcs-2.91), at runtime, there will be
two incompatible libstdc++.so being loaded into memory at the same time.
That isn't healthy, in particular, when two libraries have common symbols
(yes, there are many common symbols between different libstdc++.so), symbols
from the first loaded library will be used to resolve all references. This can
lead to crashes or aborts.
We really can't fix imcompatibility issues for C++ ABI. What we did for
1.4.2 is just trying to work around the problem. Please see 4776723 and
4706607. We statically link the C++ runtime in JDK and enabled linker
script to hide symbols from libstdc++ and other internal symbols. As the
result, those symbols become invisible to JNI code, and when some native
code needs to call into C++ runtime, the call will be resolved with
the appropriate libstdc++.so. There are still two libstdc++.so being
loaded at the same time, but it should be benign.
In the meantime, user could try one of the following workarounds:
+ If you have access to the source code of the JNI library and can rebuild
it, build it on Redhat 6.2. Then the JNI bits will be linked against the
same C++ runtime that is being used by JDK, and there will be no symbol
conflicts. This is the safest solution. You can continue to deploy on
non-RH-6.2 systems (e.g. Redhat 7.x) and have the added benefit that you
can deploy on earlier platforms.
+ If you can rebuild the library, but can't build it on Redhat 6.2,
you can use gcc (not g++) to link the binary, you also need to add
"-Wl,-Bsymbolic -Wl,-Bstatic -lstdc++, -Wl,-Bdynamic" to the command
line to statically link with the correct libstdc++ and force linker
to resolve symbols within the library.
+ If for some reason you cannot rebuild the library, you can preload
the libstdc++.so that is used by your JNI library. You need to run
"ldd" first on the library to figure out which libstdc++.so will
be used, then set LD_PRELOAD to include it. This will cause all
reference to the C++ runtime to be resolved by the preloaded libstdc++.so.
This can work around most of the problems, and easy to test.
3. Change in C++ mangling rules
This is actually part of the ABI changes, but since it has a different
symptom and requires different solution, I list it here separately.
With gcc-3.x, the format for a mangled C++ symbol has changed. For example,
A::foo(int) is encoded as foo__1Ai by gcc-2.x and as _ZN1A3fooEi by gcc-3.x.
If library X imports C++ symbols from library Y and X is built by gcc-2.x,
now you try to run X with a version of Y that is built by gcc-3.x, you'll
get errors on unsolved symbols; because, for example, X is trying to call
foo__1Ai but Y only provides _ZN1A3fooEi. That is what's happening when
you use java plugin in a browser built by gcc-3.x.
Don't import C++ symbols directly.
One more ABI compatibility problem. This time it's with Java plugin only.
Apparently in a C++ object which contains virtual functions, its vptr
points to different place when the code is compiled by gcc-2.9x or gcc-3.x.
This is causing problems in Java plugin (see 4687814) because the OJI
interface is using virtual functions extensively between browser (Mozilla)
and plugin. There is really no way to fix it other than building the plugin
with gcc-3.2 (or modifying OJI). This is not a problem with other part
of JDK because we don't use virtual functions to communicate with other
So here's what we did in Mantis in an attempt to resolve the gcc compatibility
(1) C++ runtime (aka libstdc++.so) is statically linked with JDK. When you
install JDK or JRE, there is no requirement on the backward compatibility
(2) Linker mapfiles and versioning have been enabled. C++ symbols due to
static link in (1) and also VM internal symbols are now hidden. This is
necessary to avoid symbol conflicts between different libstdc++ versions.
But if you try to access VM internal symbol directly in a program, it
will not work with 1.4.2. This change can also improve VM performance
(due to smaller dynamic symbol table), but at a cost of less accurate
symbol lookup after crash.
(3) 1.4.2 will have two libjavaplugin_oji.so files, one is built by gcc-2.91
and the other one by gcc-3.2. If you are using gcc-3 built mozilla, use
the one in "jre/plugin/i386/ns610-gcc32" directory. Otherwise, use the
one in "jre/plugin/i386/ns610"
I'm now closing this one as "fixed". Mantis-beta should be out very soon, and
the work (except (3) because it has other dependencies) has been backported
to 1.4.1_03. If you continue to see compatibility problems, feel free to let
me know (hui dot huang at sun dot com).
###@###.### suggested to change bug status to duplicate, as
there is no code change associated with this bug ID. I have marked it as a
duplicate of 4687814 to make it easier tracking code changes.
But please note, this bug is really not a duplicate of 4687814. It's
a tracking bug for C++ compatibility issues, 4687814 is only part of
the problem. Fixes have been delivered under the following bug IDs:
4776723, 4706607, 4665166, 4687814, 4791798