选Web服务工具:.Net还是SUN ONE 之五

对 Forte for Java 的总结:

在大量的 Java 开发者眼中,新的 Forte for Java 在 EJB 和 XML 功能上更能满足他们的需要 。

短期商业影响:使用 iPlanet Application Server 的公司将会得到 Forte for Java 的促进,因为新的 Forte for Java 比老版本的 Application Builder 开发工具更好用。

长期商业影响:对会话和 EJB 实体的支持,对基于 XML 的 Web 服务的支持,对 TeamWare 源代码的控制,将会产生和 J2EE 应用程序一样的积极影响。

优点:对会话和 EJB 实体的支持,对基于 XML 的 Web 服务的支持,对 TeamWare 源代码的控制,将会产生和 J2EE 应用程序一样的积极影响。

缺点:缺乏对 SOAP 的支持和对其它标准 Web 服务技术的支持;仅有很一般的编辑环境;对内存占用比较大


上一页 <淘宝热门商品:

小小豆叮

深刻理解Oracle数据库的启动和关闭

Oracle数据库提供了几种不同的数据库启动和关闭方式,本文将详细介绍这些启动和关闭方式之间的区别以及它们各自不同的功能。   一、启动和关闭Oracle数据库   对于大多数Oracle DBA来说,启动和关闭Oracle数据库最常用的方式就是在命令行方式下的Server Manager。从Oracle 8i以后,系统将Server Manager的所有功能都集中到了SQL*Plus中,也就是说从8i以后对于数据库的启动和关闭可以直接通过SQL*Plus来完成,而不再另外需要Server Manager,但系统为了保持向下兼容,依旧保留了Server Manager工具。另外也可通过图形用户工具(GUI)的Oracle Enterprise Manager来完成系统的启动和关闭,图形用户界面Instance Manager非常简单,这里不再详述。   要启动和关闭数据库,必须要以具有Oracle 管理员权限的用户登陆,通常也就是以具有SYSDBA权限的用户登陆。一般我们常用INTERNAL用户来启动和关闭数据库(INTERNAL用户实际上是SYS用户以SYSDBA连接的同义词)。Oracle数据库的新版本将逐步淘汰INTERNAL这个内部用户,所以我们最好还是设置DBA用户具有SYSDBA权限。   二、数据库的启动(STARTUP)   启动一个数据库需要三个步骤:    1、 创建一个Oracle实例(非安装阶段)    2、 由实例安装数据库(安装阶段)    3、 打开数据库(打开阶段)   在Startup命令中,可以通过不同的选项来控制数据库的不同启动步骤。   1、STARTUP NOMOUNT   NONOUNT选项仅仅创建一个Oracle实例。读取init.ora初始化参数文件、启动后台进程、初始化系统全局区(SGA)。Init.ora文件定义了实例的配置,包括内存结构的大小和启动后台进程的数量和类型等。实例名根据Oracle_SID设置,不一定要与打开的数据库名称相同。当实例打开后,系统将显示一个SGA内存结构和大小的列表,如下所示: SQL> startup nomount ORACLE 例程已经启动。 Total System Global Area 35431692 bytes Fixed Size 70924 bytes Variable Size 18505728 bytes Database Buffers 16777216 bytes Redo Buffers 77824 bytes   2、STARTUP MOUNT   该命令创建实例并且安装数据库,但没有打开数据库。Oracle系统读取控制文件中关于数据文件和重作日志文件的内容,但并不打开该文件。这种打开方式常在数据库维护操作中使用,如对数据文件的更名、改变重作日志以及打开归档方式等。在这种打开方式下,除了可以看到SGA系统列表以外,系统还会给出"数据库装载完毕"的提示。   3、STARTUP   该命令完成创建实例、安装实例和打开数据库的所有三个步骤。此时数据库使数据文件和重作日志文件在线,通常还会请求一个或者是多个回滚段。这时系统除了可以看到前面Startup Mount方式下的所有提示外,还会给出一个"数据库已经打开"的提示。此时,数据库系统处于正常工作状态,可以接受用户请求。   如果采用STARTUP NOMOUNT或者是STARTUP MOUNT的数据库打开命令方式,必须采用ALTER DATABASE命令来执行打开数据库的操作。例如,如果你以STARTUP NOMOUNT方式打开数据库,也就是说实例已经创建,但是数据库没有安装和打开。这是必须运行下面的两条命令,数据库才能正确启动。 ALTER DATABASE MOUNT; ALTER DATABASE OPEN;   而如果以STARTUP MOUNT方式启动数据库,只需要运行下面一条命令即可以打开数据库:     ALTER DATABASE OPEN.   4、其他打开方式   除了前面介绍的三种数据库打开方式选项外,还有另外其他的一些选项。   (1) STARTUP RESTRICT   这种方式下,数据库将被成功打开,但仅仅允许一些特权用户(具有DBA角色的用户)才可以使用数据库。这种方式常用来对数据库进行维护,如数据的导入/导出操作时不希望有其他用户连接到数据库操作数据。   (2) STARTUP FORCE   该命令其实是强行关闭数据库(shutdown abort)和启动数据库(startup)两条命令的一个综合。该命令仅在关闭数据库遇到问题不能关闭数据库时采用。   (3) ALTER DATABASE OPEN READ ONLY;   该命令在创建实例以及安装数据库后,以只读方式打开数据库。对于那些仅仅提供查询功能的产品数据库可以采用这种方式打开。 三、数据库的关闭(SHUTDOWN)   对于数据库的关闭,有四种不同的关闭选项,下面对其进行一一介绍。   1、SHUTDOWN NORMAL   这是数据库关闭SHUTDOWN命令的确省选项。也就是说如果你发出SHUTDOWN这样的命令,也即是SHUTDOWN NORNAL的意思。   发出该命令后,任何新的连接都将再不允许连接到数据库。在数据库关闭之前,Oracle将等待目前连接的所有用户都从数据库中退出后才开始关闭数据库。采用这种方式关闭数据库,在下一次启动时不需要进行任何的实例恢复。但需要注意一点的是,采用这种方式,也许关闭一个数据库需要几天时间,也许更长。   2、SHUTDOWN IMMEDIATE   这是我们常用的一种关闭数据库的方式,想很快地关闭数据库,但又想让数据库干净的关闭,常采用这种方式。   当前正在被Oracle处理的SQL语句立即中断,系统中任何没有提交的事务全部回滚。如果系统中存在一个很长的未提交的事务,采用这种方式关闭数据库也需要一段时间(该事务回滚时间)。系统不等待连接到数据库的所有用户退出系统,强行回滚当前所有的活动事务,然后断开所有的连接用户。   3、SHUTDOWN TRANSACTIONAL   该选项仅在Oracle 8i后才可以使用。该命令常用来计划关闭数据库,它使当前连接到系统且正在活动的事务执行完毕,运行该命令后,任何新的连接和事务都是不允许的。在所有活动的事务完成后,数据库将和SHUTDOWN IMMEDIATE同样的方式关闭数据库。   4、SHUTDOWN ABORT   这是关闭数据库的最后一招,也是在没有任何办法关闭数据库的情况下才不得不采用的方式,一般不要采用。如果下列情况出现时可以考虑采用这种方式关闭数据库。   1、 数据库处于一种非正常工作状态,不能用shutdown normal或者shutdown immediate这样的命令关闭数据库;   2、 需要立即关闭数据库;   3、 在启动数据库实例时遇到问题;   所有正在运行的SQL语句都将立即中止。所有未提交的事务将不回滚。Oracle也不等待目前连接到数据库的用户退出系统。下一次启动数据库时需要实例恢复,因此,下一次启动可能比平时需要更多的时间。 <淘宝热门商品:

小小豆叮

Sun阵营联合对抗微软Passport认证技术

美国Sun Microsystems等33家企业和团体日前联合成立了旨在推进因特网用户认证技术的开发普及开放性业界团体“Liberty Alliance Project”。这是33家企业于美国当地时间9月26日发布的。该团体显然是针对美国微软的“Passport”而成立的。   Liberty Alliance Project目标是为实现利用因特网进行交易时必需的Ubiquitous(随时随地)的单点登录(Single Sign-On)认证,进行有关标准的制订。   加盟该组织的创始企业中有服务提供、汽车制造、金融服务、旅行业、数字媒体、零售业、电信及技术相关业界的著名企业。   Liberty Alliance Projec的主要目标有如下三个方面: 1)使个人消费者和企业用户能够安全保管个人信息。基此推进无信息垄断的、可以相互运用并跨越多个网络的服务。 2)制订实现“单点登录”的开放标准。基此,使用户在任何1个WWW站点通过认证后,不必接受其它站点认证就可以使用其服务。 3)制订所有接入因特网的设备都可以使用的网络认证开放标准。基此使手机、车载设备和信用卡等各种各样的终端间都能进行安全的认证。   主要的成员企业除Sun公司外还有如下企业和团体:   ActivCard公司、美国航空公司,Apache Software Foundation、美国银行、加拿大Bell Canada Enterprises、美国Cingular Wireless、美国思科系统、美国CollabNet、美国Dun and Bradstreet、美国eBay、美国Entrust、Fidelity Investments公司、法国Gemplus、美国通用汽车、百慕大群岛Global Crossing、美国i2 Technologies、美国Intuit,美国Liberate Technologies、芬兰诺基亚、NTT DoCoMo、美国O'Reilly and Associates、美国Openwave Systems、美国RealNetworks、美国RSA Security、美国Sabre、美国Schlumberger、索尼、美国Sprint、美国Travelocity、美国联邦航空公司、美国VeriSign、英国沃达丰。   另外,上述成员将就组织及技术的共同开发等规则进行磋商,并在今后60天内完成有关协定。   顺便提一下,美国微软于美国当地时间9月20日正式宣布在因特网的用户认证服务方面改变原有的提供自主开发认证功能的方针。在Passport服务的安全协议方面通过采用开放技术“Kerberos”,以确保与其它服务提供的认证功能间的相互运用性。   另据电子版《华尔街日报》报道,Liberty Alliance Project和微软公司双方均表示“将保持对话关系”。   此前曾有多家隐私保护团体针对Passport的隐私保护功能指出:“微软公司有非法收集用户个人信息之嫌”。隐私保护团体Electronic Privacy Information Center和Privacy Foundation等已向联邦交易委员会(FTC:Federal Trade Commission)提出了调查及推迟“Windows XP”上市的请求。   据调查公司美国Gartner的调查结果,“Passport未注册用户中,有7成表示‘今后将不会使用Passport’”。“消费者将隐私和安全问题列为最为担心的事项,他们并不想为了使用Passport这样的因特网尖端技术而牺牲自己的隐私”(Gartner公司)。 <淘宝热门商品:

小小豆叮

APPLET-SERVLET-DBMS结构的实现

