/* Copyright (c) 2007 Timothy Wall, All Rights Reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package com.sun.jna; import java.lang.ref.WeakReference; import java.nio.Buffer; import java.nio.ByteBuffer; import junit.framework.TestCase; public class MemoryTest extends TestCase { public void testAutoFreeMemory() throws Exception { final boolean[] flag = { false }; Memory core = new Memory(10) { protected void finalize() { super.finalize(); flag[0] = true; } }; Pointer shared = core.share(0, 5); WeakReference ref = new WeakReference(core); core = null; System.gc(); long start = System.currentTimeMillis(); assertFalse("Memory prematurely GC'd", flag[0]); assertNotNull("Base memory GC'd while shared memory extant", ref.get()); // Avoid having IBM J9 prematurely nullify "shared" shared.setInt(0, 0); shared = null; System.gc(); while (ref.get() != null) { if (System.currentTimeMillis() - start > 5000) break; Thread.sleep(10); } assertNull("Memory not GC'd", ref.get()); } public void testSharedMemoryBounds() { Memory base = new Memory(16); Pointer shared = base.share(4, 4); shared.getInt(-4); try { shared.getInt(-8); fail("Bounds check should fail"); } catch(IndexOutOfBoundsException e) { } shared.getInt(8); try { shared.getInt(12); fail("Bounds check should fail"); } catch(IndexOutOfBoundsException e) { } } public void testAlignment() { final int SIZE = 1<<16; Memory base = new Memory(SIZE); for (int align=1;align < SIZE;align *= 2) { Memory unaligned = base; long mask = ~((long)align - 1); if ((base.peer & mask) == base.peer) unaligned = (Memory)base.share(1, SIZE-1); Pointer aligned = unaligned.align(align); assertEquals("Memory not aligned (" + align + ")", aligned.peer & mask, aligned.peer); assertSame("Alignment request on aligned memory should no-op", aligned, ((Memory)aligned).align(align)); } } public void testNegativeAlignment() { final int SIZE = 128; Memory base = new Memory(SIZE); try { base.align(-1); fail("Negative alignments not allowed"); } catch(IllegalArgumentException e) { } } public void testInvalidAlignment() { final int SIZE = 128; Memory base = new Memory(SIZE); int[] alignments = { 0, 3, 5, 9, 13 }; for (int i=0;i < alignments.length;i++) { try { base.align(alignments[i]); fail("Power-of-two alignments required"); } catch(IllegalArgumentException e) { } } } public void testAvoidGCWithExtantBuffer() throws Exception { Memory m = new Memory(1024); ByteBuffer b = m.getByteBuffer(0, m.getSize()); WeakReference ref = new WeakReference(m); WeakReference bref = new WeakReference(b); m = null; System.gc(); Memory.purge(); for (int i=0;i < 100 && ref.get() != null;i++) { Thread.sleep(10); System.gc(); Memory.purge(); } assertNotNull("Memory GC'd while NIO Buffer still extant", ref.get()); // Avoid IBM J9 optimization resulting in premature GC of buffer b.put((byte)0); b = null; System.gc(); Memory.purge(); for (int i=0;i < 100 && (bref.get() != null || ref.get() != null);i++) { Thread.sleep(10); System.gc(); Memory.purge(); } assertNull("Buffer not GC'd\n", bref.get()); assertNull("Memory not GC'd after buffer GC'd\n", ref.get()); } public static void main(String[] args) { junit.textui.TestRunner.run(MemoryTest.class); } }