# HG changeset patch # User kbarrett # Date 1530046778 14400 # Node ID 45c1fde86050195130c474cbb6a11997ebfbab31 # Parent fa380b3b2b7d4b900e42dbd1c89a2f1a8c515cb0 8205559: Remove IN_CONCURRENT_ROOT Access decorator Summary: Removed decorator and made all NativeAccess use barriers. Reviewed-by: pliden, stefank diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -2127,8 +2127,7 @@ bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, value, Address(value, 0), tmp, - thread); + access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp, thread); verify_oop(value); bind(done); } @@ -3643,8 +3642,7 @@ // ((OopHandle)result).resolve(); void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // OopHandle::resolve is an indirection. - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, - result, Address(result, 0), tmp, noreg); + access_load_at(T_OBJECT, IN_NATIVE, result, Address(result, 0), tmp, noreg); } void MacroAssembler::load_mirror(Register dst, Register method, Register tmp) { diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp --- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -321,9 +321,10 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) { bool in_heap = (decorators & IN_HEAP) != 0; - bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0; + bool as_normal = (decorators & AS_NORMAL) != 0; + assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); - bool needs_pre_barrier = in_heap || in_concurrent_root; + bool needs_pre_barrier = as_normal; bool needs_post_barrier = (new_val != noreg) && in_heap; // flatten object address if needed @@ -360,7 +361,7 @@ g1_write_barrier_post(masm, store_addr, new_val, tmp1, tmp2, tmp3); } } -}; +} #ifdef COMPILER1 diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/arm/macroAssembler_arm.cpp --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -2140,7 +2140,7 @@ b(done); bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_NATIVE, Address(value, 0), value, tmp1, tmp2, noreg); verify_oop(value); bind(done); diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp --- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -400,9 +400,10 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register val, Address dst, Register tmp) { bool in_heap = (decorators & IN_HEAP) != 0; - bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0; + bool as_normal = (decorators & AS_NORMAL) != 0; + assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); - bool needs_pre_barrier = in_heap || in_concurrent_root; + bool needs_pre_barrier = as_normal; // No need for post barrier if storing NULL bool needs_post_barrier = val != G0 && in_heap; diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/sparc/macroAssembler_sparc.cpp --- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -182,8 +182,7 @@ br (Assembler::always, true, Assembler::pt, done); delayed()->nop(); bind(not_weak); - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, - Address(value, 0), value, tmp); + access_load_at(T_OBJECT, IN_NATIVE, Address(value, 0), value, tmp); verify_oop(value); bind(done); } @@ -3402,8 +3401,7 @@ // ((OopHandle)result).resolve(); void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // OopHandle::resolve is an indirection. - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, - Address(result, 0), result, tmp); + access_load_at(T_OBJECT, IN_NATIVE, Address(result, 0), result, tmp); } void MacroAssembler::load_mirror(Register mirror, Register method, Register tmp) { diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -349,9 +349,10 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2) { bool in_heap = (decorators & IN_HEAP) != 0; - bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0; + bool as_normal = (decorators & AS_NORMAL) != 0; + assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); - bool needs_pre_barrier = in_heap || in_concurrent_root; + bool needs_pre_barrier = as_normal; bool needs_post_barrier = val != noreg && in_heap; Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi); diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/cpu/x86/macroAssembler_x86.cpp --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -5238,8 +5238,7 @@ jmp(done); bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, - value, Address(value, 0), tmp, thread); + access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp, thread); verify_oop(value); bind(done); } @@ -6216,7 +6215,7 @@ // Only 64 bit platforms support GCs that require a tmp register // Only IN_HEAP loads require a thread_tmp register // OopHandle::resolve is an indirection like jobject. - access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_NATIVE, result, Address(result, 0), tmp, /*tmp_thread*/noreg); } diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/classfile/classLoaderData.cpp --- a/src/hotspot/share/classfile/classLoaderData.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/classfile/classLoaderData.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -832,9 +832,7 @@ oop* ptr = h.ptr_raw(); if (ptr != NULL) { assert(_handles.owner_of(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr)); - // This root is not walked in safepoints, and hence requires an appropriate - // decorator that e.g. maintains the SATB invariant in SATB collectors. - NativeAccess::oop_store(ptr, oop(NULL)); + NativeAccess<>::oop_store(ptr, oop(NULL)); } } diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp --- a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -52,11 +52,6 @@ LIR_Opr pre_val, CodeEmitInfo* info) { LIRGenerator* gen = access.gen(); DecoratorSet decorators = access.decorators(); - bool in_heap = (decorators & IN_HEAP) != 0; - bool in_conc_root = (decorators & IN_CONCURRENT_ROOT) != 0; - if (!in_heap && !in_conc_root) { - return; - } // First we test whether marking is in progress. BasicType flag_type; diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp --- a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp Tue Jun 26 16:59:38 2018 -0400 @@ -98,12 +98,10 @@ template inline void G1BarrierSet::AccessBarrier:: oop_store_not_in_heap(T* addr, oop new_value) { - if (HasDecorator::value) { - // For roots not scanned in a safepoint, we have to apply SATB barriers - // even for roots. - G1BarrierSet *bs = barrier_set_cast(BarrierSet::barrier_set()); - bs->write_ref_field_pre(addr); - } + // Apply SATB barriers for all non-heap references, to allow + // concurrent scanning of such references. + G1BarrierSet *bs = barrier_set_cast(BarrierSet::barrier_set()); + bs->write_ref_field_pre(addr); Raw::oop_store(addr, new_value); } diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -281,13 +281,11 @@ StringDedupEntry** list, uintx &count) { for (StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) { if (entry->hash() == hash && entry->latin1() == latin1) { - typeArrayOop existing_value = entry->obj(); - if (equals(value, existing_value)) { - // Apply proper barrier to make sure it is kept alive. Concurrent mark might - // otherwise declare it dead if there are no other strong references to this object. - oop* obj_addr = (oop*)entry->obj_addr(); - oop obj = NativeAccess::oop_load(obj_addr); - return typeArrayOop(obj); + oop* obj_addr = (oop*)entry->obj_addr(); + oop obj = NativeAccess::oop_load(obj_addr); + if (equals(value, static_cast(obj))) { + obj = NativeAccess::oop_load(obj_addr); + return static_cast(obj); } } count++; diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -653,7 +653,6 @@ return p; } - bool conc_root = (access.decorators() & IN_CONCURRENT_ROOT) != 0; bool weak = (access.decorators() & ON_WEAK_OOP_REF) != 0; GraphKit* kit = access.kit(); diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/gc/z/zBarrierSet.cpp --- a/src/hotspot/share/gc/z/zBarrierSet.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/gc/z/zBarrierSet.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -48,12 +48,9 @@ //assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Unexpected decorator"); if (type == T_OBJECT || type == T_ARRAY) { - if (((decorators & IN_HEAP) != 0) || - ((decorators & IN_CONCURRENT_ROOT) != 0) || - ((decorators & ON_PHANTOM_OOP_REF) != 0)) { - // Barrier needed - return true; - } + assert((decorators & (IN_HEAP | IN_NATIVE)) != 0, "Where is reference?"); + // Barrier needed even when IN_NATIVE, to allow concurrent scanning. + return true; } // Barrier not neeed diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/oops/access.hpp --- a/src/hotspot/share/oops/access.hpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/oops/access.hpp Tue Jun 26 16:59:38 2018 -0400 @@ -375,8 +375,7 @@ const DecoratorSet location_decorators = decorators & IN_DECORATOR_MASK; STATIC_ASSERT(location_decorators == 0 || ( // make sure location decorators are disjoint if set (location_decorators ^ IN_NATIVE) == 0 || - (location_decorators ^ IN_HEAP) == 0 || - (location_decorators ^ (IN_NATIVE | IN_CONCURRENT_ROOT)) == 0 + (location_decorators ^ IN_HEAP) == 0 )); } diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/oops/accessDecorators.hpp --- a/src/hotspot/share/oops/accessDecorators.hpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/oops/accessDecorators.hpp Tue Jun 26 16:59:38 2018 -0400 @@ -153,8 +153,8 @@ // Note that primitive accesses will only be resolved on the barrier set if the appropriate build-time // decorator for enabling primitive barriers is enabled for the build. const DecoratorSet AS_RAW = UCONST64(1) << 12; -const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 14; -const DecoratorSet AS_NORMAL = UCONST64(1) << 15; +const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 13; +const DecoratorSet AS_NORMAL = UCONST64(1) << 14; const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_NO_KEEPALIVE | AS_NORMAL; // === Reference Strength Decorators === @@ -166,10 +166,10 @@ // * ON_UNKNOWN_OOP_REF: The memory access is performed on a reference of unknown strength. // This could for example come from the unsafe API. // * Default (no explicit reference strength specified): ON_STRONG_OOP_REF -const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 16; -const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 17; -const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 18; -const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 19; +const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 15; +const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 16; +const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 17; +const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 18; const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF; @@ -179,13 +179,9 @@ // * IN_HEAP: The access is performed in the heap. Many barriers such as card marking will // be omitted if this decorator is not set. // * IN_NATIVE: The access is performed in an off-heap data structure pointing into the Java heap. -// * IN_CONCURRENT_ROOT: The access is performed in an off-heap data structure pointing into the Java heap, -// but is notably not scanned during safepoints. This is sometimes a special case for some GCs and -// implies that it is also an IN_NATIVE. -const DecoratorSet IN_HEAP = UCONST64(1) << 20; -const DecoratorSet IN_NATIVE = UCONST64(1) << 22; -const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 23; -const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE | IN_CONCURRENT_ROOT; +const DecoratorSet IN_HEAP = UCONST64(1) << 19; +const DecoratorSet IN_NATIVE = UCONST64(1) << 20; +const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE; // == Boolean Flag Decorators == // * IS_ARRAY: The access is performed on a heap allocated array. This is sometimes a special case @@ -194,8 +190,8 @@ // marking that the previous value is uninitialized nonsense rather than a real value. // * IS_NOT_NULL: This property can make certain barriers faster such as compressing oops. const DecoratorSet IS_ARRAY = UCONST64(1) << 21; -const DecoratorSet IS_DEST_UNINITIALIZED = UCONST64(1) << 13; -const DecoratorSet IS_NOT_NULL = UCONST64(1) << 25; +const DecoratorSet IS_DEST_UNINITIALIZED = UCONST64(1) << 22; +const DecoratorSet IS_NOT_NULL = UCONST64(1) << 23; // == Arraycopy Decorators == // * ARRAYCOPY_CHECKCAST: This property means that the class of the objects in source @@ -207,17 +203,17 @@ // * ARRAYCOPY_ARRAYOF: The copy is in the arrayof form. // * ARRAYCOPY_ATOMIC: The accesses have to be atomic over the size of its elements. // * ARRAYCOPY_ALIGNED: The accesses have to be aligned on a HeapWord. -const DecoratorSet ARRAYCOPY_CHECKCAST = UCONST64(1) << 26; -const DecoratorSet ARRAYCOPY_DISJOINT = UCONST64(1) << 27; -const DecoratorSet ARRAYCOPY_ARRAYOF = UCONST64(1) << 28; -const DecoratorSet ARRAYCOPY_ATOMIC = UCONST64(1) << 29; -const DecoratorSet ARRAYCOPY_ALIGNED = UCONST64(1) << 30; +const DecoratorSet ARRAYCOPY_CHECKCAST = UCONST64(1) << 24; +const DecoratorSet ARRAYCOPY_DISJOINT = UCONST64(1) << 25; +const DecoratorSet ARRAYCOPY_ARRAYOF = UCONST64(1) << 26; +const DecoratorSet ARRAYCOPY_ATOMIC = UCONST64(1) << 27; +const DecoratorSet ARRAYCOPY_ALIGNED = UCONST64(1) << 28; const DecoratorSet ARRAYCOPY_DECORATOR_MASK = ARRAYCOPY_CHECKCAST | ARRAYCOPY_DISJOINT | ARRAYCOPY_DISJOINT | ARRAYCOPY_ARRAYOF | ARRAYCOPY_ATOMIC | ARRAYCOPY_ALIGNED; // Keep track of the last decorator. -const DecoratorSet DECORATOR_LAST = UCONST64(1) << 30; +const DecoratorSet DECORATOR_LAST = UCONST64(1) << 28; namespace AccessInternal { // This class adds implied decorators that follow according to decorator rules. @@ -235,9 +231,7 @@ // If no barrier strength has been picked, normal will be used static const DecoratorSet barrier_strength_default = memory_ordering_default | ((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY); - static const DecoratorSet conc_root_is_root = barrier_strength_default | - ((IN_CONCURRENT_ROOT & barrier_strength_default) != 0 ? IN_NATIVE : INTERNAL_EMPTY); - static const DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS; + static const DecoratorSet value = barrier_strength_default | BT_BUILDTIME_DECORATORS; }; // This function implements the above DecoratorFixup rules, but without meta @@ -253,9 +247,7 @@ // If no barrier strength has been picked, normal will be used DecoratorSet barrier_strength_default = memory_ordering_default | ((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY); - DecoratorSet conc_root_is_root = barrier_strength_default | - ((IN_CONCURRENT_ROOT & barrier_strength_default) != 0 ? IN_NATIVE : INTERNAL_EMPTY); - DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS; + DecoratorSet value = barrier_strength_default | BT_BUILDTIME_DECORATORS; return value; } } diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/oops/oopHandle.inline.hpp --- a/src/hotspot/share/oops/oopHandle.inline.hpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/oops/oopHandle.inline.hpp Tue Jun 26 16:59:38 2018 -0400 @@ -29,7 +29,7 @@ #include "oops/oopHandle.hpp" inline oop OopHandle::resolve() const { - return (_obj == NULL) ? (oop)NULL : NativeAccess::oop_load(_obj); + return (_obj == NULL) ? (oop)NULL : NativeAccess<>::oop_load(_obj); } #endif // SHARE_VM_OOPS_OOPHANDLE_INLINE_HPP diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/runtime/jniHandles.cpp --- a/src/hotspot/share/runtime/jniHandles.cpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/runtime/jniHandles.cpp Tue Jun 26 16:59:38 2018 -0400 @@ -109,7 +109,7 @@ // Return NULL on allocation failure. if (ptr != NULL) { assert(*ptr == NULL, "invariant"); - NativeAccess::oop_store(ptr, obj()); + NativeAccess<>::oop_store(ptr, obj()); res = reinterpret_cast(ptr); } else { report_handle_allocation_failure(alloc_failmode, "global"); @@ -175,7 +175,7 @@ if (handle != NULL) { assert(!is_jweak(handle), "wrong method for detroying jweak"); oop* oop_ptr = jobject_ptr(handle); - NativeAccess::oop_store(oop_ptr, (oop)NULL); + NativeAccess<>::oop_store(oop_ptr, (oop)NULL); global_handles()->release(oop_ptr); } } diff -r fa380b3b2b7d -r 45c1fde86050 src/hotspot/share/runtime/jniHandles.inline.hpp --- a/src/hotspot/share/runtime/jniHandles.inline.hpp Tue Jun 26 13:50:59 2018 -0700 +++ b/src/hotspot/share/runtime/jniHandles.inline.hpp Tue Jun 26 16:59:38 2018 -0400 @@ -57,7 +57,7 @@ if (is_jweak(handle)) { // Unlikely result = resolve_jweak(handle); } else { - result = NativeAccess::oop_load(jobject_ptr(handle)); + result = NativeAccess<>::oop_load(jobject_ptr(handle)); // Construction of jobjects canonicalize a null value into a null // jobject, so for non-jweak the pointee should never be null. assert(external_guard || result != NULL, "Invalid JNI handle");