最近越来越关注j2ee程序性能的问题,怎样改善自己的代码,怎样对程序调优、怎样架构应用、怎样调整服务器等等,终于发现一篇,以后好好研究一下。
J2EE应用程序中的性能提升
--清除耗时且低效的bug
Java很热门,尽管只诞生了9年,但它已经成为世界上领先的开发环境之一。数百万的程序员和数千家公司都在使用它,而且半数IT管理者都希望在今年部署J2EE应用程序。
但是Java的流行并不一定使之对于日益增长的Java代码开发人员变得容易。为了在生产上达到一个新的高度,程序员们逐渐在更大的团队中工作,而在他们当中,持续缩短开发周期始终很热门。每天,那些团队都要面对一个软件开发中的不变定律:您编写的代码越多,您就会碰到越多的bug——而且是浪费时间和降低应用程序质量和性能的bug。
本文主要介绍了一个J2EE应用程序的性能调优和内存使用优化。我们设置使用 BEA WebLogic Application Server。我们将讨论以下几个方面:
- 问题域
- 调优Java虚拟机
- HTTP session管理
- 调优应用服务器
- 编码标准:为未来放弃规则
问题域
我们有一个如下设置的J2EE应用程序:
- BEA WebLogic 6.1 Service Pack 5 作为应用/Web服务器。
- 某个流行的RDBMS。对我们的讨论没有影响。
- Model I Web Architecture。
- 8个无状态EJB以及6个有状态EJB。
- HTTP session拥有对有状态EJB的引用。
- Database Connection Pool初始化为2,最大值为10。
- 在Web层有大约120个servlet。
- 基于XML/XSLT的体系结构。
问题
应用程序有一个内存问题。当服务器启动时,内存使用率大约占全部可用物理内存的7~8%。随着时间的推移和更多地使用应用程序,内存使用率会增加到接近49~53%(7~10天一个周期)。
如果用户通过点击左边菜单中的“Log off”按钮从他们的会话中注销,那么应用程序就会从服务器中删去所有的有状态bean。但是,如果一个用户仅仅只是关闭浏览器窗口,那它就不会删去那些bean,而会在容器中保留它们直到应用服务器重新启动为止。这样继续下去,内存中的EJB实例数量会增加到400个甚至更多。
当BEA WebLogic Server装载了多于400个EJB时,Hotspot虚拟机会抛出一个OutOfMemory 异常。尽管看似还有更多内存可用,但这种情况还是会发生。
调优Java虚拟机
当试图分配PermGeneration空间时,Hotspot虚拟机会抛出OutOfMemory异常。Hotspot虚拟机使用不同部分的内存。持久生成部分被用来储存类、方法以及运行的Java对象所使用的符号。持久生成部分的初始大小为1MB,最大值为64MB,1.3.1之前是32MB。
要避免这种情况,我们可以通过一个Java虚拟机开关,使用下面的命令行来设置permGeneration空间。
java -server -XX:MaxPermSize=128M.
注意,增加perm 最大值只是推迟了故障的发生。最终还是要靠您的应用程序去适当地清除无用的对象。另外,并非所有的Java虚拟机都支持XX选项。
HTTP Session 管理
当用户没有从会话中注销就关闭浏览器时,用户会话中的EJB不会被垃圾收集。这就是内存中有太多EJB的主要原因。要避免这种情况,HTTP session 管理必须注意所有可能的结合。我们可以在web.xml (Web应用程序部署描述符)中设置一个默认的会话超时周期,如下所示:
<session-config>
<session-timeout>x</session-timeout>
<session-config>
通过这个设置,用户的会话会在不活动x分钟后自动释放。
另一种方法是在创建HTTP session时用下面的代码编写会话管理
HttpSession session=new HttpSession ();
session.setmaxinactiveinternal(int timeoutSeconds);
这段代码会使不活动了timeoutSeconds时间的用户会话失效。
注意:如果您把两个步骤都做了,那么在servlet代码中的值将覆盖在web.xml中设置的值。
这两种方法惟一的不同点是第二种方法以秒作为参数,而 <session-timeout> 标记则是以分钟作为参数。通常,当会话失效后,logoff servlet/JSP 会用代码删去被特殊会话所引用的所有对象/对象图形的引用。但是当用户只是关闭浏览器时,就没有办法调用注销servlet/JSP。在这种情况下,即使会话已经失效,被封装的对象和对象图形会继续存在。当垃圾收集器试图对该会话进行垃圾收集时,它也会对所有这些封装对象进行收集。当我们有大对象时(拥有大的引用/数据的对象),我们也可以用HTTPSessionListener接口来进行同样的清除工作。
javax.servlet.http.HTTPSessionListener 接口
该接口声明了下面两种回调方法:
Public void sessionCreated(HttpSessionEvent event);
Public void sessionDestroyed(HttpSessionEven event);
这些方法在一个会话被创建/销毁前被调用。
我们可以使用一个实现了这个接口的监听器类,并用这些回调方法来控制会话的创建和销毁。我们需要像下面这样在web.xml中注册我们的监听器类:
<listener>
<listener-class>MySessionListener</listener-class>
</listener>
使用监听器类以及在web.xml文件中添加会话超时参数的好处是我们能对会话管理进行更多的控制。如果会话拥有大对象,那么在垃圾收集器清除这些对象之前,它的时间片可能会消失。在这种情况下,就需要等到下一个时间片才能清除这些对象。
注意:我们所设计的应用程序只有一个进入点是很重要的。我们需要在这个类中启动一个新的 HTTP session。所有余下的页面应该检查 HTTP session 是否存在,并且当会话为null时(Session 到期)调入一个错误页面。这样就可以实现对 HTTP session 的集中控制。
调优应用服务器
BEA WebLogic 提供了一些参数,我们能用它们优化bean池的大小,这包括设置无状态bean 池的初始大小。以下是一些使用方法:
- 用 <initial-bean-pool-size> 标记为无状态会话 bean设置 bean 池的最小值:默认情况下,这个值是1000。因为无状态会话bean可以在并发用户之间共享,所以最好把这个值设置得特别小。该标记的合适值取决于并发用户以及应用程序的峰值载入情况。
- 用 <max-beans-in-free-pool> 标记为有状态会话bean设置bean 池的最大值: 它的默认值没有被规定。该标记所设置的值会极大地影响到BEA WebLogic Server的激活与钝化机制。它的合适值取决于应用程序的流量。当池中bean的数量已经达到了阈值而又有一个对新bean实例的请求到达时,WebLogic Server会挑选池中一个或更多的bean来钝化。为钝化而挑选bean实例的算法是LRU(最近最少使用)或者NRU (最近没有使用)。
如果达到了max-beans-in-cache且高速缓存中的EJB并没有正在使用,WebLogic Server会把其中某些bean钝化。尽管没用的bean还没有达到它们的 idle-timeout-seconds极限,但这也会发生。如果达到了max-beans-in-cache且高速缓存中的EJB正在被客户端使用,那么WebLogic Server就会抛出一个CacheFullException异常。 - 用 <idle-timeout-seconds> 标记设置WebLogic Server在钝化一个空闲的有状态 会话 bean实例前所等待的时间:WebLogic Server会在从交换(swap)空间中删出bean之前等待同样长的时间。应该小心设置这个值,因为一旦从交换空间中删去钝化的实例,就没有办法重新获得该bean的状态了。
例如,考虑下面的设置
<idle-timeout-seconds>1200</idle-timeout-seconds>
这个空闲bean实例将会在静止20分钟后被钝化。再过20分钟,这个bean实例会从硬盘上删去。现在,让我们假设在第41分钟用户调用了这个bean实例的一个方法。BEA WebLogic Server将会抛出错误,如程序清单1所示。
程序清单 1
: Bean has been deleted.
at weblogic.ejb20.swap.DiskSwap.read(DiskSwap.java:156) at
weblogic.ejb20.manager.StatefulSessionManager.getBean(StatefulSession Manager.java:242) at
weblogic.ejb20.manager.StatefulSessionManager.preInvoke(StatefulSessionManager.java:313)
at weblogic.ejb20.internal.BaseEJBLocalObject.preInvoke(BaseEJBLocalObject.java:113)
at
weblogic.ejb20.internal.StatefulEJBLocalObject.preInvoke(StatefulEJBLocalObject.java:126)
WebLogic 6.1 Service Pack 5提供了一个有用的标记来避免发生这种情况。这个标记如下所示:
<!-- The stateful session beans that are passivated to the disk will stay alive for this many seconds. After this interval, the passivated beans will be removed from the disk.
Used in: stateful-session-cache
Since: WebLogic Server 6.1 sp5
Default value: 600
-->
<! ELEMENT session-timeout-seconds (#PCDATA)>
如果我们为这个<session-timeout-seconds>设置值,我们就能控制钝化的bean何时从硬盘中被删去。我们可以使用这个标记并把它设置到一个适当的值,这样我们就能总是拥有有状态EJB(或者在内存中或者在硬盘中)。这将完全消除bean被删除的错误。
使用WebLogic被管理服务器
BEA WebLogic 允许您在单独一个域中创建一个或多个服务器。一个服务器是管理服务器,所有其它服务器是被管理服务器,也就是被管理服务器管理。一个应用程序投入使用后,不应该被部署在管理服务器上。使用被管理服务器的好处是我们能从管理控制台上启动和停止它们。因此,即使服务器使应用程序停止响应(任何的原因),我们还是可以有机会从管理控制台重新启动服务器。
编码标准:为未来放弃规则
当系统的运行环境并没有在设计阶段考虑到时,管理一个开发系统会更加困难。当在设计阶段认真考虑了环境、边界、应用程序的运行环境后,系统再开发将是一项简单的任务。设计是执行路径的抽象定义。当考虑了设计中的每一个细节后再开发,解决方案会更具可伸缩性。对于系统开发并没有硬性的规定,因为这取决于您正面对的特定问题域。但是,还是有一些总会有帮助的定律。
- 对于补充类比如String 和 StringBuffer要有清晰的认识: 在合适的情况下用合适的类。例如,用String类构建一个长SQL查询是效率很低的,并加重JVM string池的负荷。
- 在您使用完继承对象后立即清除它们,比如 Hashtable。
- 在EJB引用中显式地调用 remove() 方法:这会把bean实例释放到bean池中,并减少由容器创建的bean实例数量。
- 小心地管理数据库连接:在您使用完后立即调用close()方法。不要在类的第一行就打开连接。而只在需要的时候才打开连接。
- 理解业务需求,并在您编写第一行代码之前就了解代码的执行环境。
总之一句话,”尽可能晚的创建对象而尽可能早的删除它们”。
原文出处 http://www.sys-con.com/story/?storyid=43039&DE=1
<!---->
分享到:
相关推荐
本篇文章将详细介绍如何利用Eclipse进行J2EE应用程序的开发,帮助初学者和有经验的开发者更好地理解和掌握这一过程。 首先,J2EE(Java Platform, Enterprise Edition)是Oracle公司提供的一个用于开发企业级应用...
在深入分析《论文研究-...文章不仅探讨了这些模式在J2EE中的具体实现和应用,还强调了它们在提升企业级应用性能和可维护性方面的重要性。这对于进行J2EE开发的软件工程师和架构师来说,是一篇具有重要参考价值的文献。
接着,Rational Application Developer (RAD) 是一个集成开发环境(IDE),专为J2EE应用程序设计。它支持Java、JSP、Servlets、EJB等技术,并且与IBM WebSphere Application Server紧密集成,提供了从编码、调试到部署...
标题和描述中的“J2EE WEB缓存技术详解”指向了一篇关于在Java Web应用程序中使用缓存技术的深入分析文章。文章由作者夏俊于2011年撰写,主要探讨了在处理大量数据时,如何通过实施缓存策略来优化系统性能,特别是...
- 应用程序集成:在J2EE应用中,通过JNDI查找并获取连接池,然后从连接池中获取和释放数据库连接。 4. **配置示例** - C3P0配置示例: ```xml <property name="jdbcUrl" value="jdbc:mysql://localhost:...
本篇文章将围绕一个名为"j2ee人事管理系统"的项目进行深入探讨,该系统包含了SQL Server数据库的表结构创建脚本以及可运行的工程代码,适用于SpringMVC框架。我们将详细解析其核心组件和关键技术,以帮助读者理解和...
Flex是一种用于构建富互联网应用程序(RIA)的前端开发框架,而J2EE是用于构建企业级后端系统的强大平台。这种整合允许开发者创建交互性强、用户体验优秀的Web应用,同时利用J2EE的稳定性和可扩展性。 在描述中虽然...
它支持延迟加载和缓存机制,有助于提高应用程序的性能。 轻量级J2EE架构的研究与应用主要是为了解决传统J2EE架构中EJB(Enterprise JavaBeans)过度复杂的问题。Struts、Spring、Hibernate三者结合使用,可以实现一...
随着互联网业务的迅速发展与企业信息化水平的不断提升,越来越多的关键性应用程序选择基于J2EE(Java 2 Platform, Enterprise Edition)平台进行构建。例如,在金融领域中的银行系统或在电商领域的账单系统等,这些...
4. **Servlet 2.4** 和 **JSP 2.0** 规范的引入带来了更多的功能和性能提升,如EL的增强,以及JSP标签库的支持。 5. **JAXB(Java Architecture for XML Binding)**:JAXB提供了一种将XML数据绑定到Java对象的机制...
本篇文章将详细讲解如何配置MyEclipse以实现Flex与Java EE的协同开发,提升开发效率。 首先,我们需要准备以下软件: 1. Eclipse 3.3:Eclipse是一个开源的集成开发环境,用于编写各种类型的应用程序。 2. Flex...
本篇文章将详细介绍 WAS 中 Java 虚拟机 (JVM) 的性能调优与诊断方法。 #### Java虚拟机(JVM)介绍 JVM 是运行 Java 应用程序的核心组件,在 Java 代码被编译成字节码后,由 JVM 负责解释执行这些字节码。主要特点...
在IT行业中,J2EE(Java 2 Platform, Enterprise Edition)是用于构建企业级分布式应用程序的框架,而群集技术则是提升系统可用性、可扩展性和容错性的关键手段。本篇文章将深入探讨J2EE群集技术,涵盖基本概念、web...
本文是一篇关于基于J2EE的洪水预报系统水库的毕业设计论文的英文翻译,主要探讨了如何利用J2EE技术构建一个用于洪水预警的Web应用程序。J2EE(Java 2 Platform, Enterprise Edition)是由Sun Microsystems开发的平台...
在IT行业中,J2EE(Java 2 Platform, Enterprise Edition)是一个广泛使用的开源框架,用于构建企业级的分布式应用程序。Maven是Java开发中的一个项目管理和综合工具,它通过使用一个项目对象模型(Project Object ...
J2EE(Java 2 Enterprise Edition)是一个企业级的Java平台,用于构建和部署分布式、多层的Web应用程序,它与项目管理密切相关,特别是在大型企业环境中,项目管理对于J2EE应用的开发、测试、部署和维护至关重要。...
描述中给出的链接是一个博客文章的详情页,虽然具体内容未给出,但可以推测这篇文章可能详细讲解了如何在J2EE应用中构建和使用自定义的MVC框架。通常,这样的文章会涵盖以下内容:模型(Model)如何处理业务逻辑,...
本篇文章基于一份名为“Flex 性能简介”的PDF文档内容,探讨了Macromedia Flex技术与JavaServer Pages (JSP) 在服务器端性能方面的比较。通过对两者的深入对比分析,旨在为开发者提供关于如何选择更适合自身项目的...
在本书中,作者会结合实际案例,详细介绍如何在Eclipse环境下,利用Struts作为前端控制器,Hibernate处理数据持久化,Spring进行整体协调和管理,实现一个高效、灵活的J2EE应用。读者将学习到如何配置和使用这些框架...
这表明在Web应用程序开发中,开发者可以通过增加新的参数来灵活调整用户界面(UI)元素的布局。 **重要知识点:** - **左对齐与左间距调整:** 这种调整可以提高UI的一致性和用户体验。在实际开发中,通过CSS或其他...