Java EE应用中的性能问题解决方案 — 第一部分 内存溢出的解决办法(C)

来源:互联网 发布:mac os websphere 编辑:程序博客网 时间:2024/04/24 15:48

声明:本文禁止未经本人同意的任何形式转载!如有转载需求,可与本人通过个人资料中的电子邮箱联系。对于未经同意的转载,本人将保留进一步行动的权利! 

 假内存泄露

有一些情况表现得很像内存泄露,但实际上并不是的。以下情况/地方有可能导致这样的错误判断:
  • 过早下结论
  • 会话
  • 永生代异常
 
下面我们就来一一讨论一下。
 
 
过早下结论
在查找内存泄露的过程中,重要的是要适时掌握观察和分析堆的情况。其中的问题在于,因为一些长期生存的对象需要被保留在堆中,所以必须要等到堆的状态比较稳定的情况下(只保留了核心对象的情况)才能不被假象蒙蔽。所以需要当应用达到稳定状态后才能执行对堆的分析。
 
检查是否过早对堆进行分析的办法是在记录了一次堆的情况后的一段时间内(比如几个小时)不断对堆的情况进行记录分析。如果堆不断增长的趋势已经结束,那么即可对堆进行记录。如果堆还有持续上升的趋势,则可对已有的内存情况进行分析并做出判断。
 
会话
我们在前面说过,内存泄露可能会出现在Web请求的阶段。但在Web请求阶段,对象可能被存储在少数明确的一些地方,包括:
  • 页面范围(Page)
  • 请求范围(Request)
  • 会话范围(Session)
  • 应用范围(Application)
  • 静态变量(static)
  • 长期生存的类变量,例如本身就在servlet中的那些
 
在JSP中,当页面完成后,JSP里本身创建的变量是符合垃圾收集的条件的,这些变量的生存周期是在一个页面范围内。
 
属性(attribute)和参数(parameter)从Web服务器传送到应用服务器,属性也可在servlet和JSP中通过HttpServletRequest对象传递。HttpServletRequest对象作为一种通信机制服务于动态web层上的不同的组件中,但当请求完成且关闭与用户socket连接时,servlet容器就将存储在HttpServletRequest对象中的所有变量的空间回收。这些变量的生存周期是在一个请求的范围内。
 
由于HTTP是一个无状态的协议,即意味着客户端请求服务器,服务器应答客户端后,通信即中止了,会话状态将不会得到保留。因此,我们需要一种机制能进行状态的保留,这就是会话(session)。属性和参数可根据不同的用户来存储到不同的HttpSession对象中,他们可以被应用中的servlet或JSP访问。这样,就可以将诸如登录、购物车等这样的信息添加到会话中,不同用户的状态就得到了保留。对于无状态的协议,总是客户端先提出对服务器的访问,这就需要让服务器知道两次访问的最大间隔时间,以便保存会话或放弃保存会话。这就使session time-out,可通过应用服务器配置。所以,除非用户主动移除会话中的对象或者会话失效,会话中的对象就会一直驻留在服务器上。
 
Session是在用户这个级别上管理对象的,ServletContext则是在应用这个级别上管理对象的。ServletContext之所以被称为是应用范围的,就是因为可以在其它servlet和JSP页面上共享servlet的ServletContext或JSP的application对象。ServletContext是最主要的应用配置信息和应用级别数据的缓存地点,例如数据JNDI等信息。
 
如果数据没有保存在这些范围内的对象中,还有可能保留在静态变量和长期生存的类变量中。
 
静态变量在JVM中以每个类一个的级别进行存储,且不需要堆中存在类的实例。所有类实例共享相同的静态变量值,所以在一个对象中改变静态变量的值会影响到其它对象中的值。所以,如果应用将对象保存在静态变量中并将该变量赋为null的话,该静态对象并不会被JVM回收。这些静态对象是内存泄露的主要发生地。
 
最后,我们将一些对象加入了像servlet之类的长期生存的类中作为内部数据结构或成员变量。当servlet被创建并被加载到内存,它只有一个实例在内存中,多个线程通过相应的配置来访问servlet实例。如果在init()方法中加载配置信息,将其存入类的变量中,并在服务请求的时候读取这些信息,这就确保了所有的实例都访问到了同样的信息。有时候有的应用使用servlet类变量来保存页面缓存的数据。这可能放错了地方。如果考虑使用cache的话,放到集成的第三方的缓存中可能是比较好的选择。
当页面或者请求范围的变量保持着对对象的引用时,它们会被自动清理掉。如果是会话级别变量中保存着对象引用的话,就没有那么容易了。
未完待续……
Java EE应用中的性能问题解决方案参考资料下载
声明:本文禁止未经本人同意的任何形式转载!如有转载需求,可与本人通过个人资料中的电子邮箱联系。对于未经同意的转载,本人将保留进一步行动的权利!