title: Passing a Java object to C++ via JNI and then back to Java, via void*
body: <p>I have an Android app that employs both React Native and JNI. C++ (via a fork of the JUCE library) is used to generate one of the views. </p>
  
  <p>React Native requires that a new instance of a view be returned from the overridden method <code>createViewInstance(context)</code>. This seems to get called each time a React Native component containing this view is updated.</p>
  
  <p>Here is my (simplified) implementation:</p>
  
  <pre><code>protected JuceViewHolder createViewInstance(ThemedReactContext themedReactContext) {
      JuceBridge juceBridge = JuceBridge.getInstance();
      juceViewHolder = new JuceViewHolder(themedReactContext);
  
      // JNI method: this will trigger JuceBridge.createNewView
      MainActivity.createJuceWindow(juceViewHolder); 
  
      return juceViewHolder;
  </code></pre>
  
  <p>}</p>
  
  <p>For reference, <code>createJuceWindow</code> is defined as:</p>
  
  <pre><code>JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, createJuceWindow, jobject, (JNIEnv* env, jclass, jobject view))
  {
      JuceView::getInstance().createJuceWindow(view);
  }
  </code></pre>
  
  <p>which calls:</p>
  
  <pre><code>void createJuceWindow(jobject view)
  {
      viewToAttachTo = GlobalRef(view); // [GlobalRef][1] manages NewGlobalRef
      myComponent = std::unique_ptr&lt;MyComponent&gt; (new MyComponent);
      myComponent-&gt;setVisible (true);
      myComponent-&gt;setOpaque(true);
  
      if (viewToAttachTo.get() == nullptr)
          DBG ("createJuceWindow: viewToAttachTo null!!!");
  
      myComponent-&gt;setBounds(Desktop::getInstance().getDisplays().getMainDisplay().userArea);
      myComponent-&gt;addToDesktop (0, viewToAttachTo.get()); // This passes in the `jobject` held by GlobalRef
  }
  </code></pre>
  
  <p>I have separated the <a href="https://github.com/adamski/JUCE/blob/android-bridge-attachWindow/modules/juce_core/native/java/JuceViewHolder.java" rel="nofollow"><code>JuceViewHolder</code></a> derived from ViewGroup, and I am passing it to a C++ function via JNI in order to attach the (Java)<a href="https://github.com/adamski/JUCE/blob/android-bridge-attachWindow/modules/juce_core/native/java/JuceBridge.java#L385" rel="nofollow"><code>ComponentPeerView</code></a> generated from the (C++) <a href="https://github.com/adamski/JUCE/blob/android-bridge-attachWindow/modules/juce_gui_basics/native/juce_android_Windowing.cpp#L131" rel="nofollow"><code>AndroidComponentPeer</code></a> constructor</p>
  
  <pre><code>AndroidComponentPeer (Component&amp; comp, const int windowStyleFlags, void* viewToAttachTo)
      : ComponentPeer (comp, windowStyleFlags),
        usingAndroidGraphics (false),
        fullScreen (false),
        sizeAllocated (0),
        scale ((float) Desktop::getInstance().getDisplays().getMainDisplay().scale)
  {
      // NB: must not put this in the initialiser list, as it invokes a callback,
      // which will fail if the peer is only half-constructed.
  
      if (viewToAttachTo == nullptr) DBG ("viewToAttachTo null");
      view = GlobalRef (android.bridge.callObjectMethod (JuceBridge.createNewView,
                                                        (jboolean) component.isOpaque(),
                                                        (jlong) this,
                                                        (jobject) viewToAttachTo));
  
      if (view.get() == nullptr)
          DBG ("view null!");
      else
          DBG ("got view.");
  
      if (isFocused())
          handleFocusGain();
  }
  </code></pre>
  
  <p>via the <code>createNewView</code> method: (simplified here)</p>
  
  <pre><code>public final ComponentPeerView createNewView (boolean opaque, long host, ViewGroup viewToAttachTo)
  {
      ComponentPeerView v = new ComponentPeerView (viewToAttachTo.getContext(), opaque, host);
      viewToAttachTo.addView(v);
      return v;
  }
  </code></pre>
  
  <p><code>host</code> is a pointer to the C++ <code>AndroidComponentPeer</code> instance. </p>
  
  <p>This works initially, however it seems that if I switch to another View or Activity and/or switch back to the C++ View, I get a crash similar to the following:</p>
  
  <pre><code>JNI ERROR (app bug): accessed deleted global reference 0x100566
  art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0x100566
  art/runtime/java_vm_ext.cc:410]     from void com.juce.JuceBridge$ComponentPeerView.focusChanged(long, boolean)
  </code></pre>
  
  <p>My current assumption is that the error is due to the <code>void*</code> pointer becoming obsolete at some point due to the garbage collector moving the underlying object, as described in <a href="http://android-developers.blogspot.co.uk/2011/11/jni-local-reference-changes-in-ics.html" rel="nofollow">this article</a>. What I got from the article is that <code>jobject</code> should be used in place of a pointer. </p>
  
  <p>However the method signature of the <code>Component::addToDesktop</code> method that I have employed uses <code>void*</code>:</p>
  
  <pre><code>virtual void addToDesktop (int windowStyleFlags,
                                 void* nativeWindowToAttachTo = nullptr);
  </code></pre>
  
  <p>(This is the method used in iOS to pass a native <code>UIView</code> to attach a <code>Component</code> to)</p>
  
  <p>Is my assumption valid? If so, is it possible to safely cast a <code>void*</code> pointer to a Java object, store it as a <code>jobject</code> (via NewGlobalRef) and then pass it back to Java? </p>