在Internet上实现的WEB应用由于具有统一的用户界面(浏览器)、客户端无须开发任何应用已经成为现在应用程序开发的一个潮流。这种基于Internet的WEB应用一般是以Browser/WEB Server/Database Server三层形式出现,而Java Applet因其强大的功能在网络应用中越来越受流行,成为WEB Browser客户端使用最多的技术之一。一般说来,对数据库的数据存取,从Applet直接存取也是可以的,但是对一个真正的Internet应用,就不可能也不需要为每个WEB Browser客户端保留一个到数据库服务器的连接,因此,必须在数据库和最终的WEB Browser客户端之间的WEB 服务层以实现数据库操作和WEB服务,同时也便于数据库的安全控制。这样,我们就提出了一种Internet数据库应用程序开发的通用结构:APPLET-SERVLET-DBMS结构。 一、APPLET-SERVLET-DBMS结构 APPLET-SERVLET-DBMS结构如下图所示。 其中,应用层为客户机浏览器上运行的Applet应用程序,是用户的操作界面。它和服务层采用URL或SOCKET连接,完成数据交互。 服务层提供支持SERVLET的WEB服务,同时要能访问数据库,因此包含两个部分,即WEB服务和数据库操作。它和应用层采用URL或SOCKET连接,完成数据交互。它和数据库服务层采用JDBC连接,完成数据存取。 数据库服务层提供最终的数据服务。 二、配置: 在实际应用中,我们已经同时在WINDOWS平台和SOLARIS平台下实现了该APPLET-SERVLET-DBMS结构的所有功能。具体的配置如下: 应用客户端: 支持JAVA的浏览器,如IE4/IE5、Netscape或HotJava; 服务器端: Apache HTTP Server Version 1.3 Apache JServ 1.1.2 Oracle JDBC Drivers release 8.0.4.2.0 JDK1.3 数据库端: ORACLE8.0.4 开发工具: JDK1.3 JSDK2.0 所有工具和软件都可以在Internet上找到。 三、源代码示例: 1、取数据库数据 getServlet为SERVLET程序,TestApp为客户测试程序 /********getServlet.java 陈旭东 2000.12.16*******/ import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.net.*; import java.sql.*; public class getServlet extends HttpServlet{ public void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { String COMMAND=req.getParameter("name"); String id=req.getParameter ("id"); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteOut); //查询数据库 try{ rs=query (ne); }catch (Exception ex) { ex.printStackTrace (); } //发送结果APPLET out.writeUTF(COMMAND); out.writeInt (rs); if (rs>0){ out.writeInt(id); out.writeUTF(name); ... } out.flush(); }else{ out.writeUTF("BAD COMMAND!"); out.flush(); } byte buf[] = byteOut.toByteArray(); DataOutputStream dataout = new DataOutputStream(resp.getOutputStream()); dataout.write(buf); dataout.flush(); dataout.close(); } private int queryNe(NE ne) throws Exception { int columnCount=0; String sqlStr="SELECT ...";//SQL语句 Connection con=null; Statement st=null; ResultSet rs=null; try{ //连接数据库 System.out.println("connecting database..."); DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); con=DriverManager.getConnection ("jdbc:oracle:thin:@server:1521:ORCL", "scott","tiger"); //查询结果 st=con.createStatement (); rs=st.executeQuery(sqlStr); ResultSetMetaData rsmd = rs.getMetaData(); columnCount = rsmd.getColumnCount(); if (rs.next()) { int i=0; id=rs.getInt(i + 1);i++; name=rs.getString(i + 1);i++; ... }; } finally{ try{ if (rs!=null){ rs.close(); } if (st != null){ st.close(); } if (con !=null){ con.close(); } }catch(Exception ex){ ex.printStackTrace (); return 0; } } return columnCount; } } /*****TestApp中接受数据部分***********/ public void getinfo(NE ne) { ...... try{ URL url1 = new URL("http://server/servlet/getServlet?name="+cmd+"&ne="+ id); URLConnection connection1 = url1.openConnection(); DataInputStream inStream = new DataInputStream(connection1.getInputStream()); //读取SERVLET发送过来的数据 String echo = inStream.readUTF(); if (echo.equals(cmd)){ int rs =inStream.readInt(); if (rs>0){ id =inStream.readInt(); name = inStream.readUTF(); .... }; //System.out.println("接到:"+rs); }else{ //System.out.println("接到错误:"+echo); } }catch(Exception e){//System.out.println(e); } } 2、 修改数据库数据 savServlet为SERVLET程序,TestApp为客户测试程序 /***********savServlet 陈旭东 2000.12.18********************/ ... public class savServlet extends HttpServlet{ public void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { //读取APPLET发送过来的信息 String COMMAND=req.getParameter("name"); String ne_id=req.getParameter ("ne"); DataInputStream in = new DataInputStream(req.getInputStream()); ne.x = in.readInt (); ne.y = in.readInt (); ... in.close(); //修改数据库数据 boolean rs1=false; try{ rs1=SaveNe(ne); }catch (Exception ex) { ex.printStackTrace(); } } } private boolean SaveNe(NE ne) throws Exception { boolean result =false; String sqlStr="update ne set ...";//UPDATE语句 Connection con=null; Statement st=null; try{ DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); con=DriverManager.getConnection ("jdbc:oracle:thin:@server:1521:ORCL","SCOTT","TIGER"); st=con.createStatement (); int rows=st.executeUpdate (sqlStr); if (rows>0) result=true; boolean n1=st.execute("commit"); } finally{ try{ if (st != null){ st.close(); } if (con !=null){ con.close(); } }catch(Exception ex){ } } return result; } } /*********TestApp保存数据部分***************/ private void SaveNEInfo(NE ne){ .... try{ //for apache URL url1 = new URL("http://202.112.145.69/servlet/savServlet?name="+COMMAND2+"&ne="+ne_id); URLConnection con = url1.openConnection(); con.setUseCaches(false); con.setDoOutput(true); con.setDoInput(true); ByteArrayOutputStream byteout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(byteout); //发送到SERVLET out.writeInt(ne.x); out.writeInt(ne.y); ... out.flush(); byte buf[] = byteout.toByteArray(); con.setRequestProperty("Content-type","application/octet-stream"); con.setRequestProperty("Content-length",""+buf.length); DataOutputStream dataOut=new DataOutputStream(con.getOutputStream()); dataOut.write(buf); dataOut.flush(); dataOut.close(); }catch(Exception e){System.out.println(e);} } 四、结论 本文提出了一种Internet数据库应用程序开发的通用结构:APPLET-SERVLET-DBMS结构。并针对该结构进行了具体的实现,相信会对同类的应用具有借鉴意义。 <淘宝热门商品:

小小豆叮

全面研读 EJB 2.0(上)

新的 EJB 2.0 规范不仅仅是一个新的阶段性发行版,它加入了许多引人注目的变动,包括 CMP 组件模型中的一些变动和一种新的 bean 类型,它们将增强您在开发应用程序时的灵活性和可移植性。请率先了解此新规范的功能,本月已发布了它的公开草案。   2000年6月2日发布的 Enterprise JavaBeans 2.0 不仅是一个阶段性发行版,而且是该规范的一个新版本。整个规范有 500 多页,比以前的 EJB 1.1 规范长了 200 页 (66%)。该规范中最重要的变动是对容器管理的持久性 (CMP) 所作的更改,以及引入了一种全新的 bean 类型,即 MessageDrivenBean。   EJB 2.0 中的大量更改都集中在一种新 CMP 组件模型的定义中。它完全不同于旧的 CMP 模型,因为它引入了一个全新的成员,即持久性管理器,并引入了全新的方式来定义容器管理的字段,以及定义这些字段与其它 bean 和从属对象的关系。   MessageDrivenBean (消息 bean)的引入也是非常重要的。消息 bean 体现出 JMS (Java Message Service)与 EJB 相集成,以创建出一种全新的 bean 类型,它设计用来处理异步的 JMS 消息。这种振奋人心的新型 bean 为 JMS 客户机提供一种组件模型,允许将它们部署到 EJB 容器系统的丰富而强健的环境中去。   对该规范还作了许多较小的其它更改。这些其它更改虽然也重要,但它们主要是涉及使该规范更严格,以便消除多义性,并使这些组件具有更高的可移植性。本文集中讨论 EJB 2.0 中引入的新 CMP 和消息 bean 组件模型。   我将提供几个具体的例子,所以读者应该很容易跟上并理解它。但是,EJB 初学者可能发现这个材料比较困难,因为它假定读者已对 EJB 有了基本的了解。有关 EJB 的详细信息,请参阅参考资料。   容器管理的持久性   容器管理的持久性在 EJB 2.0 中发生了根本变化。在 EJB 2.0 中,持久性管理器在运行时自动处理 CMP 实体 bean 的持久性。持久性管理器负责根据一种称为抽象持久性方案的新的 bean 持久性管理器合约,将实体 bean 映射到数据库。此外,持久性管理器还负责实现和执行多种查找方法,这些查找方法均基于一种称为 EJB QL 的新型查询语言。   注意到以下事实是很重要的,即符合 EJB 2.0 规范的产品必须能支持 EJB 1.1 CMP 模型,又能支持新的 EJB 2.0 模型。虽然这两种模型并不兼容,但是为了保证向后兼容性,就必须能支持 EJB 1.1 模型。   抽象持久性方案   为了理解抽象持久性方案是如何工作的,以及它为什么重要,我将为您快速地回顾一下在 EJB 1.1 中是如何处理 CMP 的,随后再讨论在 EJB 2.0 中如何定义它。 EJB 1.1 中的 CMP 模型   在 EJB 1.1 中,bean 开发人员负责将 bean 类的持久性字段声明为 Java 基本类型或可序列化类型。下列示例显示了一个 Employee 企业级 bean 类,它是按 EJB 1.1 定义的,带有几个 CMP 字段:   // Employee bean 类   public class EmployeeBean implements   java.ejb.EntityBean {   // 实例字段   EntityContext ejbContext;   file:// 容器管理的字段   public int identity;   public String firstName;   public String lastName;   public double salary;   public Address address;   public Integer ejbCreate(int id, String fname,String lname){    identity = id;    firstName = fname;    lastName = lname;    return null;    }    ...       // Address 从属类   public class Address implements Serializable{   public String street;   public String city;   public String state;   public String zip;  }   当将关系数据库用于持久性时,基本字段如 identity、firstName、lastName 和 salary,很容易持久化,因为它们很好地映射为 SQL 类型,如 INTEGER、CHAR 和 DOUBLE。   在 EJB 1.1 中,CMP bean 的 XML 部署描述符提供 cmp-field 元素,用以标识此 bean 类中的持久性字段(容器管理的字段)。如下所示,cmp-field 元素用来区分写入数据库的字段和不写入数据库的字段。例如,ejbContext 字段就不包括在容器管理的字段的列表中,因此它不是持久性字段。            EmployeeEJB     ...   Container   ...   identity   firstName   lastName   salary   address    ...   容器提供者提供一种工具,用来将 bean 的持久性字段映射到数据库表中的列,通常每个 bean 对应一个表。但是,可序列化的类型,如 Address,就比较难于持久化。在 EJB 1.1 中,没有标准的方法将可序列化的对象映射到关系数据库。虽然 Address 类有其自身的字段集,但 XML 部署描述符并没有提供一种机制,来将这些字段映射到数据库。在大多数情况下,人们期望将可序列化的对象(如 Address)作为二进制类型(有时称为 blob 类型)持久化到某个数据库表中。   由于实体 bean 的数据方案逐渐复杂起来,所以这个问题也变得严重了。例如,Employee bean 可能有多个类似于 Address 的子对象,如 Benefits 和 JobPosition。这些子对象称为从属对象,可以形成关系数据库中跨几个表的复杂对象图。另外,EJB 1.1 中的 CMP 在很大程度上不足以持久化与其它 bean 的关系。在 EJB 1.1 中,如果某个 bean 准备维持与另一个 bean 的关系,则容器会自动将主关键字或句柄用作一个链接。与某些其它 bean 的关系其性质可能是双向的,或者要依赖于一些不易用主关键字或句柄来表示的字段,为了保持与这类 bean 的关系,上面的办法已被证明是一种远未完善的机制。   EJB 2.0 的 CMP 模型   在 EJB 2.0 中,CMP 实体 bean 和持久性管理器之间的新合约,使您能够在实体 bean 中定义更复杂的、可移植性更强的关系,包括 bean 与 bean 之间、bean 与从属对象之间、甚至从属对象与从属对象之间的关系。   持久性管理器是新加入到 Enterprise JavaBeans 部署过程中的。容器厂商,或专长于特定数据库的持久性的厂商,将能提供这种持久性管理器。其思路是将用于管理 bean 关系的机制从容器中分离出来,容器只负责管理安全、事务和资源。这种职责上的分离使不同的持久性管理器能够与不同的容器一起工作。它也使实体 bean 在不同 EJB 厂商之间以及在各种持久性管理器之间具有更强的可移植性。   如果您使用或学习过 Thought Inc. 生产的,能自动为 EJB 1.1 容器生成 BMP(bean 管理的持久性)bean 的产品 CocoBase,则您对持久性管理器工具如何工作就已经比较熟悉了。CocoBase 根据 bean 部署者提供的,从对象到关系的映射信息,为 BMP bean 生成全部数据库访问逻辑。在 EJB 2.0 中,持久性管理器能够根据部署描述符、bean 的抽象持久性方案和部署者完成的工作所提供的信息,生成 CMP 实体到关系数据库的映射。但是,持久性管理器并不局限于关系数据库。也可以为对象数据库以及遗留的系统和 ERP 系统(如 SAP)开发持久性管理器。   为了将持久性管理器从容器中分离出来,必须定义 bean 与持久性管理器之间的合约。这个合约在新的抽象持久性方案中表现出来。此方案是通过部署描述符中一组新的 XML 元素和 CMP 实体 bean 中的一组代码习语定义的。在 EJB 2.0 中,CMP bean 类被声明为抽象类,它的持久性字段和关系字段是使用抽象的读方法和写方法来访问的,而这两种方法的方法特征则映射为 XML 部署描述符中的特定元素。   在部署该 bean 时,您将使用持久性管理器工具,根据 XML 部署描述符和 bean 类,来具体实现此抽象 bean 类及其从属对象类。具体实现将包括数据访问代码,此代码将在运行时将 bean 的状态实际读出和写到数据库中。在运行时,容器使用由持久性管理器工具生成的子类,而不使用 bean 提供者定义的抽象类。   bean 类的继承层次结构   为了使讨论更充实,这里提供一个 CMP 实体的示例,它更具体地说明了抽象持久性方案是如何工作的。 <淘宝热门商品:

小小豆叮

全面研读 EJB 2.0(下)

MessageDrivenBean   在 EJB 2.0 中,对规范的一个基础性更改是添加了一种全新的企业级 bean 类型,即 MessageDrivenBean。MessageDrivenBean 专门设计来处理入网的 JMS 消息。对于许多开发人员来说,JMS 是一种新的范例,所以本文将花一些时间逐步说明对 JMS 的理解,以及它们在 EJB 2.0 中的用法。   什么是 JMS?   JMS 是一种与厂商无关的 API,用来访问消息收发系统。它类似于 JDBC (Java Database Connectivity):这里,JDBC 是可以用来访问许多不同关系数据库的 API,而 JMS 则提供同样与厂商无关的访问方法,以访问消息收发服务。许多厂商目前都支持 JMS,包括 IBM 的 MQSeries、BEA 的 Weblogic JMS service 和 Progress 的 SonicMQ,这只是几个例子。   JMS 使您能够通过消息收发服务(有时称为消息中介程序或路由器)从一个 JMS 客户机向另一个 JML 客户机发送消息。消息是 JMS 中的一种类型对象,由两部分组成:报头和消息主体。报头由路由信息以及有关该消息的元数据组成。消息主体则携带着应用程序的数据或有效负载。根据有效负载的类型来划分,可以将消息分为几种类型,它们分别携带:简单文本 (TextMessage)、可序列化的对象 (ObjectMessage)、属性集合 (MapMessage)、字节流 (BytesMessage)、原始值流 (StreamMessage),还有无有效负载的消息 (Message)。   消息收发系统是异步的,也就是说,JMS 客户机可以发送消息而不必等待回应。比较可知,这完全不同于基于 RPC 的(基于远程过程的)系统,如 EJB 1.1、CORBA 和 Java RMI 的引用实现。在 RPC 中,客户机调用服务器上某个分布式对象的一个方法。在方法调用返回之前,该客户机被阻塞;该客户机在可以执行下一条指令之前,必须等待方法调用结束。在 JMS 中,客户机将消息发送给一个虚拟通道(主题或队列),而其它 JMS 客户机则预订或监听这个虚拟通道。当 JMS 客户机发送消息时,它并不等待回应。它执行发送操作,然后继续执行下一条指令。消息可能最终转发到一个或许多个客户机,这些客户机都不需要作出回应。   EJB 2.0 中的 JMS   EJB 2.0 以两种方式支持 JMS 的集成:作为一种 bean 可用的资源,和作为一个 MessageDrivenBean。当将 JMS 用作一种资源时,使用 JMS API 的 bean 就是消息的产生者或发送者。在这种情况下,bean 将消息发送给称为主题或队列的虚拟通道。另一方面,MessageDrivenBean 则是消息的使用者或接收者。它监听特定的虚拟通道(主题或队列),并处理发送给该通道的消息。为了更好地理解消息产生者和消息使用者的作用,用 SessionBean bean 来发送一条使用 JMS 的消息,然后使用一个新的 MessageDrivenBean 来使用该同一条消息。   作为 EJB 2.0 资源的 JMS   会话 bean 和实体 bean 都是基于 RPC 的组件,为了将各种事务性的组件装配到一起,这是一种卓越的体系结构。但是,在某些情况下,RPC 的同步性质会成为一种障碍,这正是 EJB 1.1 中将对 JMS API 的访问作为一种资源包括在内的原因。利用 JNDI 环境命名的上下文,bean 可以获得一个 JMS 工厂,并将一条异步消息发送给主题或队列(也从 JNDI 获得),而不必等待回应。下面是 ShoppingCart bean 的一个例子,它使用 JMS 将 Order 的详细信息发送给消息收发主题。   public class ShoppingCartBean implements SessionBean {    // 订单详细信息是一个可序列化的对象,它包含全部订单信息。    public OrderDetail orderDetail;    public void processOrder(){     // 处理订单的逻辑从此处开始     ....     // ... 处理订单以后,向其它系统发送有关此订单的一条消息     InitialContext jndiEnc = new     InitialContext();     // 使用 JNDI ENC 获取 JMS 工厂和主题标识符     TopicConnectionFactory factory =     jndiEnc.lookup("java:comp/env/jms/topicfactory");     Topic orderTopic =     jndiEnc.lookup("java:comp/env/jms/ordertopic");     // 获得一个用来发送消息的发布者     TopicConnection con = factory.createTopicConnection();     TopicSession session = con.createTopicSession(false, Session.AUTO_ACKNOWLEDGE );     TopicPublisher publisher = session.createPublisher(orderTopic);     // 将一个 ObjectMessage 发送给主题(虚拟通道)     bjectMessage message = session.createObjectMessage();     message.setObject(orderDetail);     publisher.publish(message);     con.close();    }   ...   } 在这种情况下,JMS 是用来通知另外的应用程序,订单已被处理。这些另外的应用程序对于处理订单来说并不重要,但它们会因为得到一个订单已被处理的通知而受益。这样的例子包括自动调整库存的库存系统,和能将客户添加进产品目录邮寄名单中的销售应用程序。   使用 JMS 使 bean 能够发布(发送)消息而不会发生阻塞。bean 并不知道谁将收到消息,因为它是将消息发送给某个主题(虚拟通道),而不是直接发送给另一个应用程序。应用程序可以选择预订该主题,并接收有关新订单的通知。这样就有可能动态地在虚拟通道中添加或删除应用程序,从而产生了一种更加灵活的系统。   预订了订单主题的应用程序将收到有关新订单的通知,应用程序可以使用它们认为合适的任何方式来处理这个通知。预订了各种主题的应用程序或者从各个队列中接收消息的应用程序可以是 Java 应用程序、EAI 系统(用于集成遗留系统和 ERP 系统)或者 MessageDrivenBean 组件,在 JMS 的术语中,它们全部被认为是 JMS 客户机。 JMS 和 MessageDrivenBean   虽然大多数 JMS 厂商都提供消息中介工具,来将消息从发送者路由到接收者,但构建使用(接收)消息的 JMS 客户机却是应用程序开发人员的职责。在许多情况下,接收消息的应用程序必须强健、安全、快速而且可伸缩;它需要的基础结构基本上与 EJB 应用程序相同。   由于认识到这种需要,EJB 2.0 现在包括了 MessageDrivenBean 类型,它可以使用 JMS 消息,并且在同一个强健的、基于组件的基础结构中处理这些消息,这样的基础结构对于会话 bean 和实体 bean 都非常有用。MessageDrivenBean 类型(消息 bean)是一种企业级 bean 组件,它设计来使用异步的 JMS 消息。   除了提供容器基础结构以外,EJB 还具有另一个重要的优点:并发处理。在 EJB 中,一个已部署的消息 bean 表示一个单一的消息使用者,但这个 bean 本身是由许多 bean 实例提供服务的。每个 bean 实例都可以分别地使用消息 bean 接收到的消息。这意味着,消息 bean 不必像常规 JMS 客户机那样连续地使用消息。消息 bean 可以并发地使用接收到的多个消息,这样就能达到比传统 JMS 应用程序高得多吞吐量和好得多的可伸缩性。   为了说明消息 bean 的作用,就开发了 MarketingBean 类,并将它从订单主题中部署到供使用的消息中去。MarketingBean 将从消息中提取 OrderDetail 对象,并使用它将客户添加到适当的目录邮寄名单中。这是一种最精致的大量邮寄系统。   下面是 MarketingBean 类的定义,这个类使用发布给订单主题的消息。   public class MarketingBean implements     javax.ejb.MessageDrivenBean {      public void onMessage(Message message) {       ObjectMessage orderMessage = (ObjectMessage)orderMessage:       OrderDetail orderDetail = (OrderDetail)orderMessage.getObject();       Integer customerID = orderDetail.getCustomerID();       InitialContext jndiEnc = new InitialContext();       CatalogHome catalogHome = (CatalogHome)jndiEnc.lookup("java:comp/env/ejb/catalog");       Iterator productIDs = orderDetail.getProductsIDs();       while(productIDs.hasNext()){        Integer productID = (Integer)productIDs.next();        Catalog cat = CatalogHome.findByProductID(productID);        cat.addCustomerToMailingList(customerID);       }      }     } 正像会话 bean 和实体 bean 一样,MessageDrivenBean 也是一种完备的企业级 bean,但其间仍存在一些重要的区别。消息 bean 没有远程接口或本地接口。这是因为消息 bean 不是 RPC 组件。它没有供 EJB 客户机调用的业务方法。消息 bean 监听虚拟消息通道(主题或队列),并使用其它 JMS 客户机发送给该通道的消息。   各个消息 bean 构成一个 bean 类,这个类实现 MessageDrivenBean 接口和一个 XML 部署描述符。下面是 MessageDrivenBean 接口的定义,所有消息 bean 都必须实现这个接口。   package javax.ejb;   import javax.jms.Message;   import javax.jms.MessageListener;   public interface MessageDrivenBean extends    MessageListener{     public void onMessage(Message message);     public void ejbCreate();     public void ejbRemove();     public void      setMessageDrivenContext(MessageDrivenContext mdc);    } 当部署了一个消息驱动的 bean 以后,它就被指派来处理特定主题或队列中的消息。JMS 客户机(Java 应用程序、bean 或本地客户机)发送的任何消息,将由消息路由器转发给消息 bean,该消息 bean 正是被指派来从该虚拟通道中接收消息的。当一条消息被发送给一个消息 bean 时,EJB 容器就会从某个池中选择该 bean 的一个实例,来处理这条消息。当 bean 实例调用其 onMessage() 方法时,它就会接收到这条消息,并能够以它认为合适的任何方式来处理这条消息。一旦这条消息被使用,则只要事务没有异常中止,这条消息都不会被传送给这个消息 bean 的任何其它实例。   消息 bean 在某点上类似于无状态的会话 bean,即这两种 bean 在两次请求之间都不保持任何状态。因此,消息驱动的 bean 是无状态的,但是,就像无状态的会话 bean 一样,它们也可以有实例变量,这些变量在这个 bean 实例的整个生存期内均保持。   对消息 bean 的最后一点说明是,理解这样一个事实是很重要的,即 bean 使用的消息不一定要是由其它 bean 所产生的。消息 bean 可以使用由符合 JMS 的厂商提供的任何主题或队列中的消息。消息 bean 使用的消息可以来自其它 bean(会话 bean、实体 bean 或消息 bean)、非 EJB 的 Java 应用程序、或者甚至非 Java 的应用程序(如果其供应商符合 JMS)。例如,遗留应用程序可能使用 IBM 的 MQSeries 向队列发送消息,而该消息既可以由其它遗留应用程序使用,同样可以由消息 bean 使用。   结论   与以前的规范相比,Enterprise JavaBeans 2.0 中作了一些相当大的更改。新的 CMP 模型比以前的模型要灵活得多,它允许各种实体为复杂的对象图建立模型,而同又提供跨容器的更大的可移植性。人们迫切地期待着为查找和选择操作定义一种通用的查询语言,而它也将有助于提高可移植性。   这种新的 MessageDrivenBean 类型将有助于使这种强大的消息收发范例成为众人瞩目的焦点,就像 EJB 那样。消息收发在分布式的混合计算中是一个极其重要的组成部分,将它包括在 EJB 内就是其重要性的一个证明。   在写这篇文章时,EJB 2.0 刚刚作为公开草案发布,这意味着在它成为一个最终规范之前仍有可能更改。如果更改对此处提供的材料有重大影响,届时我将设法对本文作一些注释,但这个规范正在趋于稳定,所以不太可能有真正重大的更改。 <淘宝热门商品:

小小豆叮

全面研读 EJB 2.0(中)

EJB 2.0 中的一个示例 CMP 实体   在 EJB 2.0 中,容器管理的实体 bean 被定义为抽象的,而且它的持久性字段并不在 bean 类中直接定义。作为替代,开发了一种抽象的持久性方案,从而允许 bean 提供者间接地声明持久性字段和 bean 关系。下面是 Employee bean 的一个示例,它使用了新的抽象持久性方案。请注意,该 bean 类中未声明任何持久性字段。   public abstract EmployeeBean implements   javax.ejb.EntityBean { .   // 实例字段    EntityContext ejbContext;    // 容器管理的持久性字段    public abstract void setIdentity(int identity);    public abstract int getIdentity();    public abstract void setFirstName(String firstName);    public abstract String getFirstName();    public abstract void setLastName(String lastName);    public abstract String getLastName();    // 容器管理的关系字段    public abstract void     setContactInfo(ContactInfo info);    public abstract ContactInfo     getContactInfo();    ...   }   在此 bean 的 XML 部署描述符中,抽象的持久性方案声明容器管理的各个字段和各种关系。            EmployeeEJB    ...   Container    ...   identity   firstName   lastName    ...               ContactInfo   ContactInfo   street   city   state   zip   homePhone   workPhone   email    ...            Employee-ContactInfo          employee-has-contactinfo      one      EmployeeEJB         contactInfo   ContactInfo                contactinfo_belongsto_employee      one      ContactInfo                  用来描述容器管理的关系的 XML 元素可能变得非常复杂,因为他们必须处理各种关系的对应性和方向(单向的还是双向的)。上面的代码段说明,为了描述 bean 与其从属对象类之间的简单关系,您需要哪些元素。虽然即使是简单的关系也会被转换为冗长的 XML,但所有这些元素都是必需的,以便持久性管理器能够将复杂的对象图映射到数据库中。   虽然用于定义 CMP bean 的抽象持久性方案的 XML 元素是 EJB 2.0 中的 CMP 的主要问题,但为了简洁起见,本文不再提供 XML 示例。作为替代,本文将纯粹依靠 bean 类中必须使用的抽象习语,来说明 EJB 2.0 中的 CMP 背后的基本概念。这些代码习语与 XML 部署描述符中的关系元素一起使用,并由后者定义,所以您不能只有其一而没有另一个,但它们比该方案的 XML 部分较容易理解。   除了 XML 元素之外,抽象的持久性方案还定义了一组习语,它们在声明 bean 类及其相关的对象时必然会用到。用来访问和修改字段的方法是严格定义了的,要求用 set<:METHOD> 方法修改持久性字段,而用 get<:METHOD> 方法访问它们。这些方法的名称和返回类型由部署描述符中它们相应的 XML 关系元素规定。   实体 bean 类和从属类都遵循相同的抽象持久性方案。下面是如何将 ContactInfo 对象定义为从属对象类的示例。   public abstract class ContactInfo {     file:// 家庭地址信息    public abstract void setStreet(String street);    public abstract String getStreet();    public abstract void setState(String state);    public abstract String getState();    public abstract void setZip(String zip);    public abstract String getZip();    public abstract void setHomePhone(String phone);    public abstract String getHomePhone();     // 工作地址信息    public abstract void setWorkPhone(String phone);    public abstract String getWorkPhone();    public abstract void setEMail(String email);    public abstract String getEMail();    ...   }   从属对象随实体 bean 的存在而存在,随实体 bean 的中止而中止,这是理解从属对象与实体 bean 之间关系的关键。从属对象包含在一个具体的实体中,所以删除这个实体将导致从属对象也被删除。用关系数据库的术语来说,有时这就称为级联删除。   从属对象,如 ContactInfo,用在关系字段中。与实体 bean 形成关系的从属对象技术上称为从属对象类。EJB 客户端应用程序永远不能直接访问从属对象类;这种类不能用作 bean 的远程或本地接口中的参数或返回值。从属对象类只对 bean 类才是可见的。   从属对象类不适合作为远程参数类型,因为它们与 bean 在运行时的持久性逻辑有密切的联系。持久性管理器扩展了抽象的从属对象类,以便能提供一种实现,可用于在运行时管理 bean 的持久性状态。此外,抽象的持久性方案还为数据建模 -- 而不是为那些由企业级 bean 表示的业务概念建模 -- 所以,作为一种设计策略,将抽象的持久性方案对 EJB 客户机隐藏起来是有意义的。   例如,ContactInfo 关系字段中除了 bean 的客户机所需的简单地址信息之外,还包含许多其它信息。虽然您可以使用抽象持久性方案中的从属对象类 ContactInfo(它对 bean 的客户机是隐藏的),但是,您得用其它的对象来把这些数据实际表露给客户机。下面是一个示例,说明了如何对 EJB 客户机隐藏 ContactInfo 从属对象。在此例中,地址信息是通过在 EJB 1.1 的示例中开发的 Address 对象来表露的。    // Employee bean 的远程接口   public interface Employee extends javax.ejb.EJBObject {    public Address getHomeAddress();    public void setHomeAddress(Address address);    public int getIdentity() throws RemoteException;    public void setFirstName(String firstName) throws RemoteException;    public String getFirstName()throws RemoteException;    public void setLastName(String lastName) throws RemoteException;    public String getLastName() throws RemoteException;   }    // Employee bean 的 bean 类   public abstract EmployeeBean implements    javax.ejb.EntityBean {     ...     public Address getHomeAddress(){      ContactInfo info = getContactInfo();      Address addr = new Address();      addr.street = info.getStreet();      addr.city = info.getCity();      addr.state = info.getState();      addr.zip = info.getZip();      return addr;      }     public void setHomeAddress(Address addr){      ContactInfo info = getContactInfo();      info.setStreet(addr.street);      info.getCity(addr.city);      info.getState(addr.state);      info.getZip(addr.zip);     }     ....     // 容器管理的关系字段     public abstract void setContactInfo(ContactInfo info);     public abstract ContactInfo getContactInfo();      ...    }   尽管容器管理的关系字段没有表露给客户机,但您仍然可以从远程接口直接使用容器管理的持久性字段。请注意,用来访问 firstName 和 lastName 的容器管理的持久性字段是在远程接口中使用的。   一个 bean 与各种从属对象类之间可能具有多种不同的关系,它们由这种关系的对应性和方向来定义。Bean 与从属对象类之间可以有一对多和一对一的关系。例如,Employee bean 可能仅有一个 Benefit 从属对象类,但可能有许多 ContactInfo 从属对象类。   public abstract EmployeeBean implements    javax.ejb.EntityBean {      ...     public abstract void setContactInfos(Collection addresses);     public abstract Collection getContactInfos():     public abstract void setBenefit(Benefit benefit);     public abstract Benefit getBenefit();      ...    } 与从属对象类的一对多关系既可表示为 java.util.Collection 类型,也可表示为 ava.util.Set 类型(注:在本规范的后续版本中,java.util.Map 和 java.util.List 被视为附加的返回类型),而与从属对象的一对一关系则使用从属对象的类型。   实体 bean 也可以定义与其它实体 bean 的关系。这些关系可以是一对一、一对多或多对多。例如,Employee bean 可能有许多子级 bean,而只有一个配对的 bean。下面的代码段使用抽象持久性方案的方法习语,说明了如何为这些关系建模。该应用程序中,子级 bean 和配对的 bean 都表现为 Person bean。   public abstract EmployeeBean implements    javax.ejb.EntityBean {     ...     public abstract void setSpouse(Person manager);     public abstract Person getSpouse();     public abstract void setChildren(Collection family);     public abstract Collection getChildren();      ...    } 与另一个 bean 的一对多关系表示为 java.util.Collection 类型或 java.util.Set 类型,而一对一关系则使用该 bean 的远程接口类型。   从属对象本身与同一个 bean 中的其它从属对象之间可以有一对一、一对多和多对多的关系。此外,从属对象与其它实体 bean(除其父级 bean 之外)也可以有一对一、一对多的关系。下面的示例显示,Benefit 从属对象类与 Salary 从属对象(一种报酬计算程序)之间怎样具有一对一的关系,而与 Investment bean 又怎样具有一对多的关系。   public abstract class Benefit {    public abstract void setSalary(Salary salary);    public abstract Salary getSalary();    public abstract void setInvestments(Collection investments);    public abstract Collection getInvestments();   }   在部署时,部署者将使用持久性管理器工具来具体实现这个 bean 类及其从属类。这些具体实现将在运行时保持各种关系,并使各 bean 实例的状态与数据库同步。容器将在运行时管理持久性实例,从而提供一种强健的环境,其中具有自动的访问控制和事务控制。   bean 也可以定义从属对象的值,这些对象是可序列化的对象,如 EJB 1.1 示例中的 Address 对象。这些值通过序列化而变为持久的,它们并不形成与 bean 的关系 -- 它们是严格的容器管理的持久性字段。   容器与持久性管理器之间也已经定义了一个合约,使持久性管理器可以获得事务的句柄,并访问由该容器管理的数据库连接池。这个合约稍嫌宽松,将来还需要使其更为严格,但它是允许持久性管理器跨 EJB 容器移植的基础。容器和持久性管理器之间合约的细节已超出了本文的范围。   除了通过抽象持久性方案定义持久性之外,EJB 2.0 还提供了一种新的查询语言,用来说明持久性管理器应该如何实现 CMP 中的各种查找方法。 EJB 查询语言   EJB 查询语言 (EJB QL) 规定了持久性管理器应该如何实现在本地接口中定义的各种查找方法。 EJB QL 以 SQL-92 为基础,可由持久性管理器自动编译,这使得实体 bean 具有更高的可移植性,并且更容易部署。   EJB QL 和查找方法   EJB QL 语句是在实体 bean 的部署描述符中声明的。使用 EJB QL 非常简单。作为一个例子,Employee bean 的本地接口可以按以下方式声明:   public interface EmployeeHome extends javax.ejb.EJBHome    {     ...    public Employee findByPrimaryKey(Integer id) throws RemoteException, CreateException;    public Collection findByZipCode(String zipcode) throws RemoteException, CreateException;    public Collection findByInvestment(String investmentName) throws RemoteException, CreateException;   }   给定了上面的本地接口定义之后,您就可以使用 EJB QL 来指定持久性管理器应该如何执行查找方法。每个实体 bean 都必须有一个 findByPrimaryKey() 方法。为执行该方法所需的查询是很明显的 -- 使用主关键字的(一个或几个)字段在数据库中查找 bean,这样就不需要任何 EJB QL 语句。   findByZipCode() 方法用来获得具有某个邮政编码的所有 Employee bean。这将使用部署描述符中的下列 EJB QL 来表达。   FROM contactInfo WHERE contactInfo.zip = ?1 该语句本质上是表示“选择其邮政编码等于 zipcode 参数的所有 Employee bean”。   在用于查找方法的 EJB QL 语句中,不需要使用 SELECT 子句来表明要选择的内容。这是因为,查找方法将总是选择与其自身的 bean 类型相同的远程引用。在这种情况下,就可以认为选择语句将返回远程 Employee bean 的全部引用。   如果各种查找方法都一起部署在同一个 ejb-jar 文件中,并且其间具有可导航的实际关系,那么这些查找方法就甚至可以跨越到另一些 bean 的抽象持久性方案中去。例如,findByInvestment() 方法将要求该查找查询从 Employee 导航到投资 bean 的抽象持久性方案中去。声明来表达这种查找操作的 EJB QL 语句如下所示。   FROM element IN benefit.investments WHERE element.name = ?1 以上语句是说:“选择全部这样的 Employee bean:其获利从属对象至少包含一个投资 bean 的引用,并且其名称等于 findByInvestment() 方法的 investmentName 参数。”   EJB QL 和选择方法   EJB QL 也用于一种称为 ejbSelect 方法的新查询方法中,该方法类似于查找方法,只是它仅供 bean 类使用。该方法不在本地接口中声明,所以也不显露给客户机。此外,ejbSelect 方法可返回范围更大的各种值,而不仅限于 bean 本身的远程接口类型。   存在两种选择方法:ejbSelect<:METHOD> 和 ejbSelect<:METHOD>InEntity。ejbSelect<:METHOD> 方法是全局执行的,这是指这种方法并非专用于执行该方法的 bean 实例。ejbSelect<:METHOD>InEntity 方法则专用于执行该方法的实体实例。这些选择方法在 bean 类中被声明为抽象方法,并在这些类的业务方法中使用。下面是 ejbSelect<:METHOD> 方法和 ejbSelect<:METHOD>InEntity 方法的示例,同时说明了可以如何在业务方法中使用它们。   public abstract class EmployeeBean implements    javax.ejb.EntityBean {     ...     file:// ejbSelectInEntity     public abstract Collection     ejbSelectInvestmentsInEntity (String risk);     // ejbSelect     public abstract Collection ejbSelectInvestments(String risk);     ...    } 在上面的声明中,两种选择方法运行于不同的范围。ejbSelectInvestmentsInEntity() 仅在当前的 Employee bean 实例上执行,所以它只返回雇员的风险投资。   SELECT invest FROM invest IN benefit.investments WHERE invest.type = ?1   另一方面,ejbSelect<:METHOD> 方法的范围则是全局性的,所以同一个查询将返回整个企业内所有雇员的全部风险投资。   ejbSelect<:METHOD>InEntity 选择方法可以返回 bean 的远程类型(如在上面的查询中那样)、从属对象或任何其它 Java 类型。另一方面,全局选择方法则不能返回 bean 的从属对象类型。   选择方法的 EJB QL 语句要求使用 SELECT 子句,因为它们能够返回范围更广的各种值。   新的 ejbHome 方法   在 EJB 2.0 中,实体 bean 可以声明一些 ejbHome 方法,用来执行与 EJB 组件相关的操作,但并不专用于某个 bean 实例。在 bean 类中定义的 ejbHome 方法在本地接口中必须有一个与其相匹配的本地方法。下面的代码说明了一个本地方法,它正是作为 Employee bean 的本地接口定义的。applyCola() 方法用来根据最近 COLA(生活费用调整)的增长来更新所有雇员的薪水。   public interface EmployeeHome extends javax.ejb.EJBHome    {     file:// 本地方法     public void applyCola(double increate) throws RemoteException;     ...     } applyCola() 方法在 bean 类中必须有匹配的 ejbHome 方法,它被声明为 ejbHomeApplyCola()。ejbHomeApplyCola() 方法并非专用于一个 bean 实例,它的范围是全局的,所以它将对所有雇员的薪水使用同一个 COLA。   public abstract class EmployeeBean implements    javax.ejb.EntityBean {     ...     // ejbHome 方法     public void ejbHomeApplyCola (double increase ){      Collection col = ejbSelectAllEmployees ();      Iterator employees = col.iterator();      while(employees.next()){      Employee.emp = (Employee)employees.next();      double salary =emp.getAnnualSalary();      salary = salary + (salary*increase);      emp.setAnnualSalary(salary);     }    }   } bean 的开发人员需要为 BMP 和 CMP 实体 bean 都实现 ejbHome 方法。CMP 实现可能在很大程度上要依赖于全局的选择语句(如上面所说明的那样)和 finder 方法,而 ejbHome 的 BMP 实现则将使用直接数据库访问和 bean 的 finder 方法,来查询数据和进行更改。 <淘宝热门商品:

小小豆叮

从全球观点看Java产业

自从James Gosling于1995年将Java正式介绍给世人后,Java的支持者与反对者间对Java的爱憎,几乎可说是壁垒分明。Java支持者认为在信息科技的领域里,总算出现了一个可以解放软件设计束缚的新技术,而且这个新技术是开放而免费的;反对者则无法认同有朝一日Java能够成气候,也就是说可以成为与微软(MicrosoftR)技术相抗衡的一个新标准。在此我们无意陷入上述的争论里,然而有一点是大家所不能否认的,那就是经过五、六年来的各式挑战与洗礼,Java至今仍是安然建在。更有甚者,在某些领域的应用里,Java则早已超越其它竞争对手,成为最主要的技术之一。   对于Java的认识,很多人通常仅止于知道它是一种计算机程序语言。这样的看法虽不能说错,但是我们更喜欢将之视为是一种可以支持各式计算需求(特别是与网络应用有关)的技术平台。若只是将Java看成是一种程序语言,谁又会介意我们使用的软件是以何种语言来开发?事实上可以这么说,Java的背后代表的是对于整个信息科技,例如像网络程序技术、分布式处理、无线网络应用、甚至包括电视、CTI与Smart Card等,的全面了解与整合。Java在各式软、硬件与网络、通讯等大厂的支持下,成功地成为在这些软、硬件或网络与通讯等环境上开发其对应应用软件的主要技术。例如像电子商务的几家主要平台提供者,如Broadvision、Intershop、或IBM等,其上面的应用系统开发工具几乎都是以Java环境为主。因此在看待Java时,绝不能只把它当成是另一种计算机程序语言而已。在本文里,我们将透过介绍几个主要Java应用的发展现况,以帮助大家更进一步了解Java技术所涵盖的层面与范围。   ◎Java Card / Java Ring透过Java Card技术,目前各式Smart Card应用程序的发展,将变得更简单、更有弹性外,更重要的是发展者再也不需要担心各式Smart Card平台的不同,凡是有支持Java Card规格的Smart Card,皆可做到write once run anywhere的效果。Java Card技术的另外一个好处,则是能够提供建置Smart Card上的多应用程序(multi-applications)效果。在发卡后于安全机制管控下,也能随时动态加载新的应用程序至卡上。同时Java Card技术也完全遵守如ISO7816、Europay、MasterCard、Visa、ETSI 03.19等各式标准。目前Java Card的应用包括Visa 准备新发行的低价多应用卡、America Express的Blue等新型态卡。在这类型卡上,多种不同的应用程序,如记点功能、电子钱包等,皆可于同一张卡上执行。另外,ActivCard则开始为美国国防部的国防人力资料中心,以Java Card技术开发CAC卡(Common Access Card)。这个卡将提供给所有四百多万的军方相关人员,作为身份认证、数字签名与信息编解密用。   ◎无线应用与掌上型设备对于无线应用服务的发展者而言,其中最困难处理的事情之一,就是使用者所用的手机或PDA并不像个人计算机一样,有统一的作业平台。因此当要提供一个新的服务或信息内容时,通常必须搭配特定的手机或PDA。在Java技术的支持下,这个问题已不再是个限制,J2ME(Java 2 Platform Micro Edition)即是一个可以建置在各式掌上型设备上的跨平台标准。目前Motorola 的i85s / i50sx以及Nokia 9210等手机,Palm与WinCE的PDA,皆已支持J2ME标准。而Sharp预备今年十月于美国推出的Zaurus,则是一款以Linux与Java所开发的多媒体PDA。透过这些设备,无线应用服务的发展者,才可以真正做到不用考虑使用者的掌上型设备,进而让自己发展的内容或服务获得跨平台的好处。例如Plazmic这家公司目前就提供一个叫Plazmic Media Engine的新款软件,它是以Java技术所发展、可以在J2ME上执行的多媒体播放软件。利用这样的软件,制作多媒体内容的无线应用提供者(content provider)可以只发展一个版本的内容,进而大量降低制作成本。   ◎信息家电设备除了上述J2ME的标准外,在信息家电设备的应用上,Java技术也是百花齐放。这些技术包括RealTime Java、JavaOS与JavaChip。RealTime Java最早乃由NIST(National Institute for Standards and Technology)下设立 RTJWG (RealTime Java Working Group)负责搜集相关需求,有关RealTime Java信息可参考http://www.rtj.org/。另外从作为信息家电设备发展平台的角度来看,一个简单且可跨各式CPU平台的操作系统,也是解决作法之一,JavaOS就是一个这样的典型方案。目前例如像SavaJe公司所发展,预计于今年九月推出的SavaJe XE操作系统,就是一个可作为在12MB内存、32MB RAM、190MHz以上32-bit StrongARM-based的信息家电设备上之JavaOS操作系统。透过支持标准的Java执行环境,以Java所开发的应用软件将可直接于SavaJe XE上执行。除了上述两种软件作法外,直接将Java技术做在芯片上,并将之作为信息家电设备的核心,则是另一种解法。目前AJile 公司推出的aJ-100 single chip JVM芯片,可以支持J2ME环境,就是一个典型的范例。   ◎企业应用-J2EE在企业应用的领域上,Java技术中的J2EE (Java 2 Platform Enterprise Edition)规格,可以说是目前Java应用最成功的领域之一。事实上在application server相关的市场上,J2EE兼容的产品就占了将近百分之九十。而提供这些产品的厂商则包括各大软件公司,如BEA、Sun iPlanet、HP、Sybass、Borland、SilverStream等二十五家。因此今天大部分的web-enabled应用系统,例如像本文之前所提之电子商务平台,几乎清一色皆需要以Java作为其开发工具。当然这样的领先局面,未来也将受到微软新提出的.NET技术所挑战。有关J2EE的相关介绍颇多,在此我们不再赘述。   ◎多媒体与游戏应用-JMF与Java 2D/3D一般而言Java计算能力的表现较为人所诟病,因此在多媒体或游戏领域的发展上显的较不突出。然而JMF(Java Media Framework)与Java 2D/3D的API,事实上颇为完整与好用。而更重要的是其跨平台的好处,对于专心开发节目或游戏内容的发展者而言,更是一个非常具有吸引力的关键。有关利用Java技术发展游戏软件的组织,可参考http://www.javagaming.org/。   从上述目前利用Java技术所发展的应用来看,它的几个重要特性,例如像其优越的跨平台能力(特别是在前端设备上)、开放的标准、以及完整且高阶的功能API规划等,或可看出为何Java 技术能够在目前的几个热门领域内崭露头角。而这些Java技术的应用,也可以作为国内相关产业的发展参考。 <淘宝热门商品:

小小豆叮

中间件:基础软件的新生力量

随着计算机技术的发展,各企业IT部门面临的问题也越来越多,诸如不同硬件平台、不同网络环境、不同数据库之间的互操作,多种应用模式并存,系统效率过低,传输不可靠,数据加密,开发周期过长,等等,您可能希望把5种操作系统、6种数据库、7种网络环境、80种应用和9000个网络结点,结合成一个有机的整体协同工作,这太令人头疼了。中间件就是解决这类问题的,它试图通过屏蔽各种复杂的技术细节使您面对的技术问题简单化。   在中间件产生以前,应用软件直接使用操作系统、网络协议和数据库等开发,这些都是计算机最底层的东西,越底层越复杂,开发者不得不面临许多很棘手的问题,如操作系统的多样性,繁杂的网络程序设计、管理,复杂多变的网络环境,数据分散处理带来的不一致性问题,性能和效率、安全等等。这些与用户的业务没有直接关系,全又必须解决,耗费了大量有限的时间和精力。于是,有人提出能不能将应用软件所要面临的共性问题进行提炼、抽象,在操作系统之上再形成一个可复用的部分,供成千上万的应用软件重复使用。这一技术思想最终成为了中间件这样的软件。   中间件的技术思想为什么最终能够取得成功?不使用中间件的应用软件相当于开汽车不使用排挡,想象一下,谁能不使用工具就能以合适的力度准确地拨动齿轮驾驶汽车?中间件对于应用系统而言,就如同汽车的排挡,它大大减少开发的复杂性,减少了整体开发与维护管理成本。计算机应用系统在上一个十年里走出科学计算的小圈子,轰轰烈烈地普及到商业、政府和其它公共领域,中间件及其它支撑软件功不可没。   90年代以后,中间件在整个世界范围内开始进入黄金年代。形象地看,今天的中间件就如同电梯,不难想象,在现代化的高楼大厦中不使用电梯会有什么结果。没有电梯,你即使建了大楼也不能舒适地感受登高望远的乐趣,没有中间件也难以建设一个有规模、有质量的网络应用系统。 由于应用软件越来越复杂,中间件的衍生也越来越丰富。世界著名的咨询机构GigaInformationGroup把中间件归纳为三大类,共15种。应用系统的复杂性要求中间件的丰富性,如同电梯简单了就不够用一样。例如,你可能需要一部滚梯或一部直上直下的电梯,或它们的有机组合,或者加上一部水平的传送系统,像你在机场中经常所享用的。   仅仅能够运送客户可能还不是你全部的设想!在你的预算内,你可能需要的更多!比如一组电梯要有某种机制,能够满足你所需求的高效率:按下按钮后,最可能先到达的电梯响应客人的要求,而不是在客人上方并正向更高楼层行走的电梯响应请求。你还要求高可用性;两部以上的电梯同时运行,互相备份,平进可以增加载客量,在发生故障时,至少有一部仍然能够安全运行。你又想到了均衡负载:把众多客户要求搭载的请求分配给不同的电梯响应。你进而考虑到优化问题:把高效率、高可用性、均衡负载、耗费等等因素综合起来。你可能还需要一部观光电梯,让乘梯的人能够同时观赏楼里楼外的风光,或者需要一部电梯将楼外过街天桥上的客人直接送到楼内。普通的楼梯,根本不能实现这些设想。中间件如同电梯,能够从容面对企业的关键任务(应用)系统的复杂性。   如果用一句话来概括就是,中间件以自己的复杂换取了企业应用的简单。或者说,把复杂变得简单。一栋摩天大楼,它内部一定会有多部电梯在运行,如果电梯停了,那日子一定可想而知。中间件在应用软件中所扮演的角色,就与电梯的功能极为相似,不可或缺。 <淘宝热门商品:

小小豆叮

微软XML核心服务组件MSXML 4.0亮相

微软近日正式发布了其XML的核心服务组件——MSXML 4.0。和MSXML 3.0相比,MSXML 4.0提供了大量的新功能和功能改进。其中包括:   对XML模式语言的支持;   更快的分析器和XSLT引擎;   对XML流更好的处理;   更好的一致性支持;   MSXML 4.0并不是MSXML 3.0的替代产品,因为在3.0中的一些过时功能已经在4.0中彻底去除。所以4.0可以和3.0(甚至更早的版本)同时安装。   要提醒大家注意的是:此版本不支持4.0 RTM Beta测试版升级。因此你必须完全卸载此RTM版(别忘删除system目录下的msxml4*.dll文件)。   对此感兴趣的用户可以到微软站点下载。    http://www.microsoft.com/downloads/release.asp?ReleaseID=33037 <淘宝热门商品:

小小豆叮

推荐:一个动态监视文件增长工具spylog

<淘宝热门商品:

小小豆叮

Java HotSpot性能引擎的体系结构

--有关Sun的第二代性能技术的白皮书
内容
  1. 引言
  2. 概述
  3. 体系结构
  4. 内存模型
    1. 无句柄对象(Handleless Object)
    2. 双字对象头
    3. 将映射数据表示为对象
    4. 本地线程支持,包括任务抢先和多重处理技术
  5. 内存垃圾回收
    1. 背景说明
    2. Java HotSpot垃圾回收
    3. 精确性
    4. 相继的复制回收
    5. 采用标记-整理算法的"旧对象"回收器
    6. 增量"无暂停"垃圾回收器
  6. 超快速线程同步
  7. Java HotSpot编译器
    1. 背景说明
    2. "热点(Hot Spot)"检测
    3. 方法内嵌
    4. 动态逆优化
    5. 优化编译器
    6. 小结
    7. 对软件可重用性的影响
  8. Java本地接口(JNI)支持
1. 引言

Java>TM平台正在成为软件开发和部署的主流载体。在许多领域,Java平台的使用率正在迅猛增长--从信用卡到大型计算机、从网页applets到大型商务应用程序。因此,Java技术的品质、成熟度和性能就成了对每一个开发人员和用户至关重要的因素。Sun Microsystems,Inc.正在重点投资于能够在许多处理器和操作系统面前"抬起挡路的栏杆"的技术,应用这种技术,软件开发人员可以将基于Java的应用程序,在不考虑处理器和操作系统的情况下有效而可靠地运行。

人们对Java平台感兴趣的一个主要原因是:基于Java技术的程序与用传统语言编写的程序不同,它们是以一种可移植的和安全的形式而分布的。过去,使用可移植的分布形式一般来说都意味着在程序执行中的性能要下降。通过采用现代动态编译技术,这种性能的下降得以减缓,其本质可说是"双收其利"。

举一个简单但很重要的例子:我们可以使一个Java技术编译器为特定版本的处理器"在运行中"生成优化的机器码(例如,尽管奔腾和奔腾II处理器可以运行相同的机器码,但没有一种形式的机器码可以同时对上述二者都是优化的)。于是,Java编程语言的字节码分布形式不仅可以提供移植性,而且实际上还可以为性能的提高提供新的机会。

本文将介绍Java的第二代性能技术--Java HotSpot性能引擎。Java HotSpot性能引擎几乎在其设计的每一个领域都有创新,它使用了广泛的可用来提高性能的技术;这包括可检测并加速性能关键性(performance-critical)代码"在运行中"的适配性优化技术。Java HotSpot还提供了超快速(ultra-fast)线程同步,以获取线程安全的基于Java技术的程序的最大性能;它还提供了垃圾回收器(GC),GC不仅特别快,而且是完全"精确"的(因而也更可靠);另外,采用最新技术的算法也减少或消除了用户对垃圾回收而引起的暂停的感觉。最后,由于Java HotSpot性能引擎在源代码级是以一种简洁、高级的面向对象的设计风格编写的,因而还进一步改善了维护性和扩展性。

2. 概述

下面是Java HotSpot性能引擎的主要结构性优势:

1) 更好的一般性能
  • 无句柄对象(为提高速度,对象的引用被实现为直接指针);
  • 更快的Java编程语言的线程同步;
  • 为达到更快的C代码的调出和调入,C和Java代码可共享相同的激活栈;
  • 与及时编译JIT相比较,大大减小了代码空间和启动时间总开销。
2) 最利于繁殖的(best-of-breed)性能
  • 为获得真本地代码性能,优化了本地代码编译器;
  • 适配性的"热点(Hot Spot)"检测主要集中于性能-关键性代码的优化上,从而大大减少了总编译时间和对已编译代码的内存需求;
  • 方法内嵌技术为大部分程序消除了大多数动态方法调用;
  • 对非内嵌方法的更快的方法调用。
3) 精确的、相继的(generational)复制垃圾回收器
  • 更快的对象分配;
  • 精确性提供了更准确的对象回收(与保守的(conservative)或半精确的(partially-accurate)那种可引起难以预料的内存泄漏的回收器不同);
  • 相继回收对大多数程序来说极大地提高了回收效率;
  • 对大多数程序来说, 相继回收还极大地减小了回收"旧的对象"而引起暂停所出现的频率;
  • 相继回收也为使用大量"活的(live)"对象的内存的应用程序极大地改善了性能扩展性;
  • 使用标记-整理(mark-compact)算法来回收"旧的"对象,消除了内存碎 片,增加了本地性(locality);
  • 增量"无暂停"垃圾回收器为"长寿"对象、甚至为极大量的"活"的对象在实质上消除了对象回收过程中出现的用户可视的暂停,这对等待时间敏感的应用程序(如服务器)以及大数据量的程序来说是理想的;
