亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Groovy腳本引發的 Old GC問題怎么辦

發布時間:2021-10-21 14:17:29 來源:億速云 閱讀:183 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“Groovy腳本引發的 Old GC問題怎么辦”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Groovy腳本引發的 Old GC問題怎么辦”這篇文章吧。

示例代碼如下

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("groovy");

String function = String.format("def getTargetParamValue(%s) {return \"%s\"}", "o", "$o");
engine.eval(function);
Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("getTargetParamValue", "test-string");
System.out.println(result);

這段代碼定義了一個Groovy的方法,根據傳進去的參數返回對應的值。

由于生產環境流量很大,這段代碼被頻繁執行。測試時的代碼如下

public class ScriptEngineTest {

    public static void main(String[] args) {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("groovy");
        //測試時改為死循環
        for (int i = 0;; i++) {
            try {

                String function = String.format("def getTargetParamValue(%s) {return \"%s\"}", "o", "$o");
                engine.eval(function);
                Invocable invocable = (Invocable) engine;

                Object result = invocable.invokeFunction("getTargetParamValue", "test-string");
                System.out.println(result);

                TimeUnit.MICROSECONDS.sleep(100);

                System.out.println(new Date().toLocaleString());

            } catch (Exception e) {
                String errorMsg = String.format("異常!%s", e.getMessage());
                System.out.println(errorMsg);
            }

        }
    }
}

模擬生產環境的情況,每秒鐘執行10次。通過VusualVM觀察JVM

  • CPU使用情況,可以看到在每次堆內存擴容的時候,CPU使用量會有明顯增加
    Groovy腳本引發的 Old GC問題怎么辦

  • 堆內存使用情況
    Groovy腳本引發的 Old GC問題怎么辦

  • metaspace使用量一直在增加
    Groovy腳本引發的 Old GC問題怎么辦

  • 類加載情況,total loaded classes一直在增加
    Groovy腳本引發的 Old GC問題怎么辦

  • 線程
    Groovy腳本引發的 Old GC問題怎么辦

  • dump內存
    Groovy腳本引發的 Old GC問題怎么辦

可見,每次循環中生成的 Groovy method在方法執行完成之后并沒有被釋放掉,導致metaspace的使用量一直增加,最終撐爆JVM

針對以上問題,解決方法為每次將生成的方法緩存下了,下次要執行的時候從緩存中取。

private final ConcurrentHashMap<String, Invocable> concurrentHashMap = new ConcurrentHashMap<>();

private Object getInvokeResult(Object targetParam, String paramName, String expression) throws Exception {
    //targetParamClassName="com.umgsai.web.home.vo.NodeVO"
    String targetParamClassName = targetParam.getClass().getName();
    //expression="$nodeVO.bizOwner"
    //paramName="nodeVO"
    String functionKey = String.format("%s_%s_%s", targetParamClassName, paramName, expression);
    functionKey = StringUtil.replaceChars(functionKey, "$", "");
    functionKey = StringUtil.replaceChars(functionKey, ".", "_");
    //functionKey為方法的名稱和concurrentHashMap的key,這里需要去掉特殊字符

    Invocable invocable = concurrentHashMap.get(functionKey);
    if (invocable != null) {
        //如果緩存中有,直接調用
        return invocable.invokeFunction(functionKey, targetParam);
    }

   //如果緩存中沒有,生成方法,并且存到concurrentHashMap
    synchronized (lock) {
        invocable = concurrentHashMap.get(functionKey);
        if (invocable == null) {
            String function = String.format("def %s(%s) {return \"%s\"}", functionKey, paramName, expression);
            engine.eval(function);
            invocable = (Invocable) engine;
            concurrentHashMap.put(functionKey, invocable);
            if (log.isInfoEnabled()) {
                String msg = String.format("Create new Groovy function, functionKey=%s, paramName=%s, expression=%s",
                        functionKey,
                        paramName, expression);
                log.info(msg);
            }
        }
    }

    if (log.isInfoEnabled()) {
        log.info(String.format("Groovy function concurrentHashMap.size=%d", concurrentHashMap.size()));
    }

    return invocable.invokeFunction(functionKey, targetParam);
}

以上是“Groovy腳本引發的 Old GC問題怎么辦”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大化| 靖宇县| 河南省| 西畴县| 广南县| 宜春市| 桦甸市| 重庆市| 宝丰县| 拉萨市| 右玉县| 孟津县| 黄龙县| 乌苏市| 万全县| 广饶县| 平南县| 巴塘县| 松桃| 财经| 呼和浩特市| 天全县| 博白县| 舞阳县| 延寿县| 绥中县| 青海省| 巴中市| 池州市| 和龙市| 祁连县| 永修县| 巴马| 岳西县| 龙江县| 洛南县| 祁阳县| 荃湾区| 邵武市| 黎平县| 兰州市|