Off-heap object space

Khanh Nguyen ktruong.nguyen at gmail.com
Wed Jan 20 07:35:14 UTC 2016


Hi Mikael,

As I understand it, card table marking is there only to prevent leaks since
objects in young generation can be solely reached from old generation.
Let's say I don't care about those off-heap objects right now, i.e., I'm
willing to let them be leaks. Then I don't need a card table for off-heap
memory.
That's exactly my situation right now: I have malloced a space, have
objects allocated in it and boom, JVM just crashes (randomly)

On Tue, Jan 19, 2016 at 11:22 PM, Mikael Gerdin <mikael.gerdin at oracle.com>
wrote:

> 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