4) 先进的高级设计
  • 透明调试和简档(profiling)语意--Java HotSpot体系结构能够使本地代码的生成及优化对程序员完全透明,它可以按照纯字节码语意提供全部简档和调试信息,而不管内部实际上所用的优化方法。
3. 体系结构 Java HotSpot性能引擎的体系结构使多年来在Sun Microsystems的实验室里所做的研究达到了顶点。它综合采用了具有最新技术水平的内存模型、垃圾回收器和适配性优化器;并且它是以一种特别高级的和面向对象的风格写成的。

以下部分将介绍Java HotSpot性能引擎的重要的体系结构及其特性。

4. 内存模型

4.1 无句柄对象

Java 2 软件开发工具包(SDK)使用间接句柄来表示对象的引用。虽然在垃圾回收过程中,这样做会使对象的重新定位变得更加简单,但这会引发一个重要的性能瓶颈,因为大多数对Java编程语言对象的实例变量的访问都需要两个层次的间接引用。Java HotSpot性能引擎消除了句柄的概念:对象的引用被实现为直接指针,从而可提供对实例变量的C-速度访问。垃圾回收器则负责在内存被回收过程中,当对象被重新定位时,寻找并更新所有对在适当位置上的对象的引用。

4.2 双字(Tow-Word)对象头

