JDK-8244847 : Linux/PPC: runtime/CompressedOops/CompressedClassPointers: smallHeapTest fails
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 11,12,13,14
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: ppc
  • Submitted: 2020-05-12
  • Updated: 2022-05-19
  • Resolved: 2020-12-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 16
11.0.12Fixed 16 b28Fixed
Related Reports
Relates :  
Relates :  
Description
smallHeapTest fails on Linux/PPC, because the narrow klass base is not 0x0.

### Reproduce

java -Xmx1g -Xshare:off -Xlog:metaspace*=info -version

=> Narrow klass base: 0x00007fff28000000       // Should be 0x0

### Preconditions

CDS needs to be disabled.

At most 2g maximum heap size.

Linux kernel 4.12 or higher [6][7]
Downported to 4.1.42 [8]

### Analysis (addresses modulo ASLR in the lower bits)

JDK-8233410 made the java launcher a position independent executable (PIE). As a side effect the
launcher gets loaded to 0x0000000100000000 (4g). Before it was loaded to 0x0000000010000000 (256m)
[1]. With the precoditions above 4g is precisely the address where current heuristics do a one shot
attempt to get a zero based compressed class space (CCS) which now always fails.

On x86_64 the issue does not exist, because ELF_ET_DYN_BASE is well above 32g.

More Details:

The small java heap (-Xmx128m) is mapped just below 4g in
ReservedHeapSpace::initialize_compressed_heap() which calls try_reserve_range() with highest_start
== UnscaledOopHeapMax == 4g and lowest_start == HeapBaseMinAddress == 2g [2]. try_reserve_range()
searches from top to bottom [3], and is successfull at first try. So the heap is mapped just below
4g.

Metaspace::global_initialize() requests to map the CCS right after the java heap [4]. This fails,
because the launcher is already mapped to 4g (see above).
Metaspace::reserve_address_space_for_compressed_classes() is called to handle the failure. On PPC this method does not try to get a zerobased CCS [5].

[1] ELF_ET_DYN_BASE for PPC
    https://github.com/torvalds/linux/blob/79dede78c0573618e3137d3d8cbf78c84e25fabd/arch/powerpc/include/asm/elf.h#L27

[2] ReservedHeapSpace::initialize_compressed_heap(): call to try_reserve_range(highest=4g, lowest=2g)
    http://hg.openjdk.java.net/jdk/jdk/file/dd1034e6350f/src/hotspot/share/memory/virtualspace.cpp#l563

[3] ReservedHeapSpace::try_reserve_range(): search from top to bottom
    http://hg.openjdk.java.net/jdk/jdk/file/dd1034e6350f/src/hotspot/share/memory/virtualspace.cpp#l425

[4] Metaspace::global_initialize(): try to map CCS just after java heap
    https://github.com/openjdk/jdk/blob/f2f3ba92d78da6af3bf7e379cad436bdfa3d29bc/src/hotspot/share/memory/metaspace.cpp#L703

[5] Metaspace::reserve_address_space_for_compressed_classes() does not try to get a good address for CCS on PPC
    https://github.com/openjdk/jdk/blob/2f06893a29fba3b40cc1cf03095b75b217d1bb93/src/hotspot/share/memory/metaspace.cpp#L533

[6] Linux kernel commit that changed ELF_ET_DYN_BASE from 0x20000000 to 0x100000000UL on PPC
    https://github.com/torvalds/linux/commit/47ebb09d54856500c5a5e14824781902b3bb738e

[7] ELF_ET_DYN_BASE was changed [6] with Linux version 4.12
    https://github.com/torvalds/linux/blob/02445990a96e60a67526510d8b00f7e3d14101c3/Makefile

[8] Downport of ELF_ET_DYN_BASE change to 4.1.42
    https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.1.y&id=cd5425dae2d687f50b7cac21f7b1eac431af8381

Comments
Fix request (11u) I would like to backport this to jdk11u. Without it we cannot get a zerobased ccs on Linux/PPC64 if a small heap (2g) is configured. The issues was fixed originally in jdk16. In contrast to jdk16 CDS will be disabled(*) by default in 11u because vanilla builds won't produce a shared archive. The original patch does not apply, but the fix is equivalent and very small: it activates code for PPC64 which is already used for AARCH64 and AIX. The 11u fix does not include modifications of the test test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java as it was not disabled on PPC in 11u. RFR: https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2021-April/005694.html (*) prerequisite for the issue
12-04-2021

Changeset: 4a267f1b Author: Richard Reingruber <rrich@openjdk.org> Date: 2020-12-03 08:50:08 +0000 URL: https://git.openjdk.java.net/jdk/commit/4a267f1b
03-12-2020

The issue is not yet fixed. Instead the narrow klass base check was disabled in CompressedClassPointers.java for PPC with JDK-8243392.
27-11-2020

This is probably fixed by JDK-8243392 which remodeled the whole CDS/Metaspace initialization sequence.
17-11-2020

I think that has been fixed as a side effect of JDK-8243392
17-11-2020

An implementation for JDK-8244943 should fix this issue (JDK-8244847) too.
14-05-2020

Attachment 8244847_CompressedClassPointers_smallHeapTest_fails.patch could be used as a fix. It adds a second attempt to get a zero-based CCS at the high end of the zero-based addressable range. The patch could be easily extended to try both ends of the zero-based addressable range [HeapBaseMinAddress,OopEncodingHeapMax[ and become a simple solution for JDK-8244943
14-05-2020