Merge pull request #677 from soenter/master

增加class的加载缓存,解决频繁加载class会使jvm的方法区空间不足导致OOM的问题
pull/8/MERGE
许雪里 6 years ago committed by GitHub
commit 3e9fe7baa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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

@ -4,6 +4,10 @@ import com.xxl.job.core.glue.impl.SpringGlueFactory;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyClassLoader;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* glue factory, product class/object by name * glue factory, product class/object by name
* *
@ -30,6 +34,8 @@ public class GlueFactory {
*/ */
private GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); 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<>();
/** /**
* load new instance, prototype * load new instance, prototype
@ -38,9 +44,9 @@ public class GlueFactory {
* @return * @return
* @throws Exception * @throws Exception
*/ */
public IJobHandler loadNewInstance(String codeSource) throws Exception{ public IJobHandler loadNewInstance(long jobId, String codeSource) throws Exception{
if (codeSource!=null && codeSource.trim().length()>0) { if (codeSource!=null && codeSource.trim().length()>0) {
Class<?> clazz = groovyClassLoader.parseClass(codeSource); Class<?> clazz = getCodeSourceClass(jobId, codeSource);
if (clazz != null) { if (clazz != null) {
Object instance = clazz.newInstance(); Object instance = clazz.newInstance();
if (instance!=null) { if (instance!=null) {
@ -66,4 +72,28 @@ public class GlueFactory {
// do something // do something
} }
private Class<?> getCodeSourceClass(long jobId, 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);
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);
}
}
}
return clazz;
} catch (Exception e) {
return groovyClassLoader.parseClass(codeSource);
}
}
} }

Loading…
Cancel
Save