科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道“快”在细节 J2EE程序的性能优化技巧(3)

“快”在细节 J2EE程序的性能优化技巧(3)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

 Java 2 Platform, Enterprise Edition (J2EE)是当前很多商业应用系统使用的开发平台,该技术提供了一个基于组件的方法来设计、开发、装配和部署企业级应用程序。

来源:IT专家网 2008年5月5日

关键字: 优化 3977 J2EE java

  • 评论
  • 分享微博
  • 分享邮件
·清除Session

  通常情况,当达到设定的超时时间时,同时有些Session没有了活动,服务器会释放这些没有活动的Session,.. 不过这种情况下,特别是多用户并访时,系统内存要维护多个的无效Session。

  当用户退出时,应该手动释放,回收资源,实现如下:..

HttpSession theSession = request.getSession();
// 获取当前Session
if(theSession != null){
 theSession.invalidate(); // 使该Session失效
}

  五、EJB 问题

  EJB是Java服务器端服务框架的规范,软件厂商根据它来实现EJB服务器。应用程序开发者可以专注于支持应用所需的商业逻辑,而不用担心周围框架的实现问题。EJB规范详细地解释了一些最小但是必须的服务,如事务,安全和名字等。

  ·缓存Home接口

  EJB库使用Enterprise Bean 的客户端通过它的Home接口创建它的实例。客户端能通过JNDI访问它。服务器通过Lookup方法来获取。

  JNDI是个远程对象,通过RMI方式调用,对它的访问往往是比较费时的。所以,在设计时可以设计一个类专门用来缓存Home接口,在系统初始化时就获得需要的Home接口并缓存,以后的引用只要引用缓存即可。

  ·封装Entity Bean

  直接访问Entity Bean是个不好的习惯,用会话Bean封装对实体Bean的访问能够改进事务管理,因为每一个对get方法的直接调用将产生一个事务,容器将在每一个实体Bean的事务之后执行一个“Load-Store”.. 操作。

  最好在Session Bean中完成Entity Bean的封装,减少容器的事务处理,并在Session Bean中实现一些具体的业务方法。

  ·释放有状态的Session Bean

  相当于HttpSession,当把一个Session Bean设为Stateful,即有状态的Session Bean 后,应用容器(Container)就可能有“钝化”(Passivate)和活化(Activate)过程,即在主存和二级缓存之间对SessionBean进行存储位置的转移,在这个过程中,存在序列化过程。

  通常有状态Session Bean的释放是在超时时发生,容器自动的清除该对象,但是如果交给容器管理,一方面可能产生对象钝化,另一方面未超时期间,系统还要 维护一份该对象,所以如果我们确认使用完该StatefulSession Bean后不再需要时,可以显式的将其释放掉,方法是调用:

theSesionBean.remove();

  六、数据库访问

  在J2EE开发的应用系统中,数据库访问一般是个必备的环节。数据库用来存储业务数据,供应用程序访问。

  在Java技术的应用体系中,应用程序是通过JDBC(Java Database Connectivity)实现的接口来访问数据库的,JDBC支持“建立连接、SQL语句查询、处理结果”等基本功能。在应用JDBC接口访问数据库的过程中,只要根据规范来实现,就可以达到要求的功能。

  但是,有些时候进行数据查询的效率着实让开发人员不如所愿,明明根据规范编写的程序,运行效果却很差,造成整个系统的执行效率不高。

  ·使用速度快的JDBC驱动

  JDBC API包括两种实现接口形式,一种是纯Java实现的驱动,一种利用ODBC驱动和数据库客户端实现,具体有四种驱动模式并各有不同的应用范围,针对不同的应用开发要选择合适的JDBC驱动,在同一个应用系统中,如果选择不同的JDBC驱动,在效率上会有差别。

  例如,有一个企业应用系统,不要求支持不同厂商的数据库,这时就可以选择模式4的JDBC驱动,该驱动一般由数据库厂商实现的基于本地协议的驱动,直接调用数据库管理系统使用的协议,减少了模式3中的中间层。

