Off-heap object space

Mikael Gerdin mikael.gerdin at oracle.com
Wed Jan 20 07:22:10 UTC 2016


Hi,

On 2016-01-16 02:54, Khanh Nguyen wrote:
> Hi,
>
> I want to implement an off-heap, non-GC, non-contiguous object space. Of
> course my naive approach is to call os::malloc or the existing macro
> AllocateHeap(). Also I did turn the compressed oops flags off. But I'm
> facing this undeterministic issue: randomly the JVM crashes. That is,
> sometimes my program can successfully run (with the correct result). And
> sometimes it crashes (in library code)
>
> Partial crash log is this:
> #
> # A fatal error has been detected by the Java Runtime Environment:
> #
> #  SIGSEGV (0xb) at pc=0x00007fd71102681d, pid=6741, tid=140562059818752
> #
> # JRE version: OpenJDK Runtime Environment (8.0) (build
> 1.8.0-internal-debug-khanhtn1_2016_01_15_17_06-b00)
> # Java VM: OpenJDK 64-Bit Server VM (25.0-b70-debug interpreted mode
> linux-amd64 )
> # Problematic frame:
> # j
>   java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;+56
> #
> # Core dump written. Default location:
> /lv_scratch/scratch/khanh/openjdk8/core or core.6741
> #
> # If you would like to submit a bug report, please visit:
> #   http://bugreport.sun.com/bugreport/crash.jsp
> #
>
> ---------------  T H R E A D  ---------------
>
> Current thread (0x00007fd72000a800):  JavaThread "main" [_thread_in_Java,
> id=6742, stack(0x00007fd72794f000,0x00007fd727a50000)]
>
> siginfo:si_signo=SIGSEGV: si_errno=0, si_code=2 (SEGV_ACCERR),
> si_addr=0x00007fd723ee00be
>
> Registers:
> RAX=0x00007fd6110fc818, RBX=0x00007fd0ae129248, RCX=0x0000000000000000,
> RDX=0x0000003fe88800be
> RSP=0x00007fd727a4e428, RBP=0x00007fd727a4e480, RSI=0x00007fd727a4e3b8,
> RDI=0x0000000001200020
> R8 =0x0000000000000000, R9 =0x0000000000000024, R10=0x00007f973b660000,
> R11=0x00007fd727a4e390
> R12=0x00007fd711000564, R13=0x00007fd0ae124bb3, R14=0x00007fd727a4e4f0,
> R15=0x00007fd72000a800
> RIP=0x00007fd71102681d, EFLAGS=0x0000000000010206,
> CSGSFS=0x0000000000000033, ERR=0x0000000000000006
>    TRAPNO=0x000000000000000e
>
> Stack: [0x00007fd72794f000,0x00007fd727a50000],  sp=0x00007fd727a4e428,
>   free space=1021k
> Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native
> code)
> j
>   java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;+56
> j
>   java.util.HashMap.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+9
> j  EmptyMethod.generateHashMap()Ljava/util/HashMap;+44
> j  EmptyMethod.runTest(I)V+24
> j  EmptyMethod.main([Ljava/lang/String;)V+97
> v  ~StubRoutines::call_stub
> V  [libjvm.so+0x823762]  JavaCalls::call_helper(JavaValue*, methodHandle*,
> JavaCallArguments*, Thread*)+0x680
> V  [libjvm.so+0xaaae44]  os::os_exception_wrapper(void (*)(JavaValue*,
> methodHandle*, JavaCallArguments*, Thread*), JavaValue*, methodHandle*,
> JavaCallArguments*, Thread*)+0x3a
> V  [libjvm.so+0x8230db]  JavaCalls::call(JavaValue*, methodHandle,
> JavaCallArguments*, Thread*)+0x7d
> V  [libjvm.so+0x837185]  jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*,
> JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)+0x1ca
> V  [libjvm.so+0x84d31e]  jni_CallStaticVoidMethod+0x385
> C  [libjli.so+0x8012]  JavaMain+0x89a
>
> ---------------  P R O C E S S  ---------------
>
> Java Threads: ( => current thread )
>    0x00007fd72014c000 JavaThread "Service Thread" daemon [_thread_blocked,
> id=6765, stack(0x00007fd0a9e37000,0x00007fd0a9f38000)]
>    0x00007fd720142800 JavaThread "Signal Dispatcher" daemon
> [_thread_blocked, id=6764, stack(0x00007fd0a9f38000,0x00007fd0aa039000)]
>    0x00007fd7200e9000 JavaThread "Finalizer" daemon [_thread_blocked,
> id=6763, stack(0x00007fd110058000,0x00007fd110159000)]
>    0x00007fd7200e6800 JavaThread "Reference Handler" daemon
> [_thread_blocked, id=6762, stack(0x00007fd0aa039000,0x00007fd0aa13a000)]
> =>0x00007fd72000a800 JavaThread "main" [_thread_in_Java, id=6742,
> stack(0x00007fd72794f000,0x00007fd727a50000)]
>
> Other Threads:
>    0x00007fd7200db800 VMThread [stack:
> 0x00007fd0aa13a000,0x00007fd0aa23b000] [id=6761]
>    0x00007fd720150000 WatcherThread [stack:
> 0x00007fd0a9d36000,0x00007fd0a9e37000] [id=6766]
>
> VM state:not at safepoint (normal execution)
>
> VM Mutex/Monitor currently owned by a thread: None
>
> Heap:
>   PSYoungGen      total 5120K, used 2088K [0x00007fd611000000,
> 0x00007fd611b00000, 0x00007fd711000000)
>    eden space 4096K, 25% used
> [0x00007fd611000000,0x00007fd61110a278,0x00007fd611400000)
>    from space 1024K, 100% used
> [0x00007fd611400000,0x00007fd611500000,0x00007fd611500000)
>    to   space 1536K, 0% used
> [0x00007fd611980000,0x00007fd611980000,0x00007fd611b00000)
>   ParOldGen       total 512512K, used 1128K [0x00007fd411000000,
> 0x00007fd430480000, 0x00007fd611000000)
>    object space 512512K, 0% used
> [0x00007fd411000000,0x00007fd41111a0c0,0x00007fd430480000)
>   Metaspace       used 3255K, capacity 4108K, committed 4352K, reserved 8192K
>
> Card table byte_map: [0x00007fd7256e8000,0x00007fd726ee9000] byte_map_base:
> 0x00007f973b660000
>
> Marking Bits: (ParMarkBitMap*) 0x00007fd728f79340
>   Begin Bits: [0x00007fd0b0000000, 0x00007fd0bc000000)
>   End Bits:   [0x00007fd0bc000000, 0x00007fd0c8000000)
>
> Polling page: 0x00007fd7291f5000
>
> CodeCache: size=245760Kb used=1439Kb max_used=1439Kb free=244320Kb
>   bounds [0x00007fd711000000, 0x00007fd711270000, 0x00007fd720000000]
>   total_blobs=189 nmethods=0 adapters=164
>   compilation: disabled (interpreter mode)
>
>
> Using gdb doesn't show anything interesting unfortunately
> #2  0x00007fd023d393a3 in os::abort (dump_core=true) at
> /scratch/khanh/openjdk8/hotspot/src/os/linux/vm/os_linux.cpp:1563
> #3  0x00007fd023efacdd in VMError::report_and_die (this=0x7fd023293d00) at
> /scratch/khanh/openjdk8/hotspot/src/share/vm/utilities/vmError.cpp:1078
> #4  0x00007fd023d453d9 in JVM_handle_linux_signal (sig=11,
> info=0x7fd023293fb0, ucVoid=0x7fd023293e80, abort_if_unrecognized=1) at
> /scratch/khanh/openjdk8/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp:534
> #5  0x00007fd023d3eebf in signalHandler (sig=11, info=0x7fd023293fb0,
> uc=0x7fd023293e80) at
> /scratch/khanh/openjdk8/hotspot/src/os/linux/vm/os_linux.cpp:4278
> #6  <signal handler called>
> #7  0x00007fd00d02681d in ?? ()
> #8  0x00007fcf0d0feee0 in ?? ()
> #9  0x0000000000000002 in ?? ()
> #10 0x00007fc9e95c9c58 in ?? ()
> #11 0x00007fd023294440 in ?? ()
> #12 0x00007fca09c71bb0 in ?? ()
> #13 0x00007fd0232944f0 in ?? ()
> #14 0x00007fca09c74e30 in ?? ()
> #15 0x0000000000000000 in ?? ()
>
> So my questions, specifically, are
> 1) Why SEGV_ACCERR? And any idea of where the problem might be?
>
> 2) In theory, it should be straightforward for me to have an off-heap space
> where I can allocate objects in. I don't understand why there is a random
> crash like what I have. I mean if I violate some implicit rules in Hotspot,
> my program should fail always.

This is not the case.
Due to how the garbage collectors operate, every write to an object 
field is accompanied by a write to a "card table" used to keep track of 
object references from the old generation into the young generation.

These card table writes are compiled in to the JIT-compiled methods and 
in order to call methods on your "off heap" objects you would need the 
card table to span all of the memory in which your off heap objects reside.

This is essentially one of the core reasons why noncontiguous heaps are 
not such a simple problem to solve as some people suspect.
There are a lot of performance advantages to having a known, fixed 
maximum heap size and a fixed region of memory where the objects are 
located.

Regards
/Mikael

>
> Any pointers/suggestions are greatly appreciated.
>
> Thank you,
>


More information about the hotspot-dev mailing list