这个是怎么发现的呢,虽然没有引发OOM,但是自从我接手这个项目以后,前期都是改bug,写新需求,最近疫情在家,并且新做的小程序等待审核的期间,发现了个线上问题;发现每隔一段时间,一般是一两周,线上的堆内存就逐渐增大,虽然很缓慢的增长,但是使用jmap -heap命令查看到老年代也是越来越大,以往的gc没有起作用,正常来说内存占用应该是从部署逐步上升到保持一个稳定的水平。
1.使用命令获取jvm内存dump:
jmap -dump:format=b,file=10339.hprof 10339

2.使用工具自动分析大概率有问题的内存占用线程及实例:

大概看到了是这个DIsposer中的Hashtable占用了很大的内存;
3.查看按照内存占用降序的实例数:


其实现在通过其中的内容已经看到了一些端倪,就是TrueTypeFont的其中字符串变量是HYHeiFangW,这个是以前开发人员封装的字体工具中使用到的;
4.查看代码:
static Font registerFont(String fontFileName,int style, float fontSize){
if(fontFileName == null){
fontFileName = HYHFW;
}
Font font = null;
try {
URL url = AbstractPenAndBackground.class.getClassLoader().getResource(fontFileName);
File fontFile = new File(url.getFile());
font = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(style,fontSize);
//GraphicsEnvironment ge = GraphicsEnvironment .getLocalGraphicsEnvironment();
//ge.registerFont(font);
} catch (FontFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return font;
}
注释的代码就是引发内存泄漏的地方,跟进去代码可以看到:
sun.font.SunFontManager#registerFont方法:
AppContext var8 = AppContext.getAppContext();
var6 = (Hashtable)var8.get(regFamilyKey);
var7 = (Hashtable)var8.get(regFullNameKey);
if (var6 == null) {
var6 = new Hashtable();
var7 = new Hashtable();
var8.put(regFamilyKey, var6);
var8.put(regFullNameKey, var7);
}
this.fontsAreRegisteredPerAppContext = true;
}
Font2D var12 = FontUtilities.getFont2D(var1);
int var9 = var12.getStyle();
FontFamily var10 = (FontFamily)var6.get(var4);
if (var10 == null) {
var10 = new FontFamily(var1.getFamily(var3));
var6.put(var4, var10);
}
每次调用字体工具方法,都会将新的Font实例放到静态Hashtable中;解决方法其实就是要么取消这个操作,要么将Font也单例化;
1021

被折叠的 条评论
为什么被折叠?



