Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 833097 - dev-java/openjdk-8.312_p07: compiling with -flto -fdevirtualize-at-ltrans: .../libjvm.so: undefined symbol: _ZN14G1CMOopClosure9do_oop_nvIjEEvPT_
Summary: dev-java/openjdk-8.312_p07: compiling with -flto -fdevirtualize-at-ltrans: .....
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal
Assignee: Georgy Yakovlev
URL:
Whiteboard:
Keywords: PATCH
Depends on:
Blocks: lto
  Show dependency tree
 
Reported: 2022-02-11 00:43 UTC by Alexander Miller
Modified: 2025-02-19 19:59 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments
openjdk-8-undefined-symbols.patch (openjdk-8-undefined-symbols.patch,22.78 KB, patch)
2022-02-11 00:43 UTC, Alexander Miller
Details | Diff
Patch to add LTO flags from 11u and later on 8u (lto.patch,616 bytes, patch)
2025-02-19 19:59 UTC, Andrew John Hughes
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Miller 2022-02-11 00:43:45 UTC
Created attachment 764817 [details, diff]
openjdk-8-undefined-symbols.patch

With gcc-11.2 and a bunch of aggressive optimization flags (including -O3 -flto -fdevirtualize-at-ltrans), dev-java/openjdk-8.312_p07 fails to compile. Here's the end of the build log (with a bit of context):

-----8<-----
Boot cycle build step 2: Building a new JDK image using previously built image
gmake[1]: Entering directory '/tmp/portage/dev-java/openjdk-.312_p07/work/openjdk-8.312_p07'
Running make as '/usr/bin/gmake  VERBOSE= LOG_LEVEL=debug -R -I /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/make/common -rRw -I/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/make/common -j1 SPEC=/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-spec.gmk -j4'
Building OpenJDK for target 'images' in configuration 'linux-x86_64-normal-server-release'

## Starting langtools
gmake[2]: Entering directory '/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/langtools/make'
SetupJavaCompiler(BOOT_JAVAC) 
 [2] JAVAC := /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/images/j2sdk-image/bin/javac 
 [3] SERVER_DIR := 
 [4] SERVER_JVM := /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/images/j2sdk-image/bin/java -verbosegc -d64 -Xms6G -Xmx6G 
 [5] FLAGS := -XDignore.symbol.file=true -g -Xlint:all,-deprecation -Werror     
                
SetupJavaCompilation(BUILD_TOOLS) 
 [2] SETUP := BOOT_JAVAC 
 [3] DISABLE_SJAVAC := true 
 [4] ADD_JAVAC_FLAGS := -Xprefer:source 
 [5] SRC := /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/langtools/make/tools /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/langtools/src/share/classes 
 [6] INCLUDES := compileproperties genstubs 
 [7] BIN := /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses                   