·使用JDBC连接池

  为了提高访问数据库的性能,我们还可以使用JDBC 2.0的一些规范和特性,JDBC是占用资源的,在使用数据库连接时可以使用连接池Connection Pooling,避免频繁打开、关闭Connection。而我们知道,获取Connection是比较消耗系统资源的。

  Connection缓冲池是这样工作的:当一个应用程序关闭一个数据库连接时,这个连接并不真正释放而是被循环利用,建立连接是消耗较大的操作,循环利用连接可以显著的提高性能,因为可以减少新连接的建立。

  一个通过DataSource获取缓冲池获得连接,并连接到一个CustomerDB数据源的代码演示如下:

Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup("jdbc/CustomerDB");
Connection conn = dataSource.getConnection("password","username");

  ·缓存DataSource

  一个DataSource对象代表一个实际的数据源。这个数据源可以是从关系数据库到表格形式的文件,完全依赖于它是怎样实现的,一个数据源对象注册到JNDI名字服务后,应用程序就可以从JNDI服务器上取得该对象,并使用之和数据源建立连接。

  通过上面的例子,我们知道DataSource是从连接池获得连接的一种方式,通过JNDI方式获得,是占用资源的。

  为了避免再次的JNDI调用,可以系统中缓存要使用的DataSource。

  ·关闭所有使用的资源

  系统一般是并发的系统,在每次申请和使用完资源后,应该释放供别人使用,数据库资源每个模式的含义可以参考SUN JDBC的文档,不同是比较宝贵的,使用完成后应该保证彻底的释放。

  请看下面的代码段:

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
 DataSource dataSource = getDataSource();
 // 取的DataSource的方法,实现略。
 conn = datasource.getConnection();
 stmt = conn.createStatement();
 rs = stmt.executeQuery("SELECT * FROM ...");
 ... // 其他处理
 rs.close();
 stmt.close();
 conn.close();
}catch (SQLException ex) {
 ... // 错误处理
}

  粗看似乎没有什么问题,也有关闭相关如Connection等系统资源的代码,但当出现异常后,关闭资源的代码可能并不被执行,为保证资源的确实已被关闭,应该把资源关闭的代码放到finally块:

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
 DataSource dataSource = getDataSource();
 // 取的DataSource的方法,实现略。
 conn = datasource.getConnection();
 stmt = conn.createStatement();
 rs = stmt.executeQuery("SELECT * FROM ...");

 ... // 其他处理
}catch (SQLException ex) {
 ... // 错误处理

}finally{
 if (rs!=null) {
  try {
   rs.close(); // 关闭ResultSet}
  catch (SQLException ex) {
   ... // 错误处理
  }
 }

 if (stmt!=null){
  try {
   stmt.close(); // 关闭Statement}
  catch (SQLException ex) {
   ... // 错误处理
  }
 }
 if (conn!=null){
  try {
   conn.close(); // 关闭Connection}
  catch (SQLException ex) {
   ... // 错误处理
  }
 }
}

·大型数据量处理

  当我们在读取诸如数据列表、报表等大量数据时,可以发现使用EJB的方法是非常慢的,这时可以使用直接访问数据库的方法,用SQL直接存取数据,从而消除EJB的经常开支(例如远程方法调用、事务管理和数据序列化,对象的构造等)。

  ·缓存经常使用的数据

  对于构建的业务系统,如果有些数据要经常要从数据库中读取,同时,这些数据又不经常变化,这些数据就可以在系统中缓存起来,使用时直接读取缓存,而不用频繁的访问数据库读取数据。

  缓存工作可以在系统初始化时一次性读取数据,特别是一些只读的数据,当数据更新时更新数据库内容,同时更新缓存的数据值。

  一个例子是,在一套企业应用系统中,企业的信息数据(如企业的名称)在多个业务应用模块中使用,这时就可以把这些数据缓存起来,需要时直接读取缓存的企业信息数据。

  七、总结

  一般意义上说,参与系统运行的代码都会对性能产生影响,实际应用中应该养成良好的编程规范、编写高质量的代码,当系统性能出现问题时,要找到主要影响性能的瓶颈所在,然后集中精力优化这些代码,能达到事半功倍的效果。

  J2EE性能的优化包括很多方面的,要达到一个性能优良的系统,除了关注代码之外,还应该根据系统实际的运行情况,从服务器软硬件环境、集群技术、系统构架设计、系统部署环境、数据结构、算法设计等方面综合考虑。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章