fastjson 1.2.5
从携程获取机票订单详情的时候,返回的json对象较为复杂且内容巨多,同事通过fastjson解析成java对象。用户每次请求都会执行如下代码片段:
ParserConfig,XmlDateTypeDeserializer,DateTypeDeserializerS这三个类是工具类为什么要每次请求的时候都要new呢,明显可以作为工具使用,先不纠结这个。咱先重现内存溢出,永久代的内存溢出,模拟http请求,同时发起1000个,果然内存溢出了。
1.通过jsp -l 发现jetty 容器的pid=2557
2. jstat -gc 2557 250 20
发现jvm一直在进行ygc和fgc,而且永久代已经用完了,难道上述代码真能引起PermGen spac吗?我们知道永久带主要是存储的是java的类信息,包括解析得到的方法、属性、字段,深入java虚拟机中介绍常量池也是属于永久代,永久代=方法区+运行时常量池。
3.jmap -histo -F 2557 加上"-F"就会强制执行 显示对中的对象统计信息
发现json在使用asm生产了很多代理类
初步猜想是fastjson在通过动态代理的时候生成了代理类,每次请求都会生成新的代理,导致永久代一直加载新的类信息,结果PermGen spac出现了。
4.查看代码验证猜想,把 ParserConfig,XmlDateTypeDeserializer,DateTypeDeserializer放到静态块内初始化,这样三个类只有一个实例,通过修改代码并测试,发现少了ASM生成的动态代理类,异常也不见了。
5.这到底是为什么呢?为什么在new ParserConfig,XmlDateTypeDeserializer,DateTypeDeserializer这个三个类的时候会生成很多代理呢?并且还有其他动态代理类出现了,继续研究fastjson源码。