Java HotSpot性能引擎使用双机器-字对象头,而不是象Java 2 SDK那样使用三字对象头。由于平均的Java编程语言的对象尺寸较小,因而这种技术对节省空间产生了重要作用(大约节省了8%的堆的大小)。第一个对象头的字包含了身份标识哈希码和GC状态等信息;第二个对象头的字是一个对对象的类的引用。只有数组才有第三个对象头字段,它是用来表示数组大小的。

4.3 将映射数据表示为对象

类、方法以及其它内部映射数据被直接表示为堆上的对象(尽管这些对象也许不能被基于Java技术的程序所直接访问)。这不仅简化了内存模型,而且使你可以采用与回收其它Java编程语言对象相同的垃圾回收器来回收这类映射数据。

4.4 本地线程支持,包括任务抢先和多重处理技术

每个线程方法的激活栈是使用宿主操作系统的线程模型来表示的。Java编程语言方法和本地方法可共享相同的栈,从而可允许在C和Java编程语言间的快速调用。使用宿主操作系统的线程调度机制可支持全抢先的Java编程语言线程。

使用本地操作系统的线程和调度机制的一个主要优点是,它能够透明地利用本地操作系统支持多重处理。由于Java HotSpot性能引擎被设计为对在执行Java编程语言代码时的抢先和/或多重处理引起的竞争状态是不敏感的,因而Java编程语言线程将自动利用由本地操作系统所提供的任意调度机制和处理器分配策略。

5. 内存垃圾回收

5.1 背景说明

Java编程语言对程序员的一个主要魅力在于,它是第一个可提供内置自动内存管理(或内存垃圾回收)的主流编程语言。在传统语言中,一般都使用显式分配/释放模型来进行动态内存分配。事实证明, 这不仅是造成内存泄漏、程序错误以及用传统语言编写的程序崩溃的最主要原因之一,而且还是提高性能的瓶颈, 并且是形成模块化和可再使用代码的主要障碍(如果没有显式和难以理解的模块间的协同操作,在模块界限间确定释放点有时几乎是不可能的)。在Java编程语言中,垃圾回收也是支持安全性模型所必需的所谓"安全地"执行这一语义的重要组成部分。

当一个垃圾回收器能够"证明"某个对象对正在运行的程序来说是不可访问的时候,它仅通过回收该对象就可自动地在后台处理对该对象的内存的"释放"。这种自动的处理过程不仅完全消除了由于释放太少而引起的内存泄漏,同时也消除了由于释放太多而引起的程序崩溃和难以发现的引用错误。

从传统上讲,相对于显式释放模型来说, 垃圾回收一直被认为是一种没有效率且会引起性能下降的处理过程。事实上,使用现代垃圾回收技术,可大大改善性能,且这种性能实际上要比由显式释放所提供的性能好得多。

5.2 Java HotSpot垃圾回收器

Java HotSpot性能引擎具有一个先进的垃圾回收器,它除了包含以下将要描述的先进技术特性外,还充分利用了简洁和面向对象的设计优势,提供了一个高层次的垃圾收集结构框架,这个框架可被轻松地配置、使用或扩展以使用新的回收算法。

以下将介绍Java HotSpot垃圾回收器的的主要特性。总体来讲,所用各种技术的综合结果无论是对需要尽可能高的性能的应用程序来说,还是对不期望有由于碎片而引起内存泄漏和内存不可访问的长时运行应用程序来说,都是较好的。Java HotSpot性能引擎不仅能够提供具有最新技术水平的垃圾回收器性能,而且可以保证全部内存回收,并完全消除内存碎片。

5.3 精确性

Java HotSpot垃圾回收器是一种全精确回收器, 与之形成对比的是, 许多垃圾回收器都是保守的(conservative)或半精确的(partially-accurate)。虽然保守的垃圾回收由于易于增加到一个不支持垃圾回收的系统中, 因而具有一定的吸引力, 但它却有一定的缺陷。

一个保守的垃圾回收器不能确切地断定所有对象的引用的分布位置, 其结果是, 它必须保守地假设那些看似要引用一个对象的内存字(memory word)是事实上的对象引用。这就意味着它可能导致某种错误, 例如将一个整数误认为是一个对象指针; 这会造成一些负面影响。首先, 当发生这样的错误时(实际并不普遍), 内存泄漏会不可预知地以一种对应用程序员来说实质上不可再生(reproduce)或调试(debug)的方式出现(尽管由虚悬(dangling)对象引用所引起的崩溃仍可被预防, 并且如果有足够的备份内存, 该程序仍可正确执行);第二, 由于它可能已经导致了某个错误, 因而一个保守的回收器必须使用句柄来间接引用对象(降低性能), 或者避免重新定位对象;因为重新定位无句柄对象需要更新所有对对象的引用, 这在回收器不能确切地断定一个表面上的引用就是一个真的引用时, 是不可能做到的。不能重新定位对象将会导致对象内存碎片, 且更重要的是, 它会妨碍使用以下描述的先进的相继复制回收算法。

因为Java HotSpot回收器是全精确的, 因而它可以提供几个有力的设计保证, 这在保守的回收器上是不可能提供的: · 所有不可访问的对象内存都可以被可靠地回收;

· 所有对象都可以被重新定位, 因而可对对象内存的进行整理;这就消除了对象内存的碎片并增加了内存的本地性。

5.4 相继的复制回收

Java HotSpot性能引擎采用了具有先进技术的相继复制回收器,它有两个主要优点:

· 与Java 2 SDK相比,为大部分程序较大地提高了分配速度和总的垃圾回收效率(通常提高了5倍);

· 相应地减小了用户可感觉的垃圾回收时的"暂停"所出现的频率。

相继回收器利用了在大部分程序中大多数对象(通常为95%)都是非常短命的也就是被用作临时数据结构这样一个事实,通过将新创建的对象隔离到一个对象"幼稚园(nursery)"中,一个相继回收器可以完成以下几件事:第一,因为在对象幼稚园中,新的对象就象堆栈那样被一个接一个地分配,因而分配变得特别的快,因为这样它仅涉及单个指针的更新及对幼稚园溢出的单个检查。第二,到幼稚园溢出时,大部分幼稚园中的对象已经"死了",这就使垃圾回收器可以只简单地将幼稚园中极少数存活的对象移到别处就可以了,从而不必对幼稚园中死去的对象做回收工作。

5.5 采用标记-整理算法的"旧对象"回收器

尽管相继的复制回收器可以有效地回收大部分死的对象,但较长寿命的对象仍然在"旧对象"内存区不断地堆积。从内存不足状态或程序要求的角度考虑,有时必须执行对旧对象的垃圾回收。Java HotSpot性能引擎可以使用一种标准的标记-整理回收算法,它从"根"开始遍历活对象的全部图解,然后扫描内存并整理回收由死的对象遗留的缝隙。通过整理回收堆中的缝隙(而不是将它们回收到一个释放清单中),可消除内存碎片;由于消除了释放清单搜索,则旧对象的分配将是更合理的。

5.6 增量"无暂停"垃圾回收器

标记-整理回收器不能消除所有用户可感觉的暂停, 用户可感觉的垃圾回收暂停是在 "旧的"对象(在机器术语中指已经 "活" 了一段时间的对象)需要做垃圾收集时出现的, 而且这种暂停与现存的活的对象的数据量成比例。这就意味着当有较多数据被处理时, 该暂停可能是任意大的; 这对服务器应用程序、动画或其它软实时应用程序来说,是一种非常不好的的表现。

