11回复
3年前
求助OutOfMemoryError:MetaSpace
生产环境系统里有400多个groovy脚本,可以通过管理端修改数据库中的脚本,并发布(读取groovy脚本并编译成script对象,缓存到内存),大概逻辑如下
//1、创建临时的存放script的tempMap
Map<String,Script>tempMap=new HashMap();
//2、查数据库得到脚本文本
Map<String,String>
scriptTextMap=scriptService.selectAll();
//3、遍历id:scriptTextMap,生成Script对象,大概代码如下
for(String id:scriptTextMap.keySet()){
GroovyShell shell=new GroovyShell(new Binding());
Script script= shell.parse(scriptTextMap.get(id));
tempMap.put(id,script);
}
//4、全局scriptMap替换为tempMap
scriptMap=tempMap;
}
元数据空间128m,最大256m,堆3g,新生代2g,cms收集器
问题:运行一段时间后,load方法会抛 OutOfMemoryError:MetaSpace,查看gc日志,发现full gc前后,metaSpace used大概120M,capacity 171M,committed 248M。
上网搜了一些回答,有的说是 由于每次parse都会创建新的类加载器,每个类加载器即使加载一个对象,也会在metaSpace中占据一个内存块。但是,每次load执行后,旧的scriptMap就会被回收掉,旧的Script对象也会被回收,编译groovy生产的类应该也可以被卸载,full gc时,MetaSpace中的空间应该能够被回收,请各位大佬们帮忙看看。
3840 阅读