@Test(timeout = 5 * 60 * 1000)
 public void testJNIMemoryManagerHeapExpansion() {
   LinkedList<RefCountedTester> heldRefs = new LinkedList<RefCountedTester>();
   JNIMemoryManager mgr = JNIMemoryManager.getMgr();
   mgr.flush();
   mgr.setMinimumReferencesToCache(1024);
   int maxItems = 10000;
   // 10000 should cause several heap expansions to occur
   for (int i = 0; i < maxItems; i++) {
     heldRefs.add(RefCountedTester.make());
   }
   assertEquals("didn't pin as many as it should", maxItems, mgr.getNumPinnedObjects());
   // now release them.
   heldRefs.clear();
   while (mgr.getNumPinnedObjects() != 0) {
     MemoryTestHelper.forceJavaHeapWeakReferenceClear();
     // Do a collection
     mgr.gc(true);
   }
   assertEquals("didn't pin as many as it should", 0, mgr.getNumPinnedObjects());
   // this should cause the heap to shrink, and then grow
   for (int i = 0; i < maxItems / 2; i++) {
     heldRefs.add(RefCountedTester.make());
   }
   assertEquals("didn't pin as many as it should", maxItems / 2, mgr.getNumPinnedObjects());
   // now release them.
   heldRefs.clear();
   // and force a collection
   while (mgr.getNumPinnedObjects() != 0) {
     MemoryTestHelper.forceJavaHeapWeakReferenceClear();
     // Do a collection
     mgr.gc(true);
   }
   assertEquals("didn't pin as many as it should", 0, mgr.getNumPinnedObjects());
 }
  @Test(timeout = 60 * 1000)
  public void testReferenceCountingLoadTestOfDeath() throws InterruptedException {
    assertEquals(
        "should be no objects for collection", 0, JNIReference.getMgr().getNumPinnedObjects());
    RefCountedTester obj = RefCountedTester.make();
    for (int i = 0; i < 1000; i++) {
      RefCountedTester copy = obj.copyReference();
      assertNotNull("could not copy reference", copy);
    }
    obj = null;

    // Force a java collection
    while (JNIReference.getMgr().getNumPinnedObjects() > 0)
      MemoryTestHelper.forceJavaHeapWeakReferenceClear();

    assertEquals("Looks like we leaked an object", 0, JNIReference.getMgr().getNumPinnedObjects());
  }
  @Test
  public void testCopyReferenceLoadTest() {
    assertEquals(0, JNIMemoryManager.getMgr().getNumPinnedObjects());

    RefCounted obj = RefCountedTester.make();

    for (int i = 0; i < 100000; i++) {
      RefCounted copy = obj.copyReference();
      copy.delete();
    }
    obj.delete();
    assertEquals(0, JNIMemoryManager.getMgr().getNumPinnedObjects());
  }
  @Test
  public void testCopyReferenceLoadTestMultiThreaded() throws InterruptedException {
    assertEquals(0, JNIMemoryManager.getMgr().getNumPinnedObjects());
    final RefCounted obj = RefCountedTester.make();

    final int NUM_THREADS = 100;
    final int NUM_ITERS = 10000;
    final AtomicBoolean start = new AtomicBoolean(false);

    Thread[] threads = new Thread[NUM_THREADS];
    for (int i = 0; i < threads.length; i++) {
      threads[i] =
          new Thread(
              new Runnable() {
                public void run() {
                  synchronized (start) {
                    while (!start.get())
                      try {
                        start.wait();
                      } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                      }
                  }
                  //              System.out.println("Thread started:
                  // "+Thread.currentThread().getName());
                  for (int i = 0; i < NUM_ITERS; i++) {
                    RefCounted copy = obj.copyReference();
                    copy.delete();
                  }
                }
              },
              "thread_" + i);
    }
    for (int i = 0; i < threads.length; i++) {
      threads[i].start();
    }
    synchronized (start) {
      start.set(true);
      start.notifyAll();
    }
    for (int i = 0; i < threads.length; i++) {
      threads[i].join();
      //      System.out.println("Thread finished: "+threads[i].getName());
    }
    obj.delete();
    assertEquals(0, JNIMemoryManager.getMgr().getNumPinnedObjects());
  }