xref: /aosp_15_r20/external/fbjni/java/com/facebook/jni/HybridData.java (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1*65c59e02SInna Palant /*
2*65c59e02SInna Palant  * Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palant  *
4*65c59e02SInna Palant  * Licensed under the Apache License, Version 2.0 (the "License");
5*65c59e02SInna Palant  * you may not use this file except in compliance with the License.
6*65c59e02SInna Palant  * You may obtain a copy of the License at
7*65c59e02SInna Palant  *
8*65c59e02SInna Palant  *     http://www.apache.org/licenses/LICENSE-2.0
9*65c59e02SInna Palant  *
10*65c59e02SInna Palant  * Unless required by applicable law or agreed to in writing, software
11*65c59e02SInna Palant  * distributed under the License is distributed on an "AS IS" BASIS,
12*65c59e02SInna Palant  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*65c59e02SInna Palant  * See the License for the specific language governing permissions and
14*65c59e02SInna Palant  * limitations under the License.
15*65c59e02SInna Palant  */
16*65c59e02SInna Palant 
17*65c59e02SInna Palant package com.facebook.jni;
18*65c59e02SInna Palant 
19*65c59e02SInna Palant import com.facebook.jni.annotations.DoNotStripAny;
20*65c59e02SInna Palant 
21*65c59e02SInna Palant /**
22*65c59e02SInna Palant  * This object holds a native C++ member for hybrid Java/C++ objects.
23*65c59e02SInna Palant  *
24*65c59e02SInna Palant  * <p>NB: THREAD SAFETY
25*65c59e02SInna Palant  *
26*65c59e02SInna Palant  * <p>{@link #resetNative} deletes the corresponding native object synchronously on whatever thread
27*65c59e02SInna Palant  * the method is called on. Otherwise, deletion will occur on the {@link DestructorThread} thread.
28*65c59e02SInna Palant  */
29*65c59e02SInna Palant @DoNotStripAny
30*65c59e02SInna Palant public class HybridData {
31*65c59e02SInna Palant 
32*65c59e02SInna Palant   static {
33*65c59e02SInna Palant     System.loadLibrary("fbjni");
34*65c59e02SInna Palant   }
35*65c59e02SInna Palant 
36*65c59e02SInna Palant   private final Destructor mDestructor = new Destructor(this);
37*65c59e02SInna Palant 
38*65c59e02SInna Palant   /**
39*65c59e02SInna Palant    * To explicitly delete the instance, call resetNative(). If the C++ instance is referenced after
40*65c59e02SInna Palant    * this is called, a NullPointerException will be thrown. resetNative() may be called multiple
41*65c59e02SInna Palant    * times safely. Because the {@link DestructorThread} also calls resetNative, the instance will
42*65c59e02SInna Palant    * not leak if this is not called, but timing of deletion and the thread the C++ dtor is called on
43*65c59e02SInna Palant    * will be at the whim of the Java GC. If you want to control the thread and timing of the
44*65c59e02SInna Palant    * destructor, you should call resetNative() explicitly.
45*65c59e02SInna Palant    */
resetNative()46*65c59e02SInna Palant   public synchronized void resetNative() {
47*65c59e02SInna Palant     mDestructor.destruct();
48*65c59e02SInna Palant   }
49*65c59e02SInna Palant 
50*65c59e02SInna Palant   /**
51*65c59e02SInna Palant    * N.B. Thread safety. If you call isValid from a different thread than {@link #resetNative()}
52*65c59e02SInna Palant    * then be sure to do so while synchronizing on the hybrid. For example:
53*65c59e02SInna Palant    *
54*65c59e02SInna Palant    * <pre><code>
55*65c59e02SInna Palant    * synchronized(hybrid) {
56*65c59e02SInna Palant    *   if (hybrid.isValid) {
57*65c59e02SInna Palant    *     // Do stuff.
58*65c59e02SInna Palant    *   }
59*65c59e02SInna Palant    * }
60*65c59e02SInna Palant    * </code></pre>
61*65c59e02SInna Palant    */
isValid()62*65c59e02SInna Palant   public boolean isValid() {
63*65c59e02SInna Palant     return mDestructor.mNativePointer != 0;
64*65c59e02SInna Palant   }
65*65c59e02SInna Palant 
66*65c59e02SInna Palant   @DoNotStripAny
67*65c59e02SInna Palant   public static class Destructor extends DestructorThread.Destructor {
68*65c59e02SInna Palant 
69*65c59e02SInna Palant     // Private C++ instance
70*65c59e02SInna Palant     private volatile long mNativePointer;
71*65c59e02SInna Palant 
Destructor(Object referent)72*65c59e02SInna Palant     Destructor(Object referent) {
73*65c59e02SInna Palant       super(referent);
74*65c59e02SInna Palant     }
75*65c59e02SInna Palant 
76*65c59e02SInna Palant     @Override
destruct()77*65c59e02SInna Palant     protected final void destruct() {
78*65c59e02SInna Palant       // When invoked from the DestructorThread instead of resetNative,
79*65c59e02SInna Palant       // the DestructorThread has exclusive ownership of the HybridData
80*65c59e02SInna Palant       // so synchronization is not necessary.
81*65c59e02SInna Palant       deleteNative(mNativePointer);
82*65c59e02SInna Palant       mNativePointer = 0;
83*65c59e02SInna Palant     }
84*65c59e02SInna Palant 
deleteNative(long pointer)85*65c59e02SInna Palant     static native void deleteNative(long pointer);
86*65c59e02SInna Palant   }
87*65c59e02SInna Palant }
88