[jffi-next] 09/49: Keep a reference to the Foreign instance in objects that need to release resources in a finalizer. Stops the Foreign class being GC'd before any class that needs to use it gets GC'd.

Tim Potter tpot-guest at moszumanska.debian.org
Wed Mar 4 04:51:09 UTC 2015


This is an automated email from the git hooks/post-receive script.

tpot-guest pushed a commit to annotated tag upstream/1.0.10
in repository jffi-next.

commit cd8c2af1c2f9c3e2ee8e5cfb70b8ee4c7f5b649e
Author: Wayne Meissner <wmeissner at gmail.com>
Date:   Sat Jan 1 22:26:27 2011 +1000

    Keep a reference to the Foreign instance in objects that need to release resources in a finalizer.  Stops the Foreign class being GC'd before any class that needs to use it gets GC'd.
---
 src/com/kenai/jffi/Aggregate.java   | 22 +++++++++++++++++-----
 src/com/kenai/jffi/Array.java       |  2 +-
 src/com/kenai/jffi/CallContext.java | 17 ++++++++++++-----
 src/com/kenai/jffi/ClosurePool.java |  9 ++++++---
 src/com/kenai/jffi/Function.java    | 17 ++++++++++++-----
 src/com/kenai/jffi/LastError.java   |  7 ++++---
 src/com/kenai/jffi/Library.java     | 21 ++++++++++++---------
 src/com/kenai/jffi/MemoryIO.java    |  4 ++--
 src/com/kenai/jffi/PageManager.java | 14 ++++++++++----
 src/com/kenai/jffi/Struct.java      |  2 +-
 src/com/kenai/jffi/Union.java       |  2 +-
 11 files changed, 78 insertions(+), 39 deletions(-)