Java HotSpot性能引擎提供了另一种使用的旧空间垃圾回收器以解决这一问题。该回收器是全增量的, 它消除了用户可探察的垃圾回收暂停。该增量回收器可平滑地按比例增加,即使在处理特大的对象数据集时,也可以提供相对不变的暂停时间。这为如下应用程序创造了极佳的表现:
  • 服务器应用程序, 特别是高可用性的应用程序;
  • 处理非常大的 "活的"对象的数据集的应用程序;
  • 不期望有用户可注意到的暂停的应用程序, 如游戏、动画或其它高交互性的应用程序。
无暂停回收器采用的是一种增量旧空间回收方案, 学术上称该方案为"列车(train)"算法。该算法是将旧空间回收时的暂停分离为许多微小的暂停(典型的暂停小于10毫秒), 然后将这些微小的暂停随着时间散布开来, 于是, 实际上的程序对用户来讲,就象是没有暂停一样。由于列车算法不是一个硬实时(hard-real time)算法, 因而它不能保证暂停次数的上限。然而, 实际上特大量的暂停是极罕见的, 并且它们不是由大的数据集直接引起的。

作为一种人们十分欢迎的有益的副产品, 无暂停回收还可以改善内存本地性。因为该算法试图将紧密 "耦合的(coupled)"对象组重新定位到相邻的内存区域中, 从而可以为这些对象提供最好的内存分页和高速缓存本地性之属性。这对操作不同的对象数据集的多线程应用程序来说, 也是非常有益的。 6. 超快速线程同步

Java 编程语言的另一个重要的诱人之处,是它提供了一种语言级的线程同步。这就使得编写带有精细的线程同步加锁的多线程程序变得十分简单。然而不幸的是,目前的同步实现相对于其它Java编程语言中的微操作来说,效率非常底,它使精细的同步的操作变成了性能主要的瓶颈。

Java HotSpot性能引擎在线程的同步实现上取得了突破,它极大地促进了同步性能的提高。其结果是使同步性能变得如此之快,以至于对大多数现实世界的程序来说,它已经不是一个重要的性能问题了。

除了在"内存模型"一节中提到的在空间方面的益处之外,同步机制通过为所有无竞争的同步(它动态地由绝大多数同步所构成)提供超快速和常数-时间(constant-time)性能, 从而也提供了它的在性能方面的益处。

Java HotSpot同步实现完全适合于多重处理并应该展示出色的多处理器性能特征。

7. Java HotSpot编译器

7.1 背景说明

Java编程语言是一种新的具有独特性能特征的编程语言。迄今为止,大部分试图提高其性能的尝试都集中在如何应用为传统语言开发的编译技术上。及时编译器是基本的快速传统编译器,它可以"在运行中"将Java字节码转换为本地机器代码。及时编译器在终端用户的实际执行字节码的机器上运行,并编译每一个被首次执行的方法。

在JIT编译中存在着几个问题。首先,由于编译器是在"用户时间"内运行于执行字节码的机器上,因此它将受到编译速度的严格限制:如果编译速度不是特别快,则用户将会感到在程序的启动或某一部分的明显的延迟。这就不得不采取一种折衷方案,用这种折衷方案将很难进行最好的优化,从而将会大大地降低编译性能。

其次,即使JIT有时间进行全优化,这样的优化对Java编程语言来说,也比对传统语言(如C和C++)的优化效果要差。这有以下几个原因:
  • Java编程语言是动态"安全的",其含义是保证程序不违反语言的语义或直接访问非结构化内存。这就意味着必须经常进行动态类型测试, 例如,当转型时(casting)和向对象数组进行存储时。
  • Java编程语言在"堆(heap)"上对所有对象进行分配,而在C++中,许多对象是在栈(stack)上分配的。这就意味着Java编程语言的对象分配效率比C++的对象分配效率要高得多。除此之外,由于Java编程语言是垃圾回收式的,因而它比C++有更多的不同类型的内存分配开销(包括潜在的垃圾清理 (scavenging)和编写-隔离(write-barrier)开销)。
  • 在Java编程语言中,大部分方法调用是"虚拟的"(潜在是多态的),这在C++中很少见。这不仅意味着方法调用的性能更重要,而且意味着更难以为方法调用而执行静态编译器优化(特别是象内嵌方法(inlining)那样的全局优化)。大多数传统优化在调用之间是最有效的,而Java编程语言中的减小的调用间距离可大大降低这种优化的效率,这是因为它们使用了较小的代码段的缘故。
  • 基于Java技术的程序由于其强大的动态类装载的能力,因而可"在运行中"发生改变。这就使得它特别难于进行许多类型的全局优化,因为编译器不仅必须能够检测这些优化何时会由于动态装载而无效,而且还必须能够在程序执行过程中解除和/或重做这些优化,且不会以任何形式损坏或影响基于Java技术的程序的执行语义(即使这些优化涉及栈上的活动方法)。
上述问题的结果是使得任何试图获取Java编程语言的先进性能的尝试,都必须寻求一种非传统的解决方案,而不是盲目地应用传统编译器技术。

Java HotSpot性能引擎的体系结构通过使用适配性的优化技术,解决了以上所提出的Java编程语言的性能问题。适配性的优化技术是Sun公司的研究机构Self小组多年以来在面向对象的语言实现上的研究成果。

7.2 热点Hot Spot检测

适配性的优化技术利用了大多数程序的有趣的属性,解决了JIT编译问题。实际上,所有程序都是花费了它们的大部分时间而执行了它们中的很小一部分代码。Java HotSpot性能引擎不是在程序一启动时就对整个程序进行编译,而是在程序一启动时就立即使用解释器(interpreter)运行该程序,在运行中对该程序进行分析以检测程序中的关键性"热点(Hot Spot)",然后,再将全局本地码(native-code)优化器集中在这些热点上。通过避免编译(大部分程序的)不常执行的代码,Java HotSpot编译器将更多的注意集中于程序的性能关键性部分,因而不必增加总的编译时间。这种动态监测随着程序的运行而不断进行,因而,它可以精确地"在运行中"调整它的性能以适应用户的需要。

这种方法的一个巧妙而重要的益处是,通过将编译延迟到代码已被执行一会儿之后("一会儿"是指机器时间,而不是用户时间!),从而可在代码被使用的过程中收集信息,并使用这些信息进行更智能的优化。除收集程序中的热点信息外,也收集其它类型的信息,如与"虚拟"方法调用有关的调用者-被调用者的关系数据等。

7.3 方法内嵌

正象在"背景说明"中所提到的,Java编程语言中的"虚拟"方法调用的出现频率,是一个重要的妨碍优化的瓶颈。当Java HotSpot适配性优化器在执行过程中,一旦回收了有关程序"热点"的信息后,它不仅能将这些"热点"编译为本地代码,而且还可以执行内嵌在这些代码上的大量的方法。

内嵌具有重要的益处。它极大地减小了方法调用的动态频率,这就节省了执行这些方法调用所需要的时间。而更重要的是,内嵌为优化器生成了大得多的代码块。这种状态可以大大地提高传统编译器的优化技术的效率,从而消除提高Java编程语言性能的障碍。

内嵌对其它代码的优化起到了促进作用,它使优化的效率大大提高。随着Java HotSpot编译器的进一步成熟,操作更大的内嵌代码块的能力将使实现更先进的优化技术成为可能。

7.4 动态逆优化

尽管上述内嵌是一种非常重要的优化方法,但对于象Java编程语言那样的动态的面向对象的编程语言来说,这在传统上一直是非常难以实现的。此外,尽管检测"热点"和内嵌它们所调用的方法已经十分困难,但它仍然还不足以提供全部的Java编程语言的语义。这是因为,用Java编程语言编写的程序不仅能够"在运行中"改变方法调用的模式,而且能够为一个运行的程序动态地装载新的Java代码。

内嵌是基于全局分析的,动态装载使内嵌更加复杂了,因为它改变了一个程序内部的全局关系。一个新的类可能包含了需要被内嵌在适当位置的新的方法。所以,Java HotSpot性能引擎必须能够动态地逆优化(如果需要,然后再重新优化)先前已经优化过的"热点",甚至在"热点"代码的执行过程中进行这种操作。没有这种能力,一般的内嵌将不能在基于Java的程序上安全地执行。

7.5 优化编译器

只有性能关键性代码才被编译,这就"购买了时间",并可将这些时间用于更好的优化。Java HotSpot性能引擎使用全优化编译器,以此替代了相对简单的JIT编译器。全优化编译器可执行所有第一流的优化。例如:死代码删除、循环非变量的提升、普通子表达式删除和连续不断的传送(constant propagation)等。它还赋予优化某些特定于Java技术的性能。如:空-检查(null-check)和值域-检查(range-check)删除等。寄存器分配程序(register allocator)是一个用颜色表示分配程序的全局图形,它充分利用了大的寄存器集(register sets)。Java HotSpot性能引擎的全优化编译器的移植性能很强,它依赖相对较小的机器描述文件来描述目标硬件的各个方面。尽管编译器采用了较慢的JIT标准,但它仍然比传统的优化编译器要快得多。而且,改善的代码质量也是对由于减少已编译代码的执行次数而节省的时间的一种"回报"。

7.6 小结

综上所述,我们可以对Java HotSpot适配性优化器的作用做如下小结:
  • 一般来说,程序启动得更快。这是因为,与JIT编译器相比,预先编译做得较少的缘故。
  • 编译过程随着时间展开,从而使编译暂停时间更短,更不被用户所注意。
  • 仅编译性能关键性代码的做法"购买了时间",从而可将这些时间用在执行更好的优化上。
  • 由于编译较少的代码, 编译代码所需的内存较少.
  • 通过使编译代码前的等待时间变得长一点,可收集信息以执行更好的优化,如内嵌,这种技术将具有深远的意义。
  • 通过高度优化性能关键性代码,使重要的代码的运行速度更快。
7.7 对软件可重用性(reusability)的影响

面向对象的编程语言的一个主要优势是,通过为软件的重复使用提供一种强大的语言机制,来增加开发的生产力。然而实际上,很少能够获得这种可重用性。因为大量地使用这些机制可能会极大地减损性能,因而程序员都必须谨慎地使用它们。Java HotSpot技术的一个惊人的副作用是,它大大地减少了这种性能的减损代价。我们相信,这将会对面向对象的软件的开发方法产生重要的影响,它将第一次允许各个公司可以充分地使用面向对象的可重用性机制,且不会减损他们的软件性能。

这种作用的示例很容易获得。一个对使用Java编程语言的程序员的调查结果将会明确表明,许多程序员都避免使用全"虚拟"方法同时也避免编写较大的方法。因为他们确信,每一个虚拟方法的调用都会导致性能的下降。同时,"虚拟"方法(也就是在Java编程语言中的非"static"或"final"那些方法)的精细使用对高可重用性的类的构造特别重要,因为每一个这样的方法的作用就象一个"异常分支(hook)",它允许新的子类修改超类的操作。

由于Java HotSpot性能引擎可自动地内嵌大部分虚拟方法调用,因此,性能下降的程度被大大地减小了,甚至在许多情况下,被全部消除了。

无论怎样强调这种作用的重要性都不会过分。因为使用重要的可重用性机制,可以大大地改变有关性能的权衡关系, 这种技术具有从根本上改变面向对象的代码的编写方式的潜力。除此之外,随着面向对象的编程方法的成熟,有一种明显的向着更细分的对象以及更细分的方法发展的趋势。这两个趋势都旨在以将来的代码风格,极力增加虚拟方法调用的频率。随着这种高级代码风格的流行,Java HotSpot技术的优势将愈发明显。

8. Java本地接口(JNI)支持

Java HotSpot性能引擎可用标准Java本地接口(JNI)支持本地方法。以前用JNI编写的本地方法在源代码和二进制代码格式上都是向上兼容的。初始本地方法接口将不被支持(JNI被部分地引入,因为旧的接口没有提供对本地方法DLLs的二进制兼容性)。
<淘宝热门商品:

小小豆叮

JAVA下的GZIP应用

