LINUX.ORG.RU

Бинарная совместимость и старые версии JDK

 , , бинарная совместимость, ,


0

5

Всем здравствуйте.

С целью опытов над умершими пытаюсь завести старую версию JDK (1.3) на умеренно современной операционке (Debian 10). И да, я не оговорился – это именно JDK 1.3, выпущенный в мае 2000 года н. э., а не JDK 13, выпущенный в 2019.

И всё бы хорошо с бинарной совместимостью в том смысле, что, на первый взгляд, достаточно установить 32-разрядные зависимости, которые до сих пор есть в Debian:

  • libbsd0
  • libc6
  • libgcc1
  • libice6
  • libnspr4
  • libodbc1
  • libsm6
  • libuuid1
  • libx11-6
  • libxau6
  • libxcb1
  • libxdmcp6
  • libxext6
  • libxi6
  • libxt6
  • libxtst6
  • unixodbc-dev

Из нестандартного нужно доустановить лишь libxp6, которая без проблем достаётся из почти свежего Debian 8, да libstdc++ от gcc 2.96 (пакет compat-libstdc++-296 из ранних версий CentOS).

И вот такой набор (вплоть до моста JDBC-ODBC) прекрасно работал у меня вплоть до Debian 9 включительно.

В Debian 10 что-то случилось, и команда java -version вместо привычного

java version "1.3.1_20"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_20-b03)
Java HotSpot(TM) Client VM (build 1.3.1_20-b03, mixed mode)

выдаёт

Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/Object

И, если присмотреться, она таки действительно не может распаковать rt.jar и достать оттуда java/lang/Object.class. При запуске strace -f видно, что на Debian 9 процесс открывает rt.jar и отображает (mmap) его содержимое в виртуальную память. Это java здорового некрофила:

stat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", {st_mode=S_IFREG|0644, st_size=13904932, ...}) = 0
lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
lstat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", {st_mode=S_IFREG|0664, st_size=13904932, ...}) = 0
open("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=13904932, ...}) = 0
_llseek(3, 0, [13904932], SEEK_END)     = 0
mmap2(NULL, 13904932, PROT_READ, MAP_SHARED, 3, 0) = 0xf6b9c000
close(3)                                = 0

А вот ровно то же самое, но на Debian 10. Так сказать, java некрофила-курильщика:

stat64("/usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar", {st_mode=S_IFREG|0644, st_size=13904932, ...}) = 0
openat(AT_FDCWD, "/usr/lib/jvm/java-1.3.1_20-sun-i386/jre", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
close(3)                                = 0

Как видно, мы вместо того, чтобы выполнить open()/openat() для файла /usr/lib/jvm/java-1.3.1_20-sun-i386/jre/lib/rt.jar, выполняем то же самое действие для каталога /usr/lib/jvm/java-1.3.1_20-sun-i386/jre – с предсказуемым исходом.

Проблема совершенно точно не в ядре – её можно воспроизвести на чистом Docker-контейнере i386/debian:10, а на i386/debian:9 всё работает. Ну, т. е., на худой конец, можно гонять старый софт в Docker’е и этим удовлетвориться.

Тем не менее, если у кого-л. будут идеи, как диагностировать, – предлагайте, буду признателен.

★★★★★
Ответ на: комментарий от cocucka

Разработчики X-ов решили, что нужно использовать абстрактный Unix-сокет, который как-бы прокинут во все контенеры, и ограничивать через xauth.

Не знаю, правда, может у ТС старые xlib из 2001, ЕМНИП это после 2015 внедрять стали.

mky ★★★★★
()
Ответ на: комментарий от Bass

То, что программа 32-разрядная не означает, что в ней не может быть 64-битных чисел. Торвальдс сразу при создании ядра не подумал, что 32-бита мало для смещения в файле, но так называемые 64-битные сисколы, в которых часть параметров 64 бита появились до x86-64.

Вы уверены, что сопоставляете одинаковые места в strace'ах? Ещё есть ltrace, ЕМНИП, он покажет какие функции из glibc дёргает java, не похоже, что эта кучу lstat64() идёт от java, поди какой-нибудь readdir() или ещё что...

mky ★★★★★
()
22 июня 2023 г.
Ответ на: комментарий от Bass

А как быть с использованием «правильного» ld-linux.so.2? Тем же путь жёстко прописан в libc.so.6. patchelf?

patchelf, конечно, мировая тема, но для одноразовой проверки можно и просто запустить бинарник нужным ld-linux.so

annulen ★★★★★
()