Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do almost all Java binaries have the same size

I just noticed that binaries in bin in an old JRockit JDK 6 on CentOS 6, OpenJDK 8 on Ubuntu 18.10 and Oracle JDK 11 on Windows 11 have approximately the same size.

$ ls -la /usr/lib/jvm/java-8-openjdk-amd64/bin/
insgesamt 472
drwxr-xr-x 2 root root  4096 Jan 31 08:03 .
drwxr-xr-x 7 root root   144 Jan 31 08:03 ..
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 appletviewer
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 extcheck
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 idlj
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jar
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jarsigner
lrwxrwxrwx 1 root root    15 Jan 14 22:02 java -> ../jre/bin/java
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 javac
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 javadoc
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 javah
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 javap
-rwxr-xr-x 1 root root  2806 Jan 14 22:02 java-rmi.cgi
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jcmd
-rwxr-xr-x 1 root root 14528 Jan 14 22:02 jconsole
-rwxr-xr-x 1 root root 14520 Jan 14 22:02 jdb
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jdeps
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jhat
-rwxr-xr-x 1 root root 14552 Jan 14 22:02 jinfo
lrwxrwxrwx 1 root root    14 Jan 14 22:02 jjs -> ../jre/bin/jjs
-rwxr-xr-x 1 root root 14552 Jan 14 22:02 jmap
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jps
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jrunscript
-rwxr-xr-x 1 root root 14520 Jan 14 22:02 jsadebugd
-rwxr-xr-x 1 root root 14552 Jan 14 22:02 jstack
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jstat
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 jstatd
lrwxrwxrwx 1 root root    18 Jan 14 22:02 keytool -> ../jre/bin/keytool
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 native2ascii
lrwxrwxrwx 1 root root    15 Jan 14 22:02 orbd -> ../jre/bin/orbd
lrwxrwxrwx 1 root root    18 Jan 14 22:02 pack200 -> ../jre/bin/pack200
lrwxrwxrwx 1 root root    21 Jan 14 22:02 policytool -> ../jre/bin/policytool
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 rmic
lrwxrwxrwx 1 root root    15 Jan 14 22:02 rmid -> ../jre/bin/rmid
lrwxrwxrwx 1 root root    22 Jan 14 22:02 rmiregistry -> ../jre/bin/rmiregistry
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 schemagen
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 serialver
lrwxrwxrwx 1 root root    21 Jan 14 22:02 servertool -> ../jre/bin/servertool
lrwxrwxrwx 1 root root    20 Jan 14 22:02 tnameserv -> ../jre/bin/tnameserv
lrwxrwxrwx 1 root root    20 Jan 14 22:02 unpack200 -> ../jre/bin/unpack200
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 wsgen
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 wsimport
-rwxr-xr-x 1 root root 14504 Jan 14 22:02 xjc

This seems odd since they nothing in common in the tasks they fulfill (e.g. wsimport and xjc). Diffing a hexdump shows that the binaries only differ by a few Bytes while being relatively large.

like image 823
Kalle Richter Avatar asked Nov 07 '22 18:11

Kalle Richter


1 Answers

All of those executables contain very little code and delegate most of their work to the same set of shared libraries:

$ ldd java
    linux-vdso.so.1 =>  (0x00007ffd7faee000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2128acd000)
    libjli.so => /usr/java/jdk1.8.0_144/bin/./../lib/amd64/jli/libjli.so (0x00007f21288b7000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f21286b3000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f21282e6000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f2128ce9000)

$ ldd javac
    linux-vdso.so.1 =>  (0x00007fff8c1e9000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f23c6f3c000)
    libjli.so => /usr/java/jdk1.8.0_144/bin/./../lib/amd64/jli/libjli.so (0x00007f23c6d26000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f23c6b22000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f23c6755000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f23c7158000)

$ ldd jar
    linux-vdso.so.1 =>  (0x00007ffda8ff5000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4029428000)
    libjli.so => /usr/java/jdk1.8.0_144/bin/./../lib/amd64/jli/libjli.so (0x00007f4029212000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f402900e000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f4028c41000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4029644000)

The small difference in size is from their own symbols, which are still mostly the same across them:

$ nm java
0000000000600af4 A __bss_start
000000000040055c t call_gmon_start
0000000000600af8 b completed.6075
00000000006008a0 d const_launcher
00000000006008a8 d const_progname
0000000000600880 d __CTOR_END__
0000000000600878 d __CTOR_LIST__
0000000000600af0 D __data_start
0000000000600af0 W data_start
0000000000400760 t __do_global_ctors_aux
0000000000400580 t __do_global_dtors_aux
00000000004007b0 R __dso_handle
0000000000600890 D __DTOR_END__
0000000000600b00 b dtor_idx.6077
0000000000600888 d __DTOR_LIST__
00000000006008b0 d _DYNAMIC
0000000000600af4 A _edata
0000000000600b08 A _end
0000000000400798 T _fini
00000000004005f0 t frame_dummy
0000000000400870 r __FRAME_END__
0000000000600ac8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
00000000004004e8 T _init
0000000000600874 d __init_array_end
0000000000600874 d __init_array_start
00000000004007a8 R _IO_stdin_used
0000000000600898 d __JCR_END__
0000000000600898 d __JCR_LIST__
                 U JLI_Launch@@SUNWprivate_1.1
                 w _Jv_RegisterClasses
00000000004006c0 T __libc_csu_fini
00000000004006d0 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000400620 T main
0000000000400530 T _start
0000000000000000 A SUNWprivate_1.1

$ nm javac
0000000000600b70 A __bss_start
000000000040055c t call_gmon_start
0000000000600b70 b completed.6075
0000000000600b60 d const_appclasspath
0000000000600b50 d const_jargs
00000000006008e8 d const_launcher
00000000006008f0 d const_progname
00000000006008c8 d __CTOR_END__
00000000006008c0 d __CTOR_LIST__
0000000000600b40 D __data_start
0000000000600b40 W data_start
0000000000400770 t __do_global_ctors_aux
0000000000400580 t __do_global_dtors_aux
00000000004007c0 R __dso_handle
00000000006008d8 D __DTOR_END__
0000000000600b78 b dtor_idx.6077
00000000006008d0 d __DTOR_LIST__
00000000006008f8 d _DYNAMIC
0000000000600b70 A _edata
0000000000600b80 A _end
00000000004007a8 T _fini
00000000004005f0 t frame_dummy
00000000004008b8 r __FRAME_END__
0000000000600b10 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
00000000004004e8 T _init
00000000006008bc d __init_array_end
00000000006008bc d __init_array_start
00000000004007b8 R _IO_stdin_used
00000000006008e0 d __JCR_END__
00000000006008e0 d __JCR_LIST__
                 U JLI_Launch@@SUNWprivate_1.1
                 w _Jv_RegisterClasses
00000000004006d0 T __libc_csu_fini
00000000004006e0 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000400620 T main
0000000000400530 T _start
0000000000000000 A SUNWprivate_1.1
like image 127
Mike Avatar answered Nov 14 '22 22:11

Mike