gzip是目前广泛应用的一种压缩方式,它具有很高的压缩比和压缩效率.在sun公司发布的jdk中包含了java.util.zip 包,对gzip提供了直接支持.使用java语言可以很方便的实现gzip压缩和解压缩.以下是一个压缩和解压缩的最简程序. (压缩:gzip.java) import java.io.*; import java.util.zip.*; public class gzip { public static void main(String[] args) { if (args.length !=2) { System.out.println("Usage:java gzip "); System.exit(1); } try { //打开需压缩文件作为文件输入流 FileInputStream fin=new FileInputStream(args[0]); //建立压缩文件输出流 FileOutputStream fout=new FileOutputStream(args[1]); //建立gzip压缩输出流 GZIPOutputStream gzout=new GZIPOutputStream(fout); byte[] buf=new byte[1024];//设定读入缓冲区尺寸 int num; while ((num=fin.read(buf)) != -1) { gzout.write(buf,0,num); } gzout.close();//!!!关闭流,必须关闭所有输入输出流.保证输入输出完整和释放系统资源. fout.close(); fin.close(); }catch(IOException e) { System.out.println(e); } } } (解压缩:unzip.java) import java.io.*; import java.util.zip.*; public class ungzip { public static void main(String[] args) { if (args.length !=2) { System.out.println("Usage:java ungzip "); System.exit(1); } try { //建立gzip压缩文件输入流 FileInputStream fin=new FileInputStream(args[0]); //建立gzip解压工作流 GZIPInputStream gzin=new GZIPInputStream(fin); //建立解压文件输出流 FileOutputStream fout=new FileOutputStream(args[1]); byte[] buf=new byte[1024]; int num; while ((num=gzin.read(buf,0,buf.length)) != -1) { fout.write(buf,0,num); } gzin.close(); fout.close(); fin.close(); }catch(IOException e) { System.out.println(e); } } } 非面向对象语言要实现保存工作数据(如一个绘图程序保存一幅画面的定义),往往需要一个程序数据格式转换为外部 文件格式存储,工作时再反向转换的过程.实现比较麻烦,编程不透明.而java语言是一种面向对象的语言,使用它的对象序 列化特性,就可实现将工作对象(画面定义对象数据)直接写入硬盘,需要时再直接再读入内存,不需任何额外操作.实现非常 方便.但由于写出对象为java类格式,因此数据冗余度较大.当数据量很大时,往往造成存储文件很大.过多的磁盘操作也导致 数据读入花费了更多时间,占有了大量内存.采用gzip压缩存储对象是解决此类问题的有效手段.(在本人实现的一个监控系 统中,调入一幅测试画面(10万个组件,压缩前7M,压缩后600K),压缩前对如画面后内存为26M,压缩后读入内存为12M,读入速 度也大幅提高.效果十分明显). java程序开发网络应用程序是它的最大优势,但在某些低速网络情况下(Internet、拨号网络).网络往往造成传输瓶颈, 影响应用效果,对于实时性要求高的应用影响更大.采用压缩可以有效改善通信效果. 可见,在java下的对象gzip压缩有着广泛的应用价值.以下是一个简单事例程序. (串行化的数据对象文件:Data.java) import java.io.*; import java.util.zip.*; public class Data implements Serializable//继承串行序列化接口 { String name="匹配"; int age=123; float height=1.902f; } (对象压缩解压缩类文件:compressObject.java) import java.util.zip.*; import java.io.*; public final class compressObject { //将Data类型数据对象序列化对象压缩,返回字节数组,压缩后的对象数组可写入文件保存或用于网络传输 public static byte[] writeCompressObject(Data object_) { byte[] data_=null; try { //建立字节数组输出流 ByteArrayOutputStream o = new ByteArrayOutputStream(); //建立gzip压缩输出流 GZIPOutputStream gzout=new GZIPOutputStream(o); //建立对象序列化输出流 ObjectOutputStream out = new ObjectOutputStream(gzout); out.writeObject(object_); out.flush(); out.close(); gzout.close(); //返回压缩字节流 data_=o.toByteArray(); o.close(); }catch(IOException e) { System.out.println(e); } return(data_); } //将压缩字节数组还原为Data类型数据对象 public static Data readCompressObject(byte[] data_) { Data object_=null; try { //建立字节数组输入流 ByteArrayInputStream i = new ByteArrayInputStream(data_); //建立gzip解压输入流 GZIPInputStream gzin=new GZIPInputStream(i); //建立对象序列化输入流 ObjectInputStream in = new ObjectInputStream(gzin); //按制定类型还原对象 object_=(Data)in.readObject(); i.close(); gzin.close(); in.close(); }catch(ClassNotFoundException e) { System.out.println(e); }catch(IOException e) { System.out.println(e); } return(object_); } } (主程序:test.java) import java.io.*; import java.util.zip.*; public class test { public static void main(String[] args) { Data testData_=new Data(); //未压缩数据对象内容 System.out.println("name="+testData_.name+" age="+testData_.age+" height="+testData_.height); //压缩 byte[] i_=compressObject.writeCompressObject(testData_); /* 可执行保存或网络传输,需要时还原或在对端还原 */ //解压缩 Data o_=compressObject.readCompressObject(i_); //解压缩后对象内容 System.out.println("name="+o_.name+" age="+o_.age+" height="+o_.height); } } 以上只是java下应用gzip压缩的一个简单例子,请大家举一反三在自己的开发中使用.由于本人水平所限,不当之处 敬请指正.来信请寄chen@mail.dtbay.com. (程序全部经过测试, 编译环境:pentiumII 233,mem 160M,win98/linux,jdk1.2-jdk1.4) <淘宝热门商品:

小小豆叮

简析J2EE应用程序数据库类设计模式

本文主要介绍一种数据库相关类的设计模式。并介绍在J2EE框架中的具体实现,以及在事务处理方面的一些考虑。 一、设计模式简介   在开发J2EE应用程序时,通常是要找出应用程序中涉及到的各种信息,比如一个公司的产品目录,或一个网站的用户信息,我们会将这些信息放在数据库里。   在通常的设计中,我们要分析这些数据的属性和关系,然后进行数据库的逻辑设计,把各种信息用不同的表来存储。比如,要开发一个图书信息查询系统。可以创建下面两个表来分别表示书和出版社。   table Book (ID, Name, ISBN, Author, PublisherID, Price, Volume)   table Publisher (ID, Name, Telephone, Address, Postcode)   表Book包含了ID,书名,书号,作者,出版社ID,价格,页数。表Publisher包含ID,社名,电话,地址,邮编。这两个表通过出版社ID相关。   下面我们来介绍一种数据库相关类的设计的模式。   数据库相关类可以分成实体类(Entity Class)和会话类(Session Class)。   实体类对应于一个表的记录的封装,也就是该类的一个实例对应于表中的一个记录。而且,该类中的属性和记录中的字段是一一对应的。   会话类对应于对一个表中的所有记录的操作。比如增加一条记录,删除一条记录,查找记录和更新一条记录。   通过使用这种设计模式,使程序更加模块化,便于开发和维护。当然,也可以使用其他设计模式。 二、程序实现   在具体实现上面的这种模式时,往往根据具体的应用程序来选用不同的技术来实现。看到上面的描述模式后,我们很容易就发现,可以用EJB来实现(EJB分两种,实体EJB和会话EJB)。   我们知道,EJB提出来的目的是用于提供一种分布式组件系统的开发。如果我们的应用程序是一个分布式的应用系统,那么毫无疑问,使用EJB来实现能大大减轻编程的工作量。同时,通过使用EJB容器的一些高级特性,可以使应用程序更加可靠,扩展性也大大加强。这样一来,开发人员就不必关心一些底层技术,比如事务处理,安全等各个方面,而是把重点放在怎样实现业务逻辑上。但是我们应该注意,如果开发的应用不是分布式的情况下,那么采用EJB有可能大大降低系统的性能。因为,EJB调用的开销很大。   本文将探讨在不利用EJB技术的情况下如何来实现上面介绍的这个模式。   下面以开发图书信息查询系统为例。   1.实体类   如前面讲到的,实体类的每个实例与表中一个记录对应。这样,实体类的属性应该和表的每个字段一一对应。必须注意的是,实体类的实例是每个记录在内存中的对应,因此,在程序中对实例的操作并不马上反应到数据库的记录中。   在该类中,只是对数据的包装,因此,该类仅需要一些基本的方法,即setXX()和getXX()方法。   下面是一个实体类,是对Book表的封装。   class Book{    protected int  ID;    protected String Name;    protected String ISBN;    protected String Author;    protected int  PublisherID;    protected double Price;    protected int  Volume;    public void setID(int iID);    public int  getID();    public void setName(String sName);    public String getName();    public void setISBN(String sISBN);    public String getISBN();    public void setAuthor(String sAuthor);    public String getAuthor();    public void setPublisherID(int iID);    public int  getPublisherID();    public void setPrice(double dPrice);    public double getPrice();    public void setVolume(int iVolume);    public int  getVolume();    public Book(int iID, String sName, String sISBN, int iPublisherID, double dPrice, int iVolume);   };   同样地可以对表Publisher进行封装。   2.会话类   会话类主要是对一个表进行处理。这些操作可以是在表中创建一条记录,删除一条记录,更新一条记录和查找一条记录。这些操作的结果是将表中的记录和内存中的实体类的实例对应起来,或将实例与表中的记录对应起来。   我们可以看一下对Book表的封装。   class BookTable{    void Add(Book book);    void Delete(Book book);    void Update(Book book);    Collection findbyID(int iID);    Collection findbyXXXX(XX,XX);    Collection findbyPulisherName(String sPublisherName);   };   上面的类的申明中,Add()用于将内存中的一个Book实例映射到数据库中。Delete()用于删除数据库中的某一个记录。Update()用于更新表中的一个记录。而findbyXXXX()则对应于SELECT语句。   对于涉及到多个表操作时,可以有两种方式。一种是象BookTable一样,专门封装一个类。另一个方法是,直接在BoolTable中写一个findbyPublisherName()。这个方法设计成返回一个Book的集合。   上面只是简单的介绍了怎样实现实体类和会话类。在具体的应用中,还要考虑到数据库操作的一致性。下面就介绍一下事务处理的相关内容。 三、事务处理   为了确保对数据操作的完整和一致,在程序设计时要充分考虑到事务处理方面的问题。   1.JDBC中怎样将多个SQL语句组合成一个事务。   在JDBC中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动的得到事务确认。为了能将多个SQL语句组合成一个事务,要将auto-commit模式屏蔽掉。   在auto-commit模式屏蔽掉之后,如果不调用commit()方法,SQL语句不会得到事务确认。在最近一次commit()方法调用之后的所有SQL会在方法commit()调用时得到确认。   下面的代码是一个示范:   con.setAutoCommit(false);   PreparedStatement updateSales=con.prepareStatement("UPDATE COFFES SET SALES=? WHERE COF_NAME LIKE ?");   updateSales.setInt(1,50);   updateSales.setString(2,"Colombian");   updateSales.executeUpdate();   PreparedStatement updateTotal=con.prepareStatement("UPDATE COFFEES SET TOTAL =TOTAL+ ? WHERE COD_NAME LIKE ?");   updateTotal.setInt(1,50);   updateTotal.setString(2,"Colombian");   updateTotal.executeUpdate();   con.commit(0;   con.setAutoCommit(true);   2.J2EE中分布式事务处理   在J2EE中,程序里可以使用JTA来调用底层的JTS(JAVA Transaction Service 提供者服务)来处理分布式的事务处理。另外,如果使用EJB,可以通过在描述文件中指定transaction的属性来实现。   有关分布式事务处理的具体内容,请参见J2EE规范。 <淘宝热门商品:

小小豆叮

方正电子青睐金蝶领先的J2EE应用服务器平台

近日,北大方正电子有限公司与金蝶中间件公司达成战略合作,在其国内市场占有率达90%以上的出版业解决方案中捆绑金蝶中间件公司的Apusic J2EE应用服务器。   作为国内领先的互联网基础架构软件供应商,金蝶中间件公司早在97年就开始了JAVA核心技术地研究,其于2000年12月推出的Apusic J2EE应用服务器是国内第一个自主版权的JAVA2核心平台。经严格测试及与国外同类产品全面比较,Apusic以其技术领先、性价比高、中文支持更好、本地化开发级服务、满足国家信息安全战略需要等众多优良特性打动了方正电子。 随着J2EE技术架构的日益普及,中间件J2EE应用服务器产品已成为世界增长最快的软件市场,据IDC预测:2001年全球有87%的新应用采用J2EE应用服务器,JAVA技术人员的增长率达到了110%。由SUN、IBM、BEA、ORACLE等世界众多IT巨头倾力支持的JAVA平台技术已成为全球企业级计算的工业标准,其增长率远远超过WINDOWS体系架构。J2EE技术架构中的核心部分,J2EE应用服务器更被誉为是“电子商务及互联网的操作系统”。 长期以来,JAVA核心技术都被国外厂商所垄断,金蝶中间件公司凭其超前的技术眼光和领先的技术优势彻底打破了国外厂商在这一核心领域的垄断地位。方正电子与金蝶中间件的合作是继联想集团、金蝶软件、中华网、8848、中科院计算所等业界众多知名厂商与之合作后,又一国内领导厂商在该领域与其携手,这不仅预示着在国内主要IT领导厂商地大力推动下,代表开放和先进的JAVA技术即将在中国软件市场普及,而民族系统级核心技术也凭其过硬的实力获得国内市场的青睐。 据悉,金蝶中间件公司即将推出的Apusic2.0版本,将成为民族软件进军核心技术的又一问鼎力作,其完全支持最新发布的J2EE1.3规范,技术与国际完全同步,将最先进的EJB2.0组件技术、WEB SERVICE技术、应用集成技术、门户技术等率先带给国内用户。 金蝶中间件公司的母公司金蝶软件是中国最著名的企业应用软件厂商,通过金蝶中间件公司的核心技术纽带,方正电子也将在应用软件领域与金蝶软件联手开拓行业市场。 <淘宝热门商品:

小小豆叮

ApusicJ2EE应用服务器获软博会金奖

近日获悉,经第四届中国国际软件博览会专家评审委员会评审,金蝶Apusic J2EE应用服务器获软博会参选软件项目金奖第一名。这是继该产品获得深圳市“电子商务解决方案优选项目”和科技部2001年第四批创新基金无偿支持项目后,第一次在国家级软件项目评选中登台亮相即获得如此殊荣。 金蝶Apusic J2EE应用服务器发布于2000.12.12日,是国内第一个完全支持SUN公司J2EE规范的100%纯JAVA应用服务器,为JAVA应用提供了集成化的开发、运行和管理环境。与国际同类产品,如IBM的Websphere、BEA的Weblogic相比,Apusic采用了同样的核心技术,并在易用性、中文化、性价比、本地化开发级服务支持方面表现更好。 金蝶Apusic J2EE应用服务器的获奖,表明我国软件产业在以下几个方面获得重大突破: 1、作为国家大力支持的系统级中间件软件类别,国内除了在传统的交易、消息中间件方面有所建树外,在代表互联网和电子商务计算潮流的平台性中间件J2EE应用服务器方面也拥有了自主版权的产品。Apusic的出现,彻底打破了国外产品的垄断地位,在帮助政府、企业构建一个基本的低成本、安全、可靠的电子商务系统环境方面将具有重大的战略意义。 2、国内以金蝶中间件公司等为代表的系统软件厂商,在追踪国际最新技术、保持技术同步方面做出了重大贡献。Apusic J2EE应用服务器的出现,表明我国在目前最热的JAVA技术领域不仅与国际保持同步,而且更掌握了JAVA的核心技术,这意味着包括金蝶在内的任何一个软件公司,都可以选择Apusic的产品来开发JAVA应用软件和电子商务项目,彻底摆脱了国外产品的控制,能享受性价比更高的本地化开发级服务。 3、扭转我国软件产品只偏重于应用,而没有核心技术的局面。由于类似红旗linux和金蝶Apusic这样的系统软件厂商的大力推动,我们的电子商务系统可以构筑在linux+apusic这样可靠、低成本、安全的运行环境下,并能从核心技术层面帮助广大的应用软件厂商开发先进的多层互联网应用系统,保持产品技术的持续领先,增强产品的竞争力。 金蝶作为国内应用软件的领导厂商,对基于互联网的应用系统更有着深刻的理解,利用其下属中间件公司领先的JAVA中间件技术,可以促进广大软件厂商采用最新技术,推动JAVA技术在国内的迅速普及。 <淘宝热门商品:

小小豆叮

从商业角度分析J2EE与WINDOWS DNA 体系结构

这份白皮书的以下部分要讨论: 与COM+、WINDOWS DNA相比较,使用EJB、J2EE所能带来的商业好处。 1 业界支持 任何一个商业化的技术要想拥有良好的市场态势,业界内重要企业的大量参与是十分重要的。J2EE是由SUN引导,各厂商共同发起的,并得到广泛认可的工业标准。业内‘企业计算’领域的大企业如:IBM , BEA Systems, Oracle等都有参与。 在J2EE规范制定阶段让供应商参与进来,能够吸收他们在企业计算领域多年来成熟的经验,而且能够推动他们迅速开发出J2EE的产品。因为采取了以上策略,现在已经超过25个不同的服务器端平台支持J2EE 规范。 由于采用开放的协作制定规范,J2EE也体现了众多企业计算领域供应商的知识和专业技术。这意味着产品解决方案能够满足任何商业需求。由于有大量的厂商支持,所以用户的选择范围会更广泛。 与此相比,WINDOWS DNA架构是由微软单独制定并完成的。客户若是选择了这种没有得到业界广泛支持的专有架构,就会把他们局限在某一个供应商的技术实现上。这会就妨碍客户将来采用其他供应商的产品,而这些产品很有可能最适合某一企业的特定需求。 2保护已有的IT投资 由于公司必须适应新的商业需求,利用已有的企业信息系统方面的投资,而不是重新制定全盘方案就变得很重要。这样,一个以渐进的(而不是激进的,全盘否定的)方式建立在已有系统之上的服务器端平台机制是公司所需求的。 J2EE架构可以充分利用用户原有的投资,如一些公司使用的BEA Tuxedo、IBM CICS, IBM Encina,、Inprise VisiBroker 以及Netscape Application Server。这之所以成为可能是因为J2EE拥有广泛的业界支持和一些重要的‘企业计算’领域供应商的参与。每一个供应商都对现有的客户提供了不用废弃已有投资,进入可移植的J2EE领域的升级途径。由于基于J2EE平台的产品几乎能够在任何操作系统和硬件配置上运行,现有的操作系统和硬件也能被保留使用。 J2EE能够保留现存的IT资产有以下三方面的好处: 应用程序能被利用 已有的代码在J2EE方案中可被重用,一个应用程序可重新划分层次而不用重写。这样就减少了开发时间,加快了进入市场的步伐,降低了开发成本,把项目保持在合理预算水平上。这同时也降低了企业的风险,因为公司可以使用已被验证和曾经运作的方案,而不是撤掉已有系统从新编写。 已有的产品和使用许可协议能被利用 如果一个公司已经购买了某些已有技术的使用许可协议或维护协议,如中间件,操作系统或硬件方面的许可协议,这些许可在J2EE环境中仍能被使用。因此能够降低项目成本,缩短培训时间。 对供应商的依赖性更小 因为正在为你服务的供应商提供了用于J2EE平台的产品,整体上只有一个供应商,你不需要依靠两个供应商的帮助在他们产品之间建立连接。这就减小了应用程序的复杂性,降低了整体风险水平。 与此相对照,微软的WINDOWS DNA 架构要求客户购买并安装WINDOWS 2000,还有可能需要客户购买新的硬件。客户就没有机会使用原有供应商的许可或维护协议,增加了项目成本。 我们也应当看到WINDOWS DNA 确实提供了到用户已有系统的连接,可是客户使用这种连接要依靠两个供应商:微软和现在为你提供产品的供应商。仅用一个供应商的方案通常比两个供应商的连接方案更易管理,更可靠。 3保护未来的IT投资,适应变化 今天,一个公司的IT部门的灵活性与适应性是保持公司在市场中的竞争优势的源泉。公司应迅速改进程序,以期对变化的市场环境做出反应,同时公司通过更短时间内面向市场,比竞争对手更快的采取应对措施可以在竞争中取得飞跃。通过设计能够适应更多的用户负载或事务需求的商务系统,IT部门能够按照市场需求规划部署。 J2EE能让一个公司具有更强的适应变化的能力。因为每一个基于J2EE平台的产品都保证支持最基本的J2EE服务。公司可以只需构造一次编码良好,符合J2EE的程序,然后在部署时按应用环境做出决策。如果底层平台的功能、伸缩性或可用性还不足以满足新的市场需求,用户可以有其他选择。如果客户的J2EE应用程序设计良好,并能符合标准,这个系统可以随着时间的推移通过更换底层中间件、操作系统或硬件来进行放缩,却不会显著地更动应用程序。用这种方式对未来IT投资的保护是很具吸引力的建议。对市场需求的反应时间缩至最短,可以让公司以INTERNET所要求的那种速度采取行动。 而WINDOWS DNA没有提供象J2EE平台那种层次的对变化的适应性。客户采用WINDOWS DNA就会被绑在中间件和操作系统的微软实现上,如果这个实现的功能性、可伸缩性、可用性不尽人意,客户只能怪自己不够走运。如对底层的操作系统和中间件作些修改就会显著影响应用程序。可被选择的硬件也十分有限。这都会极大地延误公司对变化的市场环境做出反应。 4切入市场的时间 在今天的市场开发商业方案,数月时间已经是很漫长的概念,错失一个很小的首先切入市场的机会都会意味着你的公司要花费数年的时间去追赶。 缩短切入市场时间的一种方法就是选择便于应用程序快速开发的服务器端平台。J2EE和WINDOWS DNA都允许公司把一些通用的、很繁琐的服务端任务交给中间件供应商去完成。这样开发人员可以集中精力 在如何创建商业逻辑上,相应地缩短了开发时间。 然而基于J2EE平台的高级产品比WINDOWS DNA 提供了更大范围的中间件服务。这种有点有些来自于J2EE平台结构本身的优势,一些是由于J2EE能让供应商鲜明地提供各种不同特性而同时保持与平台的兼容性。以下这些复杂的中间件服务是高级中间件供应商所提供的,而在WINDOWS DNA 中却不具备的: 状态管理服务:可以让开发人员写更少的代码,不用关心如何管理状态,这样能够更快地完成程序开发。 持续性服务:可以让开发人员不用对数据访问逻辑进行编码就能编写应用程序,能生成更轻巧,与数据库无关的应用程序,这种应用程序更易于开发与维护。 分布式共享数据对象CACHE服务:可以让开发人员编制高性能的系统,极大地提高整体部署的伸缩性。 公司选择基于J2EE平台实现以上服务的产品,可比选用基于WINDOWS DNA方案 能更快地切入市场,实现更高水准的伸缩性能。 J2EE平台快速切入市场的特性也有益于那些已拥有成型的电子商务软件的供应商,如SAP, Peoplesoft、 Trilogy、 Oracle、 Tradex、 EC Cubed、 Integral、 I-mind 和 Intershop。供应商选择J2EE平台能够构造部署到任何客户目标平台的可移植程序,这些目标平台包括WINDOWS、UNIX、其他已有系统,也包括任何基于J2EE平台的产品。供应商选择微软平台只能支持部署在WINDOWS上的一小部分用户。基于J2EE的程序是独立于某一特定技术的,如数据库、操作系统或硬件。这对一个拥有广泛的异构环境下客户的供应商是必需的。J2EE比WINDOWS DNA 提供更多地底层平台服务,有助于软件供应商更快地程序开发,更迅速地市场切入。 5平台的成熟性 自从1996年12月MTS发布以来,WINDOWS DNA,COM+的服务器端构件服务被不断发展,而J2EE、EJB产品则是从1998年开始的。 看起来好像WINDOWS DNA 是一个成熟的平台。然而事实上,现在基于J2EE平台的高端产品包含一些重要的事务逻辑,而这些事务逻辑应用在产品中许多年了。提供J2EE平台商业实现的供应商(如IBM、BEA)都有很长的、得到认可的发布中间件产品的历史。这些中间件产品能实现大宗的事务系统。这些供应商不是从零开始构造服务器端平台(微软的MTS却是如此),一些供应商是通过在已得到验证的现有技术上开发一个基于J2EE平台的具有可移植性的层来实现J2EE平台。这包括CORBA产品、事务处理监视器、数据库、和/或应用服务器,以上这些技术以前都是各企业专用的。在一些基于J2EE平台的产品内的技术实现着大批的现今的商业事务,这些技术早在微软进入服务器端商业领域以前就已产生。拥有早已得到认可的技术的J2EE产品供应商有: IBM's WebSphere 逻辑上脱胎于IBM's MQSeries、 CICS 与 Encina,而今天大多数重要的实时任务系统的事务都依靠这些产品来运转。 BEA's WebLogic 这个产品自从微软1996年首次推出MTS就已被投入市场。WEBLOGIC提供到M3和Tuxedo的连接,能够让IT部门使用事务处理监视器技术,这项技术有浓厚的可靠性历史。 Oracle's Oracle 8i 能够支持以下技术:数据库服务、服务器端构件以及单个物理层上的WEB服务。Oracle 8i 是以ORACLE公司在市场上占领导地位的数据库技术和在线交易处理技术为基础的。 Netscape's Netscape Application Server 基于Kiva应用服务器技术。 1996年开始使用,现在很多大型商业网站都靠它来驱动。 IONA's iPortal Application Server 基于OrbixWeb技术, OrbixWeb是一种CORBA产品,它有很长的发布历史,提供一系列强大的高级中间件服务。 Inprise's Inprise Application Server 基于VISIBROKER,这是一种CORBA产品,长期以来一直被业界采用,并被部署在一些大型公司的站点上。 因为IT部门可以利用已有的、历经考验的技术,这在很大程度上减少了危险因素。 6 可伸缩性 公司必须要选择一种服务器端平台,这种平台应能提供极佳的可伸缩性去满足那些在他们系统上进行商业运作的大批新客户。Windows 2000 Datacenter Server在2000年2月份被认为是微软最具伸缩性的方案。据称每台机器可支撑到16个处理器,若通过OEM则可达到32个处理器。把多个装有Windows 2000机器集簇到一起,在理论上则可达到上百个处理器。要达到这样高水平的伸缩性,服务器平台必须具有跨多台机器传送客户请求的功能。微软的构件负载平衡技术就是为了在多个COM+构件上传送客户请求。 遗憾的是,微软最近宣布由于功能不够完善,构件负载平衡技术已经从‘WINDOWS 2000’2000年2月发布版中取消。这意味着涉及到COM+的中间层被限定到一台机器上,进而不能提供大型商业网站所需要的伸缩性。 然而基于J2EE平台的应用程序可被部署到各种操作系统上。例如可被部署到高端UNIX与大型机系统,这种系统单机可支持64至256个处理器。J2EE领域的供应商提供了更为广泛的负载平衡策略。能消除系统中的瓶颈,允许多台服务器集成部署。这种部署可达数千个处理器,实现可高度伸缩的系统,满足未来商业应用的需要。 通过伸缩性的例子,我们也可看出选择专有技术如WINDOWS DNA的危险性。客户没有选择余地,只能等待供应商完成指定的特性。然而选择J2EE这种开放结构,客户可以选择产品,还能保留在现有应用开发方面的投资。如果基于J2EE平台的应用程序设计正确,客户可以变更产品供应商,以最小的移植代价来满足一定的伸缩性或功能需要。 7长期的可用性 一个服务器端平台必须能全天候运转以满足公司客户、合作伙伴的需要。因为INTERNET是全球化的、无处不在的,即使在夜间按计划停机也可能造成严重损失。若是意外停机,那会有灾难性后果。随着INTERNET越来越成为主要的交易平台,这种事态现着愈发严重了。 J2EE部署到可靠的操作环境中,他们支持长期的可用性。一些J2EE部署在WINDOWS环境中,客户也可选择健壮性能更好的操作系统如Sun'sSolaris、IBM OS/390。最健壮的操作系统可达到99.999%的可用性或每年只需5分钟停机时间。这是实时性很强商业系统理想的选择。 基于微软技术的部署过去还不能达到这样高水平的可用性。WINDOWS DNA绑在WINDOWS 操作系统上,而这种操作系统过去一直由于可靠性不高受到批评。微软自己高度赞扬他的WIN 2000具有高度的可用性。但是否能达到以上这些操作系统的水平仍待观察。尽管微软的一些老客户要选择WINDOWS 2000,任务时实性很强主流商务站点会采取保守姿态。 8产品的总体成本 购买服务器端平台,我们必须考虑拥有这个产品的总体成本。它包括:服务器平台的价格、在这个平台上开发和改进方案的成本、维护费用、由于伸缩性、不稳定性问题所消耗的部署时间、由于平台的缺陷所损失的客户。较低的总体成本是拥有大宗业务、要求时实性强的商业站点所必需的。 基于J2EE平台的产品价位范围很广,各种类型的公司都可以找到满足他们预算水平,所需求服务的产品。产品有完全免费(如代码公开的Bullsoft's JOnAS)、每机2500美元(Valto's Ejipt)、每CPU35000美元(IBM's WebSphere Enterprise Edition)。而微软指定的最初价位是:Windows 2000 Advanced Server每机3999美元外加1999美元(由于INTERNET连接造成无限授权的INTERNET用户)。 微软的价位是处在基于J2EE产品价位的中低档。微软还没有宣布Windows 2000 Datacenter Server, Windows 2000 AppCenter Server价格,因此现在我们还无法把微软的高端平台与大部分J2EE平台相比。以后会因为竞争的存在,各中间件供应商包括微软会按照所提供的服务水平而达成相近的价位。 无论价格战的结果如何,J2EE架构都会比Windows DNA节省更多的整体成本。这是因为采用J2EE架构,IT部门可更充分利用在应用程序、中间件技术、操作系统方面已有的投资。基于J2EE开发的成本(最初的、后续的成本)也会显著降低。这是因为对于程序员,开发面向J2EE平台程序时,一些棘手的中间件任务可被隐式地完成,而WINDOWS DNA则不可以。开发符合J2EE规范的应用程序时,程序员可以花费更多的时间专注于业务逻辑的实现,提高了开发效率。 9 多种选择与限定在某个供应商 Windows DNA 与 J2EE一个很大的不同点是:微软的方案是专用的,排除了竞争的可能(导致垄断)而J2EE公开标准,引入竞争(自由市场)。 竞争的好处是:价格被降低;优秀的产品会出现;客户有选择权和灵活性而不是固定在某一个供应商的方案上;极大降低客户的风险水平。竞争的缺点是:制定开放的标准需要额外的工作来确保兼容。一些开放标准如SQL、CORBA在过去都曾因缺乏这种保证而深受其害,结果一些专用产品出现了。 Sun Microsystems为解决这个问题在J2EE发布中包括了一个称为‘J2EE兼容性测试套件’的产品。所有中间件供应商必须成功通过这个测试才能获得J2EE认证标志。这就确保了J2EE应用程序代码可以只开发一次,然后在任何基于J2EE平台的产品中编译、运行。客户有选择的机会,避免了依赖某一个供应商。 事实上,Sun Microsystems已成功地应用测试套件的方法来保证J2SE(JAVA2平台标准版)的兼容性。现在你可以创建基于JAVA2平台的程序仅一次,然后可以部署到任何兼容的JAVA虚拟机上。这个方法在J2EE上也是行得通的。J2EE兼容性测试套件是解决不兼容的服务器端平台的关键。读者也应该注意到,由于J2EE领域激烈的竞争,供应商业会提供超越J2EE标准的便利服务。这由供应商来决定增加哪些特性是适宜的。 10 支持异构环境 一些大的公司拥有异构的服务器端部署环境,使用多种操作系统、硬件、中间件产品。异构的环境在以下情况也可能出现:要完成多个不同项目的机构;对拥有不同部署环境的公司进行合并、收购。在以上情形中,跨异构操作系统的可移植性与互操作性是非常重要的。 J2EE能够开发部署在异构环境中的可移植程序。基于J2EE的应用程序不依赖任何特定操作系统、中间件、硬件。因此设计合理的基于J2EE的程序只需开发一次就可部署到各种平台。这在典型的异构公司计算环境中是十分关键的。J2EE标准也允许客户订购与J2EE兼容的第三方的现成的组件,把他们部署到异构环境中,节省了由自己制订整个方案所需的费用。 WINDOWS DNA(包含COM+组件)只能应用到WINDOWS 2000上,不能在现有的系统上使用。这对任何一个拥有异构环境的公司都是难以接受的。另外,选择WINDOWS DNA,公司要在异构环境中引入新的操作系统,使整个系统更加复杂。公司购买现成的组件也只能部署在WIN 2000上,限制了它的使用。 在异构环境中,不同系统的互操作或通信是非常重要的。在两个不同的J2EE系统中,同种J2EE产品可以相互通信。两个不同供应商的产品也可通信,但是由于缺乏标准机制,不同供应商的产品的事务、安全信息不能互操作。在新版的J2EE规范中将会制订一个标准协议实现完全互操作性,并且不影响已有的程序代码。微软不想遵循这个协议,所以它的服务器端产品仍是专用的,不能和其他供应商的产品互操作。 11 可维护性 通常,公司只评估一个项目整个部署过程中的成本。然而整体成本应包括一个已实现的方案的维护费用。使用J2EE要比利用WINDOWS DNA开发的应用程序更易于维护。基于J2EE平台产品支持更广泛的组件类型和中间件服务,可以让开发人员投入精力在亟待解决的商业问题而不是中间件上。开发人员利用底层平台构造灵活、易维护的企业系统,这类系统不用作大的调整就可以适应新的中间件、数据库或数据库规划。 与此相比WINDOWS DNA 部提供如此广泛的中间件功能。在构造系统时要编写更多代码,增加了程序的复杂性,不能把商业逻辑与中间件功能清晰地分开。而且终端程序将难于维护,当开发组变更,项目交接时情况更糟。 总结:二十一世纪,随着Internet日益成为主要的商业交易平台,具有可伸缩性、灵活性、易维护性的商务系统是人们关注的焦点。而J2EE恰好提供了这样一个机制。通过以上对比,使用J2EE的好处显而易见,并且随着时间的推移,将会愈发显出它的生机。 <淘宝热门商品:

小小豆叮

一个功能比较全的JMail程序

<淘宝热门商品:

小小豆叮

用java实现上传下载功能

<淘宝热门商品:

小小豆叮

编写高级应用程序

新的JavaTM 虚拟机(VMs)具有能够提高性能的特点, 并且你可以使用许多工具来提高应用程序的性能或减小一般类文件的尺寸。这种Java虚拟机的特性和工具可使你在不改变应用程序、或对应用程序仅做很小改动的情况下, 提高应用程序的性能。

Java虚拟机的特性

Java2与过去的版本相比, 性能已有很大提高, 其中包括更快的内存分配、类尺寸的减小、垃圾收集的改善、最新型的监控器和作为标准的内联JIT技术。当使用新的Java2虚拟机时, 你会看到这种性能的改善; 然而, 如果你能够理解速度是如何提高的, 你就能够调整你的应用程序, 以充分挖掘每一点性能潜力。

方法内联

Java虚拟机的Java2版可在运行时自动内联简单方法。在一个未优化的Java虚拟机中,每调用一次新的方法,就创建一个新的堆栈帧(stack frame)。创建一个新的堆栈帧需要一些额外的资源以及该栈的某些再映射(re-mapping),其结果将导致系统开销的少许增加。

由于方法内联可在你的程序中减少方法调用的次数,因而可提高性能。Java虚拟机内联代码内联了返回常数或仅访问内部域(internal fields)的方法。为了利用方法内联,你可以从以下两件事中选做其一;即:你可以使一个方法对虚拟机所要执行的内联看上去是有吸引力的,或者你可以手工内联一个方法,只要它不破坏你的对象模型。在这一语境中的手工内联意味着可以直接从一个方法中将代码移动到正在调用该方法的方法中。

下面的小例子演示了虚拟机的自动方法内联:

public class InlineMe {



    int counter=0;



    public void method1() {

        for(int i=0;i<1000;i++)

        addCount();

        System.out.println("counter="+counter);

    }



    public int addCount() {

        counter=counter+1;

        return counter;

    }



    public static void main(String args[]) {

        InlineMe im=new InlineMe();

        im.method1();

        }

}

在当前状态,addCount方法对虚拟机中的内联探测器显得是没有吸引力的,因为addCount方法返回一个值。要发现该方法是否被内联:


java -Xrunhprof:cpu=times InlineMe



它生成一个java.hprof.txt输出文件。前十个方法类似下面的结果:

 

CPU TIME (ms) BEGIN (total = 510) Thu Jan 28 16:56:15 1999

rank self accum  count trace method

 1  5.88%  5.88%    1  25 java/lang/Character.

 2  3.92%  9.80% 5808  13 java/lang/String.charAt

 3  3.92% 13.73%    1  33 sun/misc/Launcher$AppClassLoader.getPermissions

 4  3.92% 17.65%    3  31 sun/misc/URLClassPath.getLoader

 5  1.96% 19.61%    1  39 java/net/URLClassLoader.access$1

 6  1.96% 21.57% 1000  46 InlineMe.addCount

 7  1.96% 23.53%    1  21 sun/io/Converters.newConverter

 8  1.96% 25.49%    1  17 sun/misc/Launcher$ExtClassLoader.getExtDirs

 9  1.96% 27.45%    1  49 java/util/Stack.peek

10  1.96% 29.41%    1  24 sun/misc/Launcher.

如果你将addCount方法改变为不再返回一个值,则虚拟机可在运行时将其内联。为使内联代码更友好,应用下面的程序替换addCount方法:


public void addCount() {

        counter=counter+1;

}



再次运行profiler:



java -Xrunhprof:cpu=times InlineMe



这次,java.hprof.txt的输出应该显得是不同的。

AddCount方法已经消失。它已被内联了!



CPU TIME (ms) BEGIN (total = 560) Thu Jan 28 16:57:02 1999

rank self  accum  count trace method

 1  5.36%  5.36%    1  27 java/lang/Character.

 2  3.57%  8.93%    1  23 java/lang/System.initializeSystemClass

 3  3.57% 12.50%    2  47 java/io/PrintStream.

 4  3.57% 16.07% 5808  15 java/lang/String.charAt

 5  3.57% 19.64%    1  42 sun/net/www/protocol/file/Handler.openConnection

 6  1.79% 21.43%    2  21 java/io/InputStreamReader.fill

 7  1.79% 23.21%    1  54 java/lang/Thread.

 8  1.79% 25.00%    1  39 java/io/PrintStream.write

 9  1.79% 26.79%    1  40 java/util/jar/JarFile.getJarEntry

10  1.79% 28.57%    1  38 java/lang/Class.forName0

新型同步

在Java 2发布之前,同步的方法和对象总是引发一些额外的性能干扰,这是因为用来实现这种代码锁定的机制采用了一种全局监控器注册,它在某些区域仅仅是单线程的(如搜索现存监控器)。在新发布的Java 2中,每个线程都有一个监控器注册,从而消除了许多现存的性能瓶颈。

如果你曾经使用过其它锁定机制来避免同步方法的性能干扰,现在则有必要重访这些代码并考虑新的Java 2新型锁定技术。

在下面的为同步块创建监控器的例子中,你可以将速度提高40%。所用时间在采用JDK1.1.7和采用Sun Ultra 1上的Java 2时分别为14ms和10ms。


class MyLock {



  static Integer count=new Integer(5);

  int test=0;



  public void letslock() {

     synchronized(count) {

        test++;

     }

  }

}



public class LockTest {



  public static void main(String args[]) {



     MyLock ml=new MyLock();

     long time = System.currentTimeMillis();



     for(int i=0;i<5000;i++ ) {

      ml.letslock();

     }

     System.out.println("Time taken="+

      (System.currentTimeMillis()-time));

  }

}

Java Hotspot

Java HotSpotTM虚拟机是Sun Microsystem公司的下一代虚拟机。虽然Java HotSpot 虚拟机所采用的规范与Java 2虚拟机所采用的规范相同,但它已被重新设计,并使用了最先进的技术,从而可在未来许多年内,能够为Java平台提供一个强大而可靠的性能引擎。Java HotSpot虚拟机可提供:
  • 可以探测并加速性能关键性代码的实时动态优化技术。
  • 为发挥线程的最大性能而设计的超快速线程同步。
  • 可最快速获取的精确而可靠的垃圾收集器。
  • 由于其简洁、高层次以及面向对象的设计,因而在可维护性和可扩展性方面的重要改进。

JIT(Just-In-Time)编译器

用来提高应用程序性能的最简单的工具是Just-In-Time(JIT)实时编译器。JIT是一个可将Java字节码转换为本地机器码的代码生成器。由JIT调用的Java程序,其运行速度通常要比由解释程序执行字节码时的速度高得多。

JIT编译器首先是在Java开发工具包(JDKTM)1.1.6中作为一种性能更新出现的,而现在它是你在Java 2平台上使用Java解释程序命令时调用的标准工具。你可以使用Java虚拟机的-Djava.compiler=NONE 选项来使JIT编译器失效,这在JIT的末尾部分有更详细的阐述。

JIT编译器是如何工作的?

JIT编译器是作为一种依赖于平台的本地库提供的。如果JIT编译器库存在,则Java虚拟机将初始化Java本地接口(JNI)的本地代码分支以调用在该库中可获得的JIT函数,而不是调用在解释程序中的相应函数。

java.lang.Compiler 类被用来加载本地库并启动JIT编译器内的初始化。当Java虚拟机调用一个Java方法时,它使用在加载的类对象的方法块中所指定的调用(invoker)方法。Java虚拟机具有若干个调用者方法,例如,如果方法是同步的,或者它是一个本地方法,则将使用不同的调用者。JIT编译器使用它自己的调用者。Sun的产品可以为值ACC_MACHINE_COMPILED检查方法存取位以告知解释程序该方法的代码已被编译并存储在加载类中。

代码何时成为JIT编译的代码?

当一个方法被首次调用时,JIT编译器为该方法将方法块编译为本地代码,并将其存储在该方法的代码块中。

一旦代码被编译完成,在Sun平台上所使用的ACC_MACHINE_COMPILED的位则被设定。

我如何知道JIT编译器在做什么?

环境变量JIT_ARGS允许对Sun Solaris JIT编译器进行简单控制。trace 和 exclude(list)是两个有用的值。要从示例InlineMe中排除(exclude)方法并显示跟踪记录(trace),应将JIT_ARGS 做如下设定:


Unix:

export JIT_ARGS="trace exclude(InlineMe.addCount InlineMe.method1)"



$ java InlineMe                                               

Initializing the JIT library ...

DYNAMICALLY COMPILING java/lang/System.getProperty mb=0x63e74

DYNAMICALLY COMPILING java/util/Properties.getProperty mb=0x6de74

DYNAMICALLY COMPILING java/util/Hashtable.get mb=0x714ec

DYNAMICALLY COMPILING java/lang/String.hashCode mb=0x44aec

DYNAMICALLY COMPILING java/lang/String.equals mb=0x447f8

DYNAMICALLY COMPILING java/lang/String.valueOf mb=0x454c4

DYNAMICALLY COMPILING java/lang/String.toString mb=0x451d0

DYNAMICALLY COMPILING java/lang/StringBuffer. mb=0x7d690

 >>>> Inlined java/lang/String.length (4)

请注意内联方法(如String.length)是免除的。String.length 也是一个特殊的方法,它一般由Java解释程序编译为一个内部快捷字节码。当使用JIT编译器时,由Java解释程序提供的这些优化失效,从而可以使JIT编译器能够理解哪个方法正在被调用。

如何使用JIT来发挥你的优势

首先要记住的一点是,JIT编译器在第二次调用一个方法时,会获得大部分速度上的改善。JIT编译器的确是编译了整个方法,而不是对其进行逐行解释,逐行解释也是一种在运行一个可执行JIT的应用程序时用以改善性能的途径。这意味着如果代码仅被调用一次,你将不会看到太大的性能改善。JIT编译器也将忽略构造函数(class constructor),所以,如果可能的话,应最少量地保留构造函数代码。

如果不能预先检查某些Java边界条件,JIT编译器也不能获得最大的性能改善,这些边界条件包括零指针(Null pointer)或边界外数组等异常。JIT编译器能够知道出现零指针异常的唯一途径是通过由操作系统所提供的信号。由于该信号来自操作系统,而不是来自Java虚拟机,因而你的程序会出现性能上的干扰。为了保证在用JIT运行一个应用程序时,能够获取最好的性能,应确保你的代码完全没有象零指针或边界外数组那样的异常。

如果你要以远程调试状态运行Java虚拟机,或者你要看到源代码行数而不是看到在你的Java栈跟踪中的标签(Compiled Code)的话,你可能需要使JIT编译器失效。要使JIT编译器失效,可在你调用解释器命令时为JIT编译器提供一个空白或无效名称。下面的例子演示了用javac命令将源代码编译为字节码、以及用两种形式的java命令在没有JIT编译器的情况下调用解释程序的过程。

  javac MyClass.java

  java -Djava.compiler=NONE MyClass

            or  

  javac MyClass.java

  java -Djava.compiler="" MyClass

第三方工具

其它一些可用的工具包括可用来减小一般Java类文件尺寸的工具。Java类文件包括一个被称作常数池(constant pool)的区域。常数池在某一个地方为类文件保持有一个字符串和其它信息的列表,以备引用。在常数池中可以获取的诸多信息之一是方法和字段的名称。

类文件引用在类中的一个字段作为对常数池中的一个条目的引用。这意味着只要引用保持相同,则无所谓在常数池中存储什么样的值。 一些工具利用这点将常数池中的字段名和方法名重写为缩短的名称。利用这一技术可以大大减小类文件的尺寸,从而使在网上下载类文件变得简单。 <淘宝热门商品:

小小豆叮

JAVA声音技术

声音可以创造意境,触发遐想,当与虚拟图像相结合时,更加可以让整个世界充满幻觉。声音是多媒体技术的基础。这就是Sun公司的JAVA媒体技术开发小组忙于准备Java Sound 1.0 API并将其包含于下一版本的JAVA开发工具库中的原因。

在JAVA2平台出现之前,JAVA语言只能处理电话音质的声音,以单声道8KHZ的采样频率存储为μ-law AU文件。JAVA2平台增加了对AIFF,WAV以及三种MIDI文件类型的支持。所支持的三种MIDI文件格式为MIDI文件类型0、MIDI文件类型1、以及RMF。

应用程序接口API1.0版提供了一个易于使用的工具集,使程序员可以访问底层的合成与演奏引擎,从而扩展了JAVA声音的应用。其中两个重要的领域是创建数字化音频以及乐器指令数字化接口MIDI。由于提供了大量的底层支持功能,所以程序员能输入输出声音,控制MIDI设备,并能查询系统运作情况。

声音文件类型简介

主要的声音文件类型如下:

AU - (扩展名为AU或SND)适用于短的声音文件,为Solaris和下一代机器的通用文件格式,也是JAVA平台的标准的音频格式。AU类型文件使用的三种典型音频格式为: 8位μ-law类型(通常采样频率为8kHz), 8位线性类型,以及16位线性类型。
WAV - (扩展名为WAV)由 Microsoft和 IBM共同开发,对WAV的支持已经被加进Windows 95并且被延伸到Windows 98. WAV文件能存储各种格式包括μ-law,a-law和 PCM (线性)数据。他们几乎能被所有支持声音的Windows应用程序播放。

AIFF - (扩展名为AIF或IEF)音频互换文件格式是为Macintosh计算机和Silicon Graphics (SGI)计算机所共用的标准音频文件格式。AIFF和 AIFF-C几乎是相同的,除了后者支持例如μ-law和 IMA ADPCM类型的压缩。

MIDI - (扩展名为MID)乐器数字接口MIDI是为音乐制造业所认可的标准,主要用于控制诸如合成器和声卡之类的设备。

MIDI文件不包含数字音频采样,而是包括一系列指令,这些指令控制把来自不同乐器上的音符序列合成乐曲。一些MIDI文件包含附加指令来为各种合成设置进行编程。

大多数合成器支持MIDI标准,所以在一个合成器上制作的音乐能够在另一个上播放。 有 MIDI接口的计算机能操纵 MIDI数据以产生新音乐或音响效果。例如,一个完整的音乐作品可以通过一个软件驱动的命令转换成全新的形式。

JAVA声音引擎支持两种MIDI文件类型:

MIDI类型0文件-包含仅仅一个序列,所有相关的乐器部分被包含在同一个逻辑 "磁道"上。

MIDI类型1文件-包含多重的 "磁道"使得不同的乐器被逻辑地分开,从而使对声音的操作和重组更加容易。

RMF - (扩展名为RMF)混合音乐格式是由Beatnik设计出来的混合文件类型,通过交互式设定将MIDI和音频采样封装在一起。RMF好比是一个所有音乐相关文件的容器。RMF也包含对有关版权的详细文件说明的支持。RMF文件可以包含多个由不同艺术家创作的存储为MIDI类型或音频采样类型的作品,每个都关联着相关的版权信息。

对声音引擎的选择

在1997年,SUN的JAVA媒体开发组试图找到一种方法,以增强声音的处理能力并为将来提供一个坚实的平台。根据JAVA媒体开发组经理Michael Bundschuh所说,
"我们想要非常高质量的播放引擎以处理所有的从八位μ-law级直到 CD质量声音的每一件操作。 我们希望轻松跨越所有平台,诸如Solaris平台, Windows, Mac以及其他。我们也想要高度发展了的能够跨越不同平台的MIDI能力。为上述目的,合理的选择是Beatnik的音频引擎(从前是Headspace。)"
SUN取得了Beatnik的音频引擎使用许可,把它当作JAVA声音应用程序接口API的基础。

Thomas Dolby Robertson-Beatnik简介

在90年代初之前,Thomas Dolby Robertson的职业完全在音乐方面。他1982推出的"她用科学照亮了我"是一部早期的MTV巨作。整个80年代,他都在不断地作曲和录音,使用一种非结构化音乐制作软件。但是在 1990,通过一次为Guggenheim博物馆演示虚拟现实的合作,他开始思考能否做一些提高音乐制作能力的工作。

"我当时正伏在 C程序员的肩上,并且我突然认识到为做记录做了大量的工作,可是没有为演奏时的交互做任何事情。"有了这样的想法,Robertson在1992年建立了Headspace,雇用月光作曲组来帮助实现他的观点。Headspace于1996年成为公司,现在被称为Beatnik。

JAVA声音音频引擎

JAVA声音引擎为多媒体创建,同时考虑了游戏设计和发布WEB内容。用标准的 MIDI文件、RMF文件、并且/或来自任何源的采样,该引擎将播放音乐或制造音响效果,同时尽可能少用CPU。它提供完全的播放控制,具有混合音响的能力并可实时地回应用户的输入。

JAVA声音引擎是软件 MIDI合成器,采样播放设备,以及16位立体混声器。它支持混合直到64位的立体MIDI声音和音频采样。它直接支持MIDI类型0和类型1文件以及从8位设备到16位乐器的波表合成。该引擎支持所有通用的 MIDI控制器并且包含象回声处理, LFO (控制过滤器或立体声设备)之类的特性,以及ADSR信封 (播放时整形采样)。

即使用上所有的功能,JAVA声音引擎在一个90Mhz的奔腾计算机上也占用不超过30%的CPU时间。它还能通过有选择地禁用不需要的特性,使其变得更加高效一些。另外,它发布了存储在压缩的RMF音乐文件中的丰富的内容。Thomas Dolby Robertson的"她用科学照亮了我",一首7分21秒的歌曲,如存储为CD音质的文件足足占用70M字节空间。如果以RMF格式存储只需大约636 KB,是120:1的减少,同时丝毫不减音质。
为更多有关Beatnik的信息,请看Beatnik的WEB站点。

JAVA平台声音的简要历史

在JDK 1.0.x及JDK 1.1.x下, AudioClip接口提供下列机能:

l AudioClip接口

播放
循环
停止

恢复和播放声音最简单的方法是通过Applet类的play()方法。调用play()方法有如下二种方式:

play()-带有一个参数,一个 URL对象,装载并演奏储存在 URL处的声音片断。

play()-带有二个参数,基本 URL和文件夹路径名,装载并演奏声音文件。第一参数经常是对getCodeBase()或 getDocumentBase()的调用。

下列代码片断举例说明了直接播放 hello.au的方法。AU文件与小应用程序位于相同文件夹或目录。

play(getCodeBase(), "hello.au");

play()一旦被调用立刻开始恢复和播放声音。如果声音文件不能被查找,将不会有出错信息,仅仅是沉默。
启动和停止声音文件,或循环播放,你必须用 applet的 getAudioClip方法把它装载进入 AudioClip对象,类似上面play()方法的参数,getAudioClip方法要用一个或两个参数,当作播放的指示。 第一个或唯一的一个参数是 URL参数,用来指示声音文件的位置,第二参数是文件夹路径指针。

下列代码行举例说明加载声音文件进入剪贴对象:

AudioClip co = getAudioClip(getCodeBase(), "horns.wav");

getAudioClip()方法仅仅能被applet内调用。随着JAVA2的引入,应用程序也能用Applet类的newAudioClip方法装入声音文件。前一例子可以改写如下以用于Java应用程序:

AudioClip co = newAudioClip("horns.wav");

在你已创建 AudioClip对象之后,你能用该对象调用play()、loop()以及stop()方法。如果 getAudioClip或 newAudioClip方法不能找到指定的声音文件, AudioClip对象的值将是空的。试着播放空对象会导致出错,所以标准的过程首先是对该条件进行检测。
接下来是一个完整的程序设计示例,该程序将产生一个applet,当鼠标在该小应用程序applet范围内按下时会播放 flute+hrn+mrmba.au音乐样本。此AU示例文件与applet在相同目录或文件夹下的。

import java.applet.*;
import java.awt.event.*;

public class PlayAudio extends Applet
implements MouseListener {
AudioClip audio;

public void init() {
audio = getAudioClip(getDocumentBase(),
"flute+hrn+mrmba.au");
addMouseListener(this);
}

public void mousePressed(MouseEvent evt) {
if (audio != null) audio.play();
}

public void mouseEntered (MouseEvent me) {
}

public void mouseExited (MouseEvent me) {
}

public void mouseClicked (MouseEvent me) {
}

public void mouseReleased(MouseEvent me) {
}

}

注意: 在许多JAVA2技术书籍中,mouseDown()方法确实是JAVA 1.0事件模型的一部分。使用该方法会有一定的危险,因为该方法在将来可能不会被支持。在JAVA2平台下将MouseListener与mousePressed结合使用是优先的选择。

API 1.0-质的飞跃

注意:下列备注是以JAVA API的早期版本0.86为基础的。虽然目前这里讨论的大多数对象和概念与过去保持一致,但由于该API版本已经终止,出现某些改变的可能是存在的。

JAVA声音 1.0 API为JAVA平台定义了一整套的基本的底层音频处理功能。它提供如下接口为:

<淘宝热门商品:

小小豆叮

Oracle提供新一代应用开发工具Oracle9i JDeveloper

为了更好地方便开发者利用最先进的Internet技术,近日Oracle公司宣布推出新一代应用开发工具Oracle9i JDeveloper,它充分利用了Oracle9i 应用服务器(Oracle9iAS)和Oracle9i数据库(Oracle9iDB)的优势,具有多种以往不具备的全新特性。目前Oracle已经开始在Oracle技术网(OTN)实施的“早期采用者计划(EAP)”提供Oracle9i JDeveloper,1700万OTN成员可以立即利用Oracle9i JDeveloper开发J2EE和XML的应用以及Web服务。 越来越多的公司正在采用J2EE标准,Gartner资深研究人员Mark Driver认为:“随着用户需求的不断增加,电子商务应用变得越来越复杂,而能够使各种应用完全互操作的J2EE是开发者有效战胜这些挑战的有力工具。” Oracle9i Jdeveloper完全利用Java编写,能够与以前的Oracle服务器软件以及其他厂商支持J2EE的应用服务器产品相兼容,而且在设计时着重针对Oracle9i,能够无缝化跨平台之间的应用开发,提供了业界第一个完整的、集成了J2EE和XML的开发环境,允许开发者快速开发可以通过Web、无线设备及语音界面访问的Web服务和交易应用,以往只能通过将传统Java编程技巧与最新模块化方式结合到一个单一集成的开发环境中之后才能完成J2EE应用开发生命周期管理的事实,从根本上得到改变。 Oracle9i JDeveloper具有多种首次推出的特性,包括: 单一的集成开发环境支持整个应用开发生命周期 Oracle9i JDeveloper引进了统一模块化语言(Unified Modeling Language,UML),无论哪个环节发生变化,Java和XML开发人员可以利用UML在代码、模块和向导之间进行同步的电子商务应用处理。Oracle9i JDeveloper包含了集成的性能和存储分析工具,可以追踪性能问题、存储漏洞和死机情况。同时,它还具有支持团队开发的功能,使企业能够管理由多个开发者联合开发的、具有多个子项目的复杂应用。 简单、快速的J2EE开发与部署 Oracle9i JDeveloper支持最新的J2EE标准,利用了Oracle Business Components for Java,后者是一个100%端到端的J2EE和XML架构,从而能够大幅度简化J2EE应用开发的过程,使开发者无需在修改代码等繁杂的工作中耽误工夫。利用Oracle成熟的SQL和XML数据源对象关系映象技术,新工具能够对传统的J2EE应用进行优化,同时,通过充分利用Oracle9iAS新的J2EE功能,新工具集允许Oracle9i应用开发人员使用“向导”,更容易地部署、测试和调试应用。 集成的Java、XML和SQL开发 为了使开发者能够方便地创建下一代J2EE应用和Web服务,Oracle9i JDeveloper提供了唯一集成了Java、XML和SQL的开发环境,利用Oracle9i JDeveloper内置的XML计划编辑器,Java和XML开发者能够利用WWW联盟(W3C)最新定义的内容来创建基于XML的Internet应用,在这个环境中,开发者能够使用Java类、EJB、Oracle Business Components for Java以及PL/SQL等多种工具来高效率创建新一代J2EE应用和Web服务。 <淘宝热门商品:

小小豆叮

SQL Server 2000 JDBC驱动程序

SQL Server 2000 JDBC Driver是最好的 Type 4 JDBC驱动程序,它提供了面向企业的、与Java环境的高度可靠、高度可伸缩的连通性。SQL Server 2000 JDBC Driver为所有Java小程序(Java-enabled Applet)、应用程序或者应用程序服务器提供了JDBC访问能力。它跨越Internet和Intranet提供了对SQL Server 2000的高性能点对点访问和n层(n-tier)访问。该驱动程序针对Java环境进行了优化,使您可以将Java技术与现有的系统相结合,以扩展现有系统的功能和性能。

SQL Server 2000 JDBC Driver是一个遵从JDBC 2.0规范的驱动程序。它还支持JDBC 2.0 Optional Package的一个子集,该子集提供了以下一些功能(详细信息参见文档):

  • Java命名目录接口(JNDI),用于命名数据源
  • 连接池(Connection Pooling)

SQL Server 2000 JDBC Driver 支持的SQL Server版本有:

  • SQL Server 2000.
  • SQL Server 2000 with Service Pack 1

以下操作系统支持SQL Server 2000 JDBC Driver:

  • Windows XP
  • Windows 2000 with Service Pack 2
  • AIX
  • HP-UX
  • Solaris
  • Linux

SQL Server 2000 JDBC Driver支持以下版本的JDK:

  • JDK 1.1.8
  • JDK 1.2
  • JDK 1.3

您可以使用新闻组对该产品进行端到端的讨论、报告程序错误或者询问其它任何相关问题。该产品当前处于beta测试过程,而且只通过新闻组进行技术支持。

安装指导

  • 点击链接将Setup.exe(针对基于Microsoft Windows的系统)或Mssqlserver.tar(针对基于UNIX的系统)下载到您的计算机上。
  • 点击链接将Install.txt文件下载到您的计算机上。
  • 遵照Install.txt文件中的指令进行以后的操作。

Download FileSetup.exe
6.9 MB 可执行文件
33 分钟 @ 28.8 Kbps

Download FileMssqlserver.tar
5.9 MB 可执行文件
29 分钟 @ 28.8 Kbps

Download FileInstall.txt
1 KB 文本文件
<1 min @ 28.8 Kbps

<淘宝热门商品:

小小豆叮

Oracle 最新发布的 R 3 版本功能特色

Oracle8i 是世界上最为主流的电子商务数据库。最新发布的 R 3 版本具有如下的功能特色:

  • 新增 Java 服务
  • 功能强大的新安全特性
  • 增强型 XML 支持
  • 支持 HTTP PL/SQL网关
  • Apache支持的Oracle HTTP Listener

Oracle8i 企业版数据库的下列功能项,使 Oracle 数据库在安全数据管理、事务处理以及数据仓储方面更加强大:

新增 Java 服务

能够在 Oracle8i R 3 Oracle Internet Application Server 9i之间提供普通的 Java 服务。用 Oracle8i JVMJava 虚拟机,前身为Oracle JServer),可以在数据库和应用服务器层更加容易地进行配置,并大大提高了性能。 Oracle8i JVM 在不同服务器层提供完全一致、高度可扩展的 Java 虚拟机功能。版本中包括:

  • Entity Beans (EJB 1.1) 用来支持实现 Enterprise Java Beans
  • Java Servlets 以及 Java Server Pages 是本年度 Oracle iDevelop Conference  的热门话题。 Java Servlets 以及 Java Server Pages (JSP) 正以迅雷不及掩耳之势,成为 企业门户 Web 站点开发的关键技术解决方案。
  • Java 2 Enterprise Edition APIs ——这一版本中包括的应用编程接口有: JMSJava 消息服务),JTAJava 事务 API),JDBC 等等。
  • Oracle8i JVM Accelerator —— Oracle8i JVM Accelerator 提供了本地编译 Java 代码功能,大大提升了Java 的性能。

功能强大的新安全特性

Oracle8i R 3 中新增的安全特性包括:

  • HTTP 上支持 SSL 连接到数据库,确保强大的网络认证、数据保密及完整性。
  • 对瘦 JDBC 的强大加密功能 连接到数据库,确保网络数据保密及完整性。
  • 3 DES 加密功能 对数据库中的数据而言。确保数据库中某一特定的内容安全,即使是超级用户或 DBA 也不能对其访问。
  • Entrust PKI 进行集成 实现了在 Oracle 环境下安全管理 X.509 数字证书。

增强型 XML 支持

XML SQL 实用工具

Oracle XML SQL 实用工具,实现了用原始格式读写 XML 文档,与数据库进行交互。

增强型 XML 开发工具包 (XDK)

支持 JavaJava BeansCC++ PL/SQL XML 开发工具包已被集成到了 Oracle Internet Developer Suite XDK 包括:

  • XML ParserXML 解析器),实现对 XML 文档的程序访问。
  • XML ProcessorXML 处理器),可以将任何格式的 XML 文档转换成其它 XML 文档或基于文本格式的文档(如 HTML)。
  • XML Class GeneratorXML 类生成器),可以生成类文件,以创建 XML 文档,便于应用程序、Applet JavaServer Pages 使用。
  • XML Java Beans,增加了可视性与非可视性 XML 功能特性,其中包括查看、解析和转换 XML 文档。
  • XSQL Servlets,可以由互联网上的 SQL 查询语句生成动态 XML 文档或 HTML 文档。

支持 HTTP PL/SQL 网关

由于采用了嵌入式 PL/SQL 网关,Oracle8i R 3 提供本机的、现成的支持,以便于在互联网上配置基于 PL/SQL 的应用程序。而对 PL/SQL  过程可以直接进行 HTTP调用,有助于优化利用您现有的应用程序,同时可以节省开发费用。

 

Apache 支持的 Oracle HTTP Listener

Apache 支持的 Oracle HTTP 服务器是目前的缺省 HTTP Listener,服务于静态 HTML 和来自数据库的无状态 Servlets。无需应用服务器或外部 ListenerOracle8i R 3 就可以直接收到 HTTP 调用。而广泛使用的 Apache Listener 可以保证兼容所有的 Oracle8i 平台。 <淘宝热门商品:

小小豆叮