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

albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new 8e5eac1  fix  cache Class avoid PermGen space OOM in dubbo3.0 (#7386)
8e5eac1 is described below

commit 8e5eac1acff7fa987dd3a2b4dfaaa5137b673f1d
Author: xiaoheng1 <[email protected]>
AuthorDate: Tue Apr 13 14:31:56 2021 +0800

    fix  cache Class avoid PermGen space OOM in dubbo3.0 (#7386)
    
    * fix #6742 cache Class avoid PermGen space OOM
    
    * optimization cache Class avoid PermGen space OOM
    
    * optimization cache Class avoid PermGen space OOM
    
    * Optimize Proxy WeakReference to SoftReference
---
 .../org/apache/dubbo/common/bytecode/Proxy.java    | 53 ++++++++++++++++++----
 1 file changed, 43 insertions(+), 10 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java 
b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
index bb2b40b..c7fc5b2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
 
 import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -50,6 +50,8 @@ public abstract class Proxy {
     private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);
     private static final String PACKAGE_NAME = 
Proxy.class.getPackage().getName();
     private static final Map<ClassLoader, Map<String, Object>> PROXY_CACHE_MAP 
= new WeakHashMap<ClassLoader, Map<String, Object>>();
+    // cache class, avoid PermGen OOM.
+    private static final Map<ClassLoader, Map<String, Object>> PROXY_CLASS_MAP 
= new WeakHashMap<ClassLoader, Map<String, Object>>();
 
     private static final Object PENDING_GENERATION_MARKER = new Object();
 
@@ -103,8 +105,11 @@ public abstract class Proxy {
 
         // get cache by class loader.
         final Map<String, Object> cache;
+        // cache class
+        final Map<String, Object> classCache;
         synchronized (PROXY_CACHE_MAP) {
             cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new HashMap<>());
+            classCache = PROXY_CLASS_MAP.computeIfAbsent(cl, k -> new 
HashMap<>());
         }
 
         Proxy proxy = null;
@@ -118,14 +123,38 @@ public abstract class Proxy {
                     }
                 }
 
-                if (value == PENDING_GENERATION_MARKER) {
-                    try {
-                        cache.wait();
-                    } catch (InterruptedException e) {
+                // get Class by key.
+                Object clazzObj = classCache.get(key);
+                if (null == clazzObj || clazzObj instanceof Reference<?>) {
+                    Class<?> clazz = null;
+                    if (clazzObj instanceof Reference<?>) {
+                        clazz = (Class<?>) ((Reference<?>) clazzObj).get();
+                    }
+
+                    if (null == clazz) {
+                        if (value == PENDING_GENERATION_MARKER) {
+                            try {
+                                cache.wait();
+                            } catch (InterruptedException e) {
+                            }
+                        } else {
+                            cache.put(key, PENDING_GENERATION_MARKER);
+                            break;
+                        }
+                    } else {
+                        try {
+                            proxy = (Proxy) clazz.newInstance();
+                            return proxy;
+                        } catch (InstantiationException | 
IllegalAccessException e) {
+                            throw new RuntimeException(e);
+                        } finally {
+                            if (null == proxy) {
+                                cache.remove(key);
+                            } else {
+                                cache.put(key, new SoftReference<>(proxy));
+                            }
+                        }
                     }
-                } else {
-                    cache.put(key, PENDING_GENERATION_MARKER);
-                    break;
                 }
             }
             while (true);
@@ -190,7 +219,7 @@ public abstract class Proxy {
             ccp.setClassName(pcn);
             ccp.addField("public static java.lang.reflect.Method[] methods;");
             ccp.addField("private " + InvocationHandler.class.getName() + " 
handler;");
-            ccp.addConstructor(Modifier.PUBLIC, new 
Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
+            ccp.addConstructor(Modifier.PUBLIC, new Class<?>[] 
{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
             ccp.addDefaultConstructor();
             Class<?> clazz = ccp.toClass();
             clazz.getField("methods").set(null, methods.toArray(new 
Method[0]));
@@ -204,6 +233,10 @@ public abstract class Proxy {
             ccm.addMethod("public Object newInstance(" + 
InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
             Class<?> pc = ccm.toClass();
             proxy = (Proxy) pc.newInstance();
+
+            synchronized (classCache) {
+                classCache.put(key, new SoftReference<Class<?>>(pc));
+            }
         } catch (RuntimeException e) {
             throw e;
         } catch (Exception e) {
@@ -220,7 +253,7 @@ public abstract class Proxy {
                 if (proxy == null) {
                     cache.remove(key);
                 } else {
-                    cache.put(key, new WeakReference<Proxy>(proxy));
+                    cache.put(key, new SoftReference<Proxy>(proxy));
                 }
                 cache.notifyAll();
             }

Reply via email to