Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add JDK tools support #8

Closed
serhei opened this issue Dec 17, 2019 · 6 comments
Closed

add JDK tools support #8

serhei opened this issue Dec 17, 2019 · 6 comments
Milestone

Comments

@serhei
Copy link
Owner

serhei commented Dec 17, 2019

JDK tools (jps, jstack, jstat) require a special case to locate the correct version of libjli.so (NB there may be multiple versions on one system):

$ ldd /usr/bin/jps
	linux-vdso.so.1 (0x00007ffcb43db000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3ac289e000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f3ac2884000)
	libjli.so => not found
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f3ac287e000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f3ac26b8000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3ac28e8000)
$ rpm -ql java-1.8.0-openjdk-devel | grep libjli
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/lib/amd64/jli/libjli.so
@serhei serhei added this to the v1.0 milestone Dec 17, 2019
@serhei
Copy link
Owner Author

serhei commented Dec 17, 2019

Java also wants other libraries which may not be captured by ldd e.g.:

$ rpm -ql java-1.8.0-openjdk-headless | grep libjava 
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib/amd64/libjava.so
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib/amd64/libjava_crw_demo.so
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib/amd64/libjavajpeg.so

@serhei
Copy link
Owner Author

serhei commented Dec 17, 2019

Java search paths can be obtained with:

$ java -XshowSettings:properties -version 2>&1 | grep sun.boot.library.path
    sun.boot.library.path = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib/amd64
$ LD_LIBRARY_PATH=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib/amd64/jli ldd /usr/bin/jps
	linux-vdso.so.1 (0x00007fff4af83000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ff47a855000)
	libz.so.1 => /lib64/libz.so.1 (0x00007ff47a83b000)
	libjli.so => /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib/amd64/jli/libjli.so (0x00007ff47a829000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007ff47a823000)
	libc.so.6 => /lib64/libc.so.6 (0x00007ff47a65d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ff47a89f000)

@serhei
Copy link
Owner Author

serhei commented Jan 15, 2020

Getting a handle on the issue:

  • an executable such as /usr/bin/jps is a symlink, e.g. on my system
    /usr/bin/jps -> /etc/alternatives/jps -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/bin/jps
  • the executable loads libraries on-demand (not captured by ldd) via a relative rpath as revealed by readelf --dynamic /usr/bin/jps:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libjli.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [lib.so]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/../lib/amd64/jli:$ORIGIN/../lib/amd64]

Changing the rpath (via chrpath) is a hack that does not work in all cases (cannot lengthen the string unless the rpath was padded), so the best bet seems to be to replicate the JVM directory hierarchy in the target container.

Testing methods such as the following on a local system

mkdir -p tree/bin tree/lib
cp /usr/bin/jps tree/bin/jps
ln -s /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib tree/lib/jps
./tree/bin/jps

currently yields

Could not find or load main class sun.tools.jps.Jps

so there are additional files missing.

@serhei
Copy link
Owner Author

serhei commented Jan 15, 2020

If the JDK tool version has to match the in-container JRE version, then the hierarchy created by oc-inject could include a symlink to in-container JRE's files/directories.

@serhei
Copy link
Owner Author

serhei commented Jan 23, 2020

Successful:

mkdir -p tree/bin tree/jre
cp /usr/bin/jps tree/bin/jps
ln -s /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/lib tree/lib
ln -s /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b13-0.fc29.x86_64/jre/lib tree/jre/lib
./tree/bin/jps

Executable requires both lib and jre/lib directories.

@serhei serhei closed this as completed in 32e0b40 Feb 7, 2020
@serhei
Copy link
Owner Author

serhei commented Feb 7, 2020

Pushed a working implementation (tested on jps, jstack, jstat),
will open more issues if problems with it are discovered.
For more robust JDK tool functionality I should work on issue #6.

Turns out that Java programs do not like to be loaded via ld-linux-x86-64.so.2.
This forces us to use ld-linux-x86-64.so.2 from the container (not injected)
and correspondingly also the version of glibc from the container.

Since the container presumably has a Java program and therefore libc,
and the JDK tool version must closely match the container JRE version
anyways, this is not as serious a problem as it sounds.

serhei added a commit that referenced this issue Feb 7, 2020
Not doing so caused the 'automatic' (libjli.so based)
opts.java enablement to fail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant