使用FileChannel 读取文件时,调用FileChannel.map()会将文件映射到内存中,大幅提升了读取速度
但是如果只是close流和FileChannel 是解除不了内存中的占用的,所以如果要删除这个文件或者进行其他操作的话,就需要解除map或者等待gc
方法是使用反射调用unmap方法(因为并未提供直接解除占用的方法)
Method m = FileChannelImpl.class.getDeclaredMethod("unmap", MappedByteBuffer.class);
m.setAccessible(true);
m.invoke(FileChannelImpl.class, byteBuffer);
代码如上
可是这时候又会出现如图,哇靠,图没了吗???
算了,反正就是permgen会一直增长,直到撑爆
因为这是新改动 所以定位问题时候一下就定位到这里,经过修改不使用FileChannel做读取文件,也避免了使用反射调用
根据网上帖子:http://rednaxelafx.iteye.com/blog/548536
说明了反射调用可能会出现的问题(未进行求证,由于permgen增长超级慢..观察了1个多小时还没出现问题,所以忙别的去了,有时间一定再进行求证)
好了就是这么多,如有不正确请批评指出,谢谢
后续:
本以为解决了问题的我飘得不能再飘了,打dota都有劲儿了,然后相隔几天tomcat再次爆掉,差点摔死我...
记:
本以为去掉这个反射就没有啥问题了,但是几天后tomcat的permgen再次爆掉,jstack 下来的文件中全都是locked,jmap下来的栈中没什么异常,显示线程也不都是locked,
这让我很头大,根本不知道如何查起了...
不过经过我不懈的google和百度,终于找到一种方法可以查到jvm一直在装载什么东西
感谢--http://www.kuqin.com/shuoit/20140614/340522.html
这里面的5:
5:查看perm中的类加载情况
在启动的脚本中打开-verbose:class来查看运行的过程中到底多少个类被加载了。【verbose和verbose:class意义相同, 还有-verbose:gc, -verbose:jni】
JAVA_OPTS="${JAVA_OPTS} -verbose:class"
我再tomcat加上之后重启tomcat,然后出现每次访问都会load sun.reflect.GeneratedSerializationConstructorAccessor ,(我这是2000台机器访问web服务),而且访问非常快,每次访问都会加载一次reflect,那问题出在哪里?
我使用springmvc做的,这每次访问都会出现,那就肯定出在一个通用的访问位置,我查看了自己的配置文件,最后发现我的日志aop切的是Controller...(太笨了我)
配置如下
<aop:pointcut id="aopRiZhi" expression="(execution(* com.xxx.*.controller.*.*(..)) )" />
再看记录日志的代码
Field f = jp.getTarget().getClass().getSuperclass().getDeclaredField("username");
我擦,反射!!reflect!!好吧,找到问题了,把配置文件中的aop注释掉,替换,上线.
so nice ,一点问题都没有了,permgen平的像飞机场一样.根本不增长...
这下这个问题才彻底解决,飘飘飘~~
感谢观看,如有指教/疑问请联系.还望不吝赐教,谢谢各位!