You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2019/09/21 15:30:59 UTC

[isis] branch v2 updated: ISIS-2158: share the _MethodCache on the _Context

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/v2 by this push:
     new 76ea7bf  ISIS-2158: share the _MethodCache on the _Context
76ea7bf is described below

commit 76ea7bf6a851ca23d0fbd55629119bb80ae3c89c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Sep 21 17:30:50 2019 +0200

    ISIS-2158: share the _MethodCache on the _Context
---
 .../isis/commons/internal/collections/_Arrays.java | 17 +++++++-
 .../commons/internal/reflection/_MethodCache.java  | 48 +++++++++++++---------
 .../isis/metamodel/facets/MethodFinderUtils.java   |  5 ++-
 .../isis/runtime/system/MethodFinderUtilsTest.java |  8 +++-
 4 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java b/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java
index 49e28b3..faf6965 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java
@@ -247,7 +247,22 @@ public final class _Arrays {
         System.arraycopy(array, index+1, result, index, remaining);
         return result;
     }
-
+    
+    /**
+     * Returns {@code null} if given {@code array} is {@code null} or of length zero, 
+     * returns given {@code array} otherwise.
+     *  
+     * @param <T>
+     * @param array
+     * @return null for empty arrays
+     */
+    public static @Nullable <T> T[] emptyToNull(T[] array) {
+        if(array!=null && array.length==0) {
+            return null;
+        }
+        return array;
+    }
+    
     // -- COMPONENT TYPE INFERENCE
 
     /**
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java b/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java
index 3ca0acc..6618481 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java
@@ -24,30 +24,41 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.isis.commons.internal.context._Context;
+
+import static org.apache.isis.commons.internal.collections._Arrays.emptyToNull;
+
+import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
 import lombok.val;
 
 /**
  * <h1>- internal use only -</h1>
  * <p>
- * JDK reflection API has no Class.getMethod(name, ...) variant that does not produce an expensive 
- * stack-trace, when no such method exists. 
- * 
- * @apiNote thread-save 
- * 
- * </p>
- * <p>
  * <b>WARNING</b>: Do <b>NOT</b> use any of the classes provided by this package! <br/>
  * These may be changed or removed without notice!
  * </p>
+ * <p>
+ * Motivation: JDK reflection API has no Class.getMethod(name, ...) variant that does not produce an expensive 
+ * stack-trace, when no such method exists. 
+ * </p> 
+ * @apiNote 
+ * thread-save, implements AutoCloseable so we can put it on the _Context, which then automatically 
+ * takes care of the lifecycle
  * @since 2.0
  */
-public final class _MethodCache {
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class _MethodCache implements AutoCloseable {
+    
+    public static _MethodCache getInstance() {
+        return _Context.computeIfAbsent(_MethodCache.class, _MethodCache::new);
+    }
 
     /**
-     * A drop-in replacement for {@link Class#getMethod(String, Class...)} that does not throw 
-     * a {@link ClassNotFoundException}   
+     * A drop-in replacement for {@link Class#getMethod(String, Class...)} that only looks up 
+     * public methods and does not throw {@link NoSuchMethodException}s.    
      */
     public Method lookupMethod(Class<?> type, String name, Class<?>[] paramTypes) {
         
@@ -60,7 +71,7 @@ public final class _MethodCache {
             }
         }
         
-        return methodsByKey.get(Key.of(type, name, nullify(paramTypes)));
+        return methodsByKey.get(Key.of(type, name, emptyToNull(paramTypes)));
     }
 
     public int size() {
@@ -79,19 +90,18 @@ public final class _MethodCache {
         private final Class<?>[] paramTypes;
         
         public static Key of(Class<?> type, Method method) {
-            return Key.of(type, method.getName(), nullify(method.getParameterTypes()));
+            return Key.of(type, method.getName(), emptyToNull(method.getParameterTypes()));
         }
         
-        
     }
-    
-    private static Class<?>[] nullify(Class<?>[] x) {
-        if(x!=null && x.length==0) {
-            return null;
+
+    @Override
+    public void close() throws Exception {
+        synchronized(inspectedTypes) {
+            inspectedTypes.clear();
+            methodsByKey.clear();
         }
-        return x;
     }
     
     
-    
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodFinderUtils.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodFinderUtils.java
index 92d5a9e..66e761b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodFinderUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodFinderUtils.java
@@ -45,7 +45,7 @@ public final class MethodFinderUtils {
         return method;
     }
     
-    private static final _MethodCache methodCache = new _MethodCache(); //TODO could be share on the context
+    //private static final _MethodCache methodCache = new _MethodCache(); //TODO could be share on the context
 
     /**
      * Returns a specific public methods that: have the specified prefix; have
@@ -66,6 +66,9 @@ public final class MethodFinderUtils {
             final Class<?> returnType,
             final Class<?>[] paramTypes) {
         
+        
+        val methodCache = _MethodCache.getInstance();
+        
         val method = methodCache.lookupMethod(type, name, paramTypes);
         if(method == null) {
             return null;
diff --git a/core/runtime/src/test/java/org/apache/isis/runtime/system/MethodFinderUtilsTest.java b/core/runtime/src/test/java/org/apache/isis/runtime/system/MethodFinderUtilsTest.java
index fb2ca4e..3b3ed39 100644
--- a/core/runtime/src/test/java/org/apache/isis/runtime/system/MethodFinderUtilsTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/runtime/system/MethodFinderUtilsTest.java
@@ -60,8 +60,12 @@ public class MethodFinderUtilsTest {
     }
 
     @Parameters
-    public static Collection parameters() {
-        return Arrays.asList(new Object[][] { { MethodScope.OBJECT, staticMethod, false }, { MethodScope.CLASS, staticMethod, true }, { MethodScope.OBJECT, instanceMethod, true }, { MethodScope.CLASS, instanceMethod, false }, });
+    public static Collection<?> parameters() {
+        return Arrays.asList(new Object[][] { 
+            { MethodScope.OBJECT, staticMethod, false }, 
+            { MethodScope.CLASS, staticMethod, true }, 
+            { MethodScope.OBJECT, instanceMethod, true }, 
+            { MethodScope.CLASS, instanceMethod, false }, });
     }
 
     public static void someStaticMethod() {