title: why is my Java object being copied or finalize() being called twice?
body: <p>Long Java/Android/JNI story short... I have two classes, an object/class which I created called Packet, and a JNI interface to lower-level C code that I wrote.  In one class, I parse incoming packets and store them in an ArrayList. When they are "parsed" a function Packet.dissect() is called, which uses JNI to call lower-level C-code.  This C-code malloc()'s some memory, and returns the memory pointer to the Java code which stores it in a private member of the Packet object:</p>
  
  <pre><code>ArrayList&lt;Packet&gt; _scan_results;
  
      ...
  
          // Loop and read headers and packets
          while(true) {
              Packet rpkt = new Packet(WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP);
  
              switch(_state) {
  
              case IDLE:
                  break;
  
              case SCANNING:
                  // rpkt.dissect() calls a JNI C-code function which allocates
                  // memory (malloc) and returns the pointer, which is stored in
                  // a private member of the Packet (rpkt._dissect_ptr).
                  rpkt.dissect();
                  if(rpkt.getField("wlan_mgt.fixed.beacon")!=null)
                      _scan_results.add(rpkt);
  
                  break;
              }
          }
  </code></pre>
  
  <p>Now, I want to ensure that this memory is freed so that I do not have a leak.  So, when the garbage collector determines that the Packet object is no longer in use, I rely on finalize() to call a JNI C-code function, passing the pointer, which frees the memory:</p>
  
  <pre><code>protected void finalize() throws Throwable {
      try {
  
          if(_dissection_ptr!=-1)
              dissectCleanup(_dissection_ptr);
  
      } finally {
          super.finalize();
      }
  }
  </code></pre>
  
  <p>Great, this works just fine <em>UNTIL</em> I attempt to share the ArrayList with the second class.  To do so, I use Broadcast in Android by sending a broadcast with the ArrayList list from the first class, to a BroadcastReceiver in the second class.  Here is where it is broadcast from the first class:</p>
  
  <pre><code>    // Now, send out a broadcast with the results
      Intent i = new Intent();
      i.setAction(WIFI_SCAN_RESULT);
      i.putExtra("packets", _scan_results);
      coexisyst.sendBroadcast(i);
  </code></pre>
  
  <p>What I <em>thought</em> was true about doing this, would be that each Packet in the list is passed to the second class by reference to the object.  If this were true, then no matter what the two classes do with the List and the objects in them, I am guaranteed that the garbage collector will only call finalize() <em>ONCE</em> for each Packet (when both classes are deemed finished with each packet).  This is super important, or free() will be called twice on the same pointer (causing a SEGFAULT).</p>
  
  <p>This seems to be happening to me.  Once the second class receives the ArrayList from the broadcast, it parses through it, and holds several Packet's from the list.  When doing so, there is another object/class which has a member of type Packet, if I "like" the packet, I save it by doing:</p>
  
  <pre><code>other_object.pkt = pktFromList;
  </code></pre>
  
  <p>Eventually this method which received the Broadcast returns, and some of the Packets were "kept."  Finally, when I click a button (several seconds later), the ArrayList in the original class is cleared:</p>
  
  <pre><code>_scan_results.clear();
  </code></pre>
  
  <p>I have assumed that even when clear() is called here, if the first class has "kept" some of the packets, the garbage collector will not call finalize() on them.  The only way for this to be false would be if: (1) when the broadcast is sent, the ArrayList is copied and not passed by reference, or (2) when the packets are "kept" in the second class, the Packet object is copied rather than being kept by reference.</p>
  
  <p>Well, one of these is false because free() is occasionally called on the same piece of memory twice.  I see that it is allocated ("new dissection: MEMORY_ADDRESS1 - IGNORE_THIS"), and then two finalize() are called trying to deallocate the same memory address:</p>
  
  <pre><code>INFO/Driver(6036): new dissection: 14825864 - 14825912
  ...
  INFO/Driver(6036): received pointer to deallocate: 14825864
  ...
  INFO/Driver(6036): received pointer to deallocate: 14825864
  INFO/DEBUG(5946): signal 11 (SIGSEGV), fault addr 0000001c
  </code></pre>
  
  <p>So, one of the two assumptions I am making about the objects being passed around is false.  Does anyone know which it might be, and how I can pass the objects more carefully by reference so that I can clean the memory up properly?</p>
  
  <p>If you made it this far through my question and understand it, thank you ;)</p>