Browse Source

新增Class的加载缓存,解决频繁加载Class会使jvm的方法区空间不足导致OOM的问题;

xuxueli 6 years ago
parent
commit
e6483c4b26

+ 2 - 1
doc/XXL-JOB官方文档.md

@@ -1425,7 +1425,8 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
 - 11、执行器回调日志落盘方案复用RPC序列化方案,并移除Jackson依赖;
 - 12、任务支持更换绑定执行器,方便任务分组转移和管理;
 - 13、执行器热部署时JobHandler重新初始化,修复由此导致的 "jobhandler naming conflicts." 问题;
-- 14、[迭代中]任务线程隔离:
+- 14、新增Class的加载缓存,解决频繁加载Class会使jvm的方法区空间不足导致OOM的问题;
+- 15、[迭代中]任务线程隔离:
     - 执行器测异步响应,不存在阻塞不需要隔离;
     - 调度中心共用单一调度线程池,可能导致调度阻塞需要线程隔离;调度线程池拆分为Fast/Slow两个,针对调度较慢的执行器地址请求,降级使用Slow线程池;考虑是否可以任务级隔离线程池;
 

+ 1 - 1
xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java

@@ -113,7 +113,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
             // valid handler
             if (jobHandler == null) {
                 try {
-                    IJobHandler originJobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getJobId(), triggerParam.getGlueSource());
+                    IJobHandler originJobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getGlueSource());
                     jobHandler = new GlueJobHandler(originJobHandler, triggerParam.getGlueUpdatetime());
                 } catch (Exception e) {
                     logger.error(e.getMessage(), e);

+ 19 - 29
xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueFactory.java

@@ -33,9 +33,7 @@ public class GlueFactory {
 	 * groovy class loader
 	 */
 	private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
-
-	private static final ConcurrentHashMap<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>();
-	private static final ConcurrentHashMap<Long, String> JOBID_MD5KEY_CACHE = new ConcurrentHashMap<>();
+	private ConcurrentHashMap<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>();
 
 	/**
 	 * load new instance, prototype
@@ -44,9 +42,9 @@ public class GlueFactory {
 	 * @return
 	 * @throws Exception
 	 */
-	public IJobHandler loadNewInstance(long jobId, String codeSource) throws Exception{
+	public IJobHandler loadNewInstance(String codeSource) throws Exception{
 		if (codeSource!=null && codeSource.trim().length()>0) {
-			Class<?> clazz = getCodeSourceClass(jobId, codeSource);
+			Class<?> clazz = getCodeSourceClass(codeSource);
 			if (clazz != null) {
 				Object instance = clazz.newInstance();
 				if (instance!=null) {
@@ -62,38 +60,30 @@ public class GlueFactory {
 		}
 		throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null");
 	}
-
-	/**
-	 * inject service of bean field
-	 *
-	 * @param instance
-	 */
-	public void injectService(Object instance) {
-		// do something
-	}
-
-	private Class<?> getCodeSourceClass(long jobId, String codeSource){
+	private Class<?> getCodeSourceClass(String codeSource){
 		try {
-			MessageDigest md = MessageDigest.getInstance("MD5");
-			byte[] md5 = md.digest(codeSource.getBytes());
-			BigInteger no = new BigInteger(1, md5);
-			String md5Str = no.toString(16);
+			// md5
+			byte[] md5 = MessageDigest.getInstance("MD5").digest(codeSource.getBytes());
+			String md5Str = new BigInteger(1, md5).toString(16);
+
 			Class<?> clazz = CLASS_CACHE.get(md5Str);
 			if(clazz == null){
 				clazz = groovyClassLoader.parseClass(codeSource);
-				Class<?> preClazz = CLASS_CACHE.putIfAbsent(md5Str, clazz);
-
-				// 如果代碼有變化則刪除之前class緩存
-				if(preClazz == null){
-					String preMd5 = JOBID_MD5KEY_CACHE.put(jobId, md5Str);
-					if(preMd5 != null){
-						CLASS_CACHE.remove(preMd5);
-					}
-				}
+				CLASS_CACHE.putIfAbsent(md5Str, clazz);
 			}
 			return clazz;
 		} catch (Exception e) {
 			return groovyClassLoader.parseClass(codeSource);
 		}
 	}
+
+	/**
+	 * inject service of bean field
+	 *
+	 * @param instance
+	 */
+	public void injectService(Object instance) {
+		// do something
+	}
+
 }