diff --git a/src/com/kenai/jffi/Aggregate.java b/src/com/kenai/jffi/Aggregate.java
index 4be8246..e8f0107 100644
--- a/src/com/kenai/jffi/Aggregate.java
+++ b/src/com/kenai/jffi/Aggregate.java
@@ -18,6 +18,9 @@
 
 package com.kenai.jffi;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 public abstract class Aggregate extends Type {
     /** The FFI type of this type */
     private final int type;
@@ -32,14 +35,22 @@ public abstract class Aggregate extends Type {
 
     private volatile boolean disposed = false;
 
+    /** A handle to the foreign interface to keep it alive as long as this object is alive */
+    private final Foreign foreign;
+
     public Aggregate(long handle) {
+        this(Foreign.getInstance(), handle);
+    }
+    
+    Aggregate(Foreign foreign, long handle) {
         if (handle == 0L) {
             throw new NullPointerException("Invalid ffi_type handle");
         }
+        this.foreign = foreign;
         this.handle = handle;
-        this.type = Foreign.getInstance().getTypeType(handle);
-        this.size = Foreign.getInstance().getTypeSize(handle);
-        this.align = Foreign.getInstance().getTypeAlign(handle);
+        this.type = foreign.getTypeType(handle);
+        this.size = foreign.getTypeSize(handle);
+        this.align = foreign.getTypeAlign(handle);
     }
     
     final long handle() {
@@ -64,7 +75,7 @@ public abstract class Aggregate extends Type {
         }
 
         disposed = true;
-        Foreign.getInstance().freeAggregate(handle);
+        foreign.freeAggregate(handle);
     }
 
     @Override
@@ -74,7 +85,8 @@ public abstract class Aggregate extends Type {
                 dispose();
             }
         } catch (Throwable t) {
-            t.printStackTrace(System.err);
+            Logger.getLogger(getClass().getName()).log(Level.WARNING, 
+                    "Exception when freeing FFI aggregate: %s", t.getLocalizedMessage());
         } finally {
             super.finalize();
         }
diff --git a/src/com/kenai/jffi/Array.java b/src/com/kenai/jffi/Array.java
index 520c1c6..3061ed2 100644
--- a/src/com/kenai/jffi/Array.java
+++ b/src/com/kenai/jffi/Array.java
@@ -33,7 +33,7 @@ public final class Array extends Aggregate {
      * @param fields The fields contained in the struct.
      */
     public Array(Type elementType, int length) {
-        super(Foreign.getInstance().newArray(elementType.handle(), length));
+        super(Foreign.getInstance(), Foreign.getInstance().newArray(elementType.handle(), length));
         this.elementType = elementType;
         this.length = length;
     }
diff --git a/src/com/kenai/jffi/CallContext.java b/src/com/kenai/jffi/CallContext.java
index 8c0de65..bb48632 100644
--- a/src/com/kenai/jffi/CallContext.java
+++ b/src/com/kenai/jffi/CallContext.java
@@ -18,6 +18,9 @@
 
 package com.kenai.jffi;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 /**
  * Native function call context
  *
@@ -43,6 +46,9 @@ public final class CallContext implements CallInfo {
     /** The parameter types of this function */
     private final Type[] parameterTypes;
 
+    /** A handle to the foreign interface to keep it alive as long as this object is alive */
+    private final Foreign foreign = Foreign.getInstance();
+    
     /**
      * Creates a new instance of <tt>Function</tt> with default calling convention.
      *
@@ -83,7 +89,7 @@ public final class CallContext implements CallInfo {
         final int flags = (!saveErrno ? Foreign.F_NOERRNO : 0)
                 | (convention == CallingConvention.STDCALL ? Foreign.F_STDCALL : Foreign.F_DEFAULT);
 
-        final long h = Foreign.getInstance().newCallContext(returnType.handle(),
+        final long h = foreign.newCallContext(returnType.handle(),
                 Type.nativeHandles(paramTypes), flags);
         if (h == 0) {
             throw new RuntimeException("Failed to create native function");
@@ -98,7 +104,7 @@ public final class CallContext implements CallInfo {
         this.parameterTypes = (Type[]) paramTypes.clone();
 
         this.parameterCount = paramTypes.length;
-        this.rawParameterSize = Foreign.getInstance().getFunctionRawParameterSize(h);
+        this.rawParameterSize = foreign.getFunctionRawParameterSize(h);
     }
 
     /**
@@ -152,7 +158,7 @@ public final class CallContext implements CallInfo {
         if (disposed) {
             throw new RuntimeException("context already freed");
         }
-        Foreign.getInstance().freeCallContext(contextAddress);
+        foreign.freeCallContext(contextAddress);
         disposed = true;
     }
 
@@ -160,10 +166,11 @@ public final class CallContext implements CallInfo {
     protected void finalize() throws Throwable {
         try {
             if (contextAddress != 0 && !disposed) {
-                Foreign.getInstance().freeCallContext(contextAddress);
+                foreign.freeCallContext(contextAddress);
             }
         } catch (Throwable t) {
-            t.printStackTrace(System.err);
+            Logger.getLogger(getClass().getName()).log(Level.WARNING, 
+                    "Exception when freeing CallContext: %s", t.getLocalizedMessage());
         } finally {
             super.finalize();
         }
diff --git a/src/com/kenai/jffi/ClosurePool.java b/src/com/kenai/jffi/ClosurePool.java
index f71e83d..dc45d47 100644
--- a/src/com/kenai/jffi/ClosurePool.java
+++ b/src/com/kenai/jffi/ClosurePool.java
@@ -31,6 +31,7 @@ final class ClosurePool {
     private final List<MagazineHolder> partial = new LinkedList<MagazineHolder>();
     private final List<MagazineHolder> full = new LinkedList<MagazineHolder>();
     private final Set<Magazine> magazines = new HashSet<Magazine>();
+
     //
     // Since the CallContext native handle is used by the native pool code
     // a strong reference to the call context needs to be kept.
@@ -138,6 +139,8 @@ final class ClosurePool {
     private static final class Magazine {
         /** Store a reference to the MemoryIO accessor here for easy access */
         private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
+        /** A handle to the foreign interface to keep it alive as long as this object is alive */
+        private final Foreign foreign = Foreign.getInstance();
 
         private final CallContext ctx;
         private final long magazine;
@@ -148,7 +151,7 @@ final class ClosurePool {
 
         Magazine(CallContext ctx) {
             this.ctx = ctx;
-            this.magazine = Foreign.getInstance().newClosureMagazine(ctx.getAddress(), Proxy.METHOD);
+            this.magazine = foreign.newClosureMagazine(ctx.getAddress(), Proxy.METHOD);
         }
 
         Slot get() {
@@ -161,7 +164,7 @@ final class ClosurePool {
 
         private Slot newSlot() {
             Proxy proxy = new Proxy(ctx);
-            long h = Foreign.getInstance().closureMagazineGet(magazine, proxy);
+            long h = foreign.closureMagazineGet(magazine, proxy);
             if (h == 0) {
                 nativeEmpty = true;
                 return null;
@@ -205,7 +208,7 @@ final class ClosurePool {
                 }
 
                 if (magazine != 0 && release) {
-                    Foreign.getInstance().freeClosureMagazine(magazine);
+                    foreign.freeClosureMagazine(magazine);
                 }
             } finally {
                 super.finalize();
diff --git a/src/com/kenai/jffi/Function.java b/src/com/kenai/jffi/Function.java
index d09e90c..1cfcea4 100644
--- a/src/com/kenai/jffi/Function.java
+++ b/src/com/kenai/jffi/Function.java
@@ -18,6 +18,9 @@
 
 package com.kenai.jffi;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 /**
  * Native function invocation context
  *
@@ -46,6 +49,9 @@ public final class Function implements CallInfo {
     /** Whether the native context has been freed yet */
     private volatile boolean disposed = false;
 
+    /** A handle to the foreign interface to keep it alive as long as this object is alive */
+    private final Foreign foreign = Foreign.getInstance();
+
     /**
      * Creates a new instance of <tt>Function</tt> with default calling convention.
      *
@@ -87,7 +93,7 @@ public final class Function implements CallInfo {
         final int flags = (!saveErrno ? Foreign.F_NOERRNO : 0)
                 | (convention == CallingConvention.STDCALL ? Foreign.F_STDCALL : Foreign.F_DEFAULT);
 
-        final long h = Foreign.getInstance().newFunction(address,
+        final long h = foreign.newFunction(address,
                 returnType.handle(), Type.nativeHandles(paramTypes),
                 flags);
         if (h == 0) {
@@ -103,7 +109,7 @@ public final class Function implements CallInfo {
         this.paramTypes = (Type[]) paramTypes.clone();
 
         this.parameterCount = paramTypes.length;
-        this.rawParameterSize = Foreign.getInstance().getFunctionRawParameterSize(h);        
+        this.rawParameterSize = foreign.getFunctionRawParameterSize(h);        
     }    
 
     /**
@@ -166,7 +172,7 @@ public final class Function implements CallInfo {
         if (disposed) {
             throw new RuntimeException("function already freed");
         }
-        Foreign.getInstance().freeFunction(contextAddress);
+        foreign.freeFunction(contextAddress);
         disposed = true;
     }
 
@@ -174,10 +180,11 @@ public final class Function implements CallInfo {
     protected void finalize() throws Throwable {
         try {
             if (contextAddress != 0 && !disposed) {
-                Foreign.getInstance().freeFunction(contextAddress);
+                foreign.freeFunction(contextAddress);
             }
         } catch (Throwable t) {
-            t.printStackTrace(System.err);
+            Logger.getLogger(getClass().getName()).log(Level.WARNING, 
+                    "Exception when freeing function context: %s", t.getLocalizedMessage());
         } finally {
             super.finalize();
         }
diff --git a/src/com/kenai/jffi/LastError.java b/src/com/kenai/jffi/LastError.java
index 9687999..f49bfb1 100644
--- a/src/com/kenai/jffi/LastError.java
+++ b/src/com/kenai/jffi/LastError.java
@@ -22,6 +22,7 @@ package com.kenai.jffi;
  * Provides access to the value of errno on unix, or GetLastError on windows.
  */
 public final class LastError {
+    private final Foreign foreign = Foreign.getInstance();
 
     /** Lazy-initialization singleton holder */
     private static final class SingletonHolder {
@@ -47,7 +48,7 @@ public final class LastError {
      */
     @Deprecated
     public final int getError() {
-        return Foreign.getInstance().getLastError();
+        return foreign.getLastError();
     }
 
     /**
@@ -56,7 +57,7 @@ public final class LastError {
      * @return The value of errno/GetLastError()
      */
     public final int get() {
-        return Foreign.getInstance().getLastError();
+        return foreign.getLastError();
     }
 
     /**
@@ -65,6 +66,6 @@ public final class LastError {
      * @param value The value to set errno to.
      */
     public final void set(int value) {
-        Foreign.getInstance().setLastError(value);
+        foreign.setLastError(value);
     }
 }
diff --git a/src/com/kenai/jffi/Library.java b/src/com/kenai/jffi/Library.java
index a6d292d..b57d5b5 100644
--- a/src/com/kenai/jffi/Library.java
+++ b/src/com/kenai/jffi/Library.java
@@ -37,7 +37,7 @@ public final class Library {
 
     /** A handle to the current process */
     private static final class DefaultLibrary {
-        private static final Library INSTANCE = new Library(null, dlopen(null, LAZY | GLOBAL));
+        private static final Library INSTANCE = openLibrary(null, LAZY | GLOBAL);
     }
 
     /** Perform  lazy  binding. Only resolve symbols as needed */
@@ -46,7 +46,7 @@ public final class Library {
     /** Resolve all symbols when loading the library */
     public static final int NOW    = Foreign.RTLD_NOW;
 
-    /** Symbols in this library are not made availabl to other libraries */
+    /** Symbols in this library are not made available to other libraries */
     public static final int LOCAL  = Foreign.RTLD_LOCAL;
 
     /** All symbols in the library are made available to other libraries */
@@ -58,6 +58,9 @@ public final class Library {
     /** The name of this <tt>Library</tt> */
     private final String name;
 
+    /** A handle to the foreign interface to keep it alive as long as this object is alive */
+    private final Foreign foreign;
+
     /**
      * Internal wrapper around dlopen.
      *
@@ -68,8 +71,7 @@ public final class Library {
      * @param flags The flags to pass to dlopen
      * @return The native handle for the opened library, or 0 if it failed to open.
      */
-    private static final long dlopen(String name, int flags) {
-        final Foreign foreign = Foreign.getInstance();
+    private static long dlopen(Foreign foreign, String name, int flags) {
         try {
             return foreign.dlopen(name, flags);
 
@@ -132,12 +134,14 @@ public final class Library {
             flags = LAZY | LOCAL;
         }
 
-        final long address = dlopen(name, flags);
+        final Foreign foreign = Foreign.getInstance();
+        final long address = dlopen(foreign, name, flags);
 
-        return address != 0L ? new Library(name, address) : null;
+        return address != 0L ? new Library(foreign, name, address) : null;
     }
     
-    private Library(String name, long address) {
+    private Library(Foreign foreign, String name, long address) {
+        this.foreign = foreign;
         this.name = name;
         this.handle = address;
     }
@@ -149,7 +153,6 @@ public final class Library {
      * @return The address of the symbol within the current address space.
      */
     public final long getSymbolAddress(String name) {
-        final Foreign foreign = Foreign.getInstance();
         try {
             return foreign.dlsym(handle, name);
 
@@ -173,7 +176,7 @@ public final class Library {
     protected void finalize() throws Throwable {
         try {
             if (handle != 0L) {
-                Foreign.getInstance().dlclose(handle);
+                foreign.dlclose(handle);
             }
         } finally {
             super.finalize();
diff --git a/src/com/kenai/jffi/MemoryIO.java b/src/com/kenai/jffi/MemoryIO.java
index 33b64cf..15c9e56 100644
--- a/src/com/kenai/jffi/MemoryIO.java
+++ b/src/com/kenai/jffi/MemoryIO.java
@@ -26,7 +26,7 @@ import java.lang.reflect.Method;
  */
 public abstract class MemoryIO {
     /** A handle to the JNI accessor */
-    private final Foreign foreign = Foreign.getInstance();
+    final Foreign foreign = Foreign.getInstance();
 
     /** The address mask used to truncate 32bit addresses contained in long values */
     private static final long ADDRESS_MASK = Platform.getPlatform().addressMask();
@@ -590,7 +590,7 @@ public abstract class MemoryIO {
      * An implementation of MemoryIO using JNI methods.
      */
     private static abstract class NativeImpl extends MemoryIO {
-        protected static final Foreign foreign = Foreign.getInstance();
+
         public final byte getByte(long address) {
             return foreign.getByte(address);
         }
diff --git a/src/com/kenai/jffi/PageManager.java b/src/com/kenai/jffi/PageManager.java
index f8230e0..e7208b9 100644
--- a/src/com/kenai/jffi/PageManager.java
+++ b/src/com/kenai/jffi/PageManager.java
@@ -31,6 +31,12 @@ abstract public class PageManager {
     /** The memory should be writable */
     public static final int PROT_WRITE = Foreign.PROT_WRITE;
 
+    private final Foreign foreign = Foreign.getInstance();
+
+    final Foreign getForeign() {
+        return foreign;
+    }
+
     private static final class SingletonHolder {
         public static final PageManager INSTANCE = Platform.getPlatform().getOS() == Platform.OS.WINDOWS
                 ? new Windows() : new Unix();
@@ -51,7 +57,7 @@ abstract public class PageManager {
      * @return The size of a page on the current system, in bytes.
      */
     public final long pageSize() {
-        return Foreign.getInstance().pageSize();
+        return getForeign().pageSize();
     }
 
     /**
@@ -90,19 +96,19 @@ abstract public class PageManager {
         @Override
         public long allocatePages(int npages, int protection) {
             long sz = npages * pageSize();
-            return Foreign.getInstance().mmap(0, sz, protection,
+            return getForeign().mmap(0, sz, protection,
                     Foreign.MAP_ANON | Foreign.MAP_PRIVATE, -1, 0);
 
         }
 
         @Override
         public void freePages(long address, int npages) {
-            Foreign.getInstance().munmap(address, npages * pageSize());
+            getForeign().munmap(address, npages * pageSize());
         }
 
         @Override
         public void protectPages(long address, int npages, int protection) {
-            Foreign.getInstance().mprotect(address, npages * pageSize(), protection);
+            getForeign().mprotect(address, npages * pageSize(), protection);
         }
     }
 
diff --git a/src/com/kenai/jffi/Struct.java b/src/com/kenai/jffi/Struct.java
index cc6dc53..e44dc4c 100644
--- a/src/com/kenai/jffi/Struct.java
+++ b/src/com/kenai/jffi/Struct.java
@@ -31,7 +31,7 @@ public final class Struct extends Aggregate {
      * @param fields The fields contained in the struct.
      */
     public Struct(Type... fields) {
-        super(Foreign.getInstance().newStruct(Type.nativeHandles(fields), false));
+        super(Foreign.getInstance(), Foreign.getInstance().newStruct(Type.nativeHandles(fields), false));
         this.fields = (Type[]) fields.clone();
     }
 }
diff --git a/src/com/kenai/jffi/Union.java b/src/com/kenai/jffi/Union.java
index bbe7eea..c531c3f 100644
--- a/src/com/kenai/jffi/Union.java
+++ b/src/com/kenai/jffi/Union.java
@@ -31,7 +31,7 @@ public final class Union extends Aggregate {
      * @param fields The fields contained in the struct.
      */
     public Union(Type... fields) {
-        super(Foreign.getInstance().newStruct(Type.nativeHandles(fields), true));
+        super(Foreign.getInstance(), Foreign.getInstance().newStruct(Type.nativeHandles(fields), true));
         this.fields = (Type[]) fields.clone();
     }
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jffi-next.git



More information about the pkg-java-commits mailing list