/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE * file in the root directory of this source tree. */ #include "fb/fbjni.h" namespace facebook { namespace jni { namespace detail { void HybridData::setNativePointer(std::unique_ptr new_value) { static auto pointerField = getClass()->getField("mNativePointer"); auto* old_value = reinterpret_cast(getFieldValue(pointerField)); if (new_value) { // Modify should only ever be called once with a non-null // new_value. If this happens again it's a programmer error, so // blow up. FBASSERTMSGF(old_value == 0, "Attempt to set C++ native pointer twice"); } else if (old_value == 0) { return; } // delete on a null pointer is defined to be a noop. delete old_value; // This releases ownership from the unique_ptr, and passes the pointer, and // ownership of it, to HybridData which is managed by the java GC. The // finalizer on hybridData calls resetNative which will delete the object, if // resetNative has not already been called. setFieldValue(pointerField, reinterpret_cast(new_value.release())); } BaseHybridClass* HybridData::getNativePointer() { static auto pointerField = getClass()->getField("mNativePointer"); auto* value = reinterpret_cast(getFieldValue(pointerField)); if (!value) { throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException"); } return value; } local_ref HybridData::create() { return newInstance(); } } namespace { void resetNative(alias_ref jthis) { jthis->setNativePointer(nullptr); } } void HybridDataOnLoad() { registerNatives("com/facebook/jni/HybridData", { makeNativeMethod("resetNative", resetNative), }); } }}