/bin/mkdir -p /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses
/bin/rm -f /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch.tmp
/bin/echo  Writing 2 paths to ' >> /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch.tmp'
Writing 2 paths to  >> /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch.tmp
/bin/echo Compiling `/usr/bin/wc /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch.tmp | /usr/bin/tr -s ' ' | /usr/bin/cut -f 2 -d ' '` files for BUILD_TOOLS
Compiling 2 files for BUILD_TOOLS
( /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/images/j2sdk-image/bin/javac -XDignore.symbol.file=true -g -Xlint:all,-deprecation -Werror  -Xprefer:source -implicit:none -sourcepath "/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/langtools/make/tools:/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/langtools/src/share/classes" -d /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses  @/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch.tmp && /bin/mv /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch.tmp /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/bootcycle-build/langtools/btclasses/_the.BUILD_TOOLS_batch)
Error: dl failure on line 894
Error: failed /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/images/j2sdk-image/jre/lib/amd64/server/libjvm.so, because /tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/build/linux-x86_64-normal-server-release/images/j2sdk-image/jre/lib/amd64/server/libjvm.so: undefined symbol: _ZN14G1CMOopClosure9do_oop_nvIjEEvPT_
gmake[2]: Leaving directory '/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07/langtools/make'
gmake[2]: *** No rule to make target 'all', needed by 'default'.  Stop.
gmake[2]: *** No rule to make target 'all', needed by 'default'.  Stop.
gmake[1]: *** [/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07//make/Main.gmk:85: langtools-only] Error 2
gmake[1]: Leaving directory '/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07'
make: *** [/tmp/portage/dev-java/openjdk-8.312_p07/work/openjdk-8.312_p07//make/Main.gmk:179: bootcycle-images-only] Error 2
 * ERROR: dev-java/openjdk-8.312_p07::gentoo failed (compile phase):
 *   emake failed
----->8-----

Now, that's been a tricky one.

The missing symbol, _ZN14G1CMOopClosure9do_oop_nvIjEEvPT_ aka "void G1CMOopClosure::do_oop_nv<unsigned int>(unsigned int*)", is virtual inline and its definition is in a separate header (g1OopClosures.inline.hpp), while the main header (g1OopClosures.hpp) only contains the declaration.
So an undefined symbol can result if a compilation unit only includes the main header—and other compilation units that include both headers may not emit it either because it's declared inline. When an optimizer performs speculative devirtualization, this can happen in non-obvious places, basically anywhere the virtual method is used in the entire class hierarchy.
A few other do_oop_nv instances defined in the same source file are also missing from the build's libjvm.so, so I scanned all of its object files for
these symbols and found a number of affected compilation units.

Long story short: including the inline header in the corresponding source files fixes the problem. See attached patch.

Not sure if the issue is related to LTO or some other flags, it could be hit by any compiler that can do speculative devirtualization.

I expect the same applies to dev-java/openjdk-8.322_p06, but haven't tested it yet.
A similar problem exists for dev-java/openjdk-11.0.14_p9-r1, I'll file a separate bug for that.
Comment 1 Andrew John Hughes 2022-11-09 00:17:55 UTC
OpenJDK doesn't support LTO, so removing that is the first thing I'd try.
Comment 2 Sam James archtester Gentoo Infrastructure gentoo-dev Security 2022-11-09 00:18:50 UTC
(In reply to Andrew John Hughes from comment #1)
> OpenJDK doesn't support LTO, so removing that is the first thing I'd try.

There's a patch included fwiw.
Comment 3 Andrew John Hughes 2023-04-04 17:10:00 UTC
It appears there should be support in OpenJDK for building with LTO that was quietly added in JDK 9 with the ARM32 port. It only came to our attention due to this follow-up work in the upcoming releases:

https://bugs.openjdk.org/browse/JDK-8292226

The best solution might be to detect -flto in the ebuild and replace it with passing --with-jvm-features=link-time-opt to the OpenJDK build.

We're looking at turning it on in Fedora:

https://bugzilla.redhat.com/show_bug.cgi?id=1861441#c10
Comment 4 Georgy Yakovlev archtester gentoo-dev 2023-04-06 00:21:44 UTC
--with-jvm-features=link-time-opt

with it openjdk-11 still fails to build

it works with 17 though.

I'm going to:

strip lto *flags in openjdk:8
strip lto *flags in openjdk:11 but add (masked) USE=lto which passes --with-jvm-features=link-time-opt and hopefully get fixed.
strip lto *flags in openjdk:17 and USE=lto will activate --with-jvm-features=link-time-opt
Comment 5 Georgy Yakovlev archtester gentoo-dev 2023-04-06 00:27:32 UTC
since openjdk:8 now filters out -flto* let's close this and continue discussion of openjdk:11 in https://bugs.gentoo.org/833098
Comment 6 Larry the Git Cow gentoo-dev 2023-04-06 00:27:48 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=970458062aa4c59f525e447cc9f7b6251acdb2d1

commit 970458062aa4c59f525e447cc9f7b6251acdb2d1
Author:     Georgy Yakovlev <gyakovlev@gentoo.org>
AuthorDate: 2023-04-06 00:22:21 +0000
Commit:     Georgy Yakovlev <gyakovlev@gentoo.org>
CommitDate: 2023-04-06 00:27:41 +0000

    dev-java/openjdk: handle lto
    
    Bug: https://bugs.gentoo.org/833098
    Closes: https://bugs.gentoo.org/833097
    Signed-off-by: Georgy Yakovlev <gyakovlev@gentoo.org>

 dev-java/openjdk/metadata.xml               |  1 +
 dev-java/openjdk/openjdk-11.0.18_p10.ebuild | 10 +++++++++-
 dev-java/openjdk/openjdk-17.0.6_p10.ebuild  | 10 +++++++++-
 dev-java/openjdk/openjdk-8.362_p09.ebuild   |  6 ++++++
 4 files changed, 25 insertions(+), 2 deletions(-)

Additionally, it has been referenced in the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=3fb095f88d00b6e9f0ac6be366117c2f7736c8db

commit 3fb095f88d00b6e9f0ac6be366117c2f7736c8db
Author:     Georgy Yakovlev <gyakovlev@gentoo.org>
AuthorDate: 2023-04-06 00:24:47 +0000
Commit:     Georgy Yakovlev <gyakovlev@gentoo.org>
CommitDate: 2023-04-06 00:27:42 +0000

    profiles/base: mask openjdk:11[lto]
    
    Bug: https://bugs.gentoo.org/833097
    Bug: https://bugs.gentoo.org/833098
    Signed-off-by: Georgy Yakovlev <gyakovlev@gentoo.org>

 profiles/base/package.use.mask | 6 ++++++
 1 file changed, 6 insertions(+)
Comment 7 Andrew John Hughes 2025-02-19 19:58:56 UTC
For the record, I suspect 8u would need backports of https://bugs.openjdk.org/browse/JDK-8075955 and maybe https://bugs.openjdk.org/browse/JDK-8204540 which is not going to happen at this stage in its lifecycle.

The problem with the attached patch as a fix upstream is it breaks the encapsulation of the different GC implementations and I suspect may fail with some configurations. There's not generally much support for this upstream (hence why it is still off by default)

Downstream though, you could experiment with adding the same flags 11u does when  --with-jvm-features=link-time-opt is enabled. I've attached a patch for this I tried on 8u. With that alone, it fails as in the subject of this bug.
Comment 8 Andrew John Hughes 2025-02-19 19:59:54 UTC
Created attachment 919440 [details, diff]
Patch to add LTO flags from 11u and later on 8u