Category: Windows操作系统

2009-01-06

获取运行中的JVM系统属性

归类于: Windows操作系统 - 06 Jan 2009

  获取你的JVM系统环境属性

  Java的”Writer once,run anywhere”口号的确让我们领略到了Java的神奇,也成为SUN宣传Java的金字招牌。拂开这层神秘的面纱,我们不难发现其核心是运行在各种操作系统中的JVM(Java虚拟机)在发挥着重要的作用,Java虚拟机允许我们的纯java类可以达到”一次编写,到处运行”。每个安装在不同操作系统的Java虚拟机负责着Java程序与操作系统之间的工作,因此每个Java虚拟机的系统环境属性是不同的,我们可以通过访问Java虚拟机的系统属性来获知一些关于当前操作系统的一些基本信息,这些信息的价值有时是非常重要的。

  标准SDK中提供了java.lang.System类,这个类定义了一个对系统设备(包括系统属性和系统输入输出数据流)的、与平台无关的接口。方法getProperties()返回一个java.util.Property对象,对象中存放了JVM的系统属性列表,我们可以通过这个列表来得到java虚拟机的一些系统属性。

  下面的例子中,将介绍如何实现获取JVM系统属性的功能

  类设计

  设计SystemInfo类,用来获取系统的属性,并打印输出到标准输出。首先我们将设计一个getSystemProperty()方法,该方法将调用java.lang.System.getProperties()返回一个系统属性列表,在main()函数中,将系统属性的关键字和属性描述放到一个Hashtable结构中,通过遍历这个结构,获取系统属性值。类结构图如下:

  

  

  //package com.cn-java;

  import java.lang.System;

  import java.util.Properties;

  import java.util.Hashtable;

  import java.util.Enumeration;

  public class SystemInfo{

  //存放JVM获得的系统属性

  static private Properties _property;

  //Main function

  public static void main(String[] args){

  getSystemProperty();

  Hashtable hashKey;

  hashKey=new Hashtable();

  //将系统信息的关键字和标题放到hashtable

  hashKey.put(”java.home”,

  ”Java安装目录

  ”);

  hashKey.put(”java.class.path”,

  ”装载类的路径

  ”);

  hashKey.put(”java.specification.version”,

  ”Java API 规范的版本

  ”);

  hashKey.put(”java.specification.vendor”,

  ”Java API 规范的厂商

  ”);

  hashKey.put(”java.specification.name”,

  ”Java API 规范的名称

  ”);

  hashKey.put(”java.version”,

  ”Java API 实现的版本

  ”);

  hashKey.put(”java.vendor”,

  ”Java API 实现的厂商

  ”);

  hashKey.put(”java.vendor.url”,

  ”Java API 规范厂商的URL”);

  hashKey.put(”java.vm.specification.version”,

  ”Java虚拟机规范的版本

  ”);

  hashKey.put(”java.vm.specification.vendor”,

  ”Java虚拟机规范的厂商

  ”);

  hashKey.put(”java.vm.specification.name”,

  ”Java虚拟机规范的名称

  ”);

  hashKey.put(”java.vm.version”,

  ”Java虚拟机实现的版本

  ”);

  hashKey.put(”java.vm.vendor”,

  ”Java虚拟机实现的厂商

  ”);

  hashKey.put(”java.vm.name”,

  ”Java虚拟机实现的名称

  ”);

  hashKey.put(”java.class.version”,

  ”Java类文件格式的版本

  ”);

  hashKey.put(”os.name”,

  ”主机操作系统的名称

  ”);

  hashKey.put(”os.arch”,

  ”主机操作系统的体系结构”);

  hashKey.put(”os.version”,

  ”主机操作系统的版本

  ”);

  hashKey.put(”file.separator”,

  ”平台目录的分隔符

  ”);

  hashKey.put(”path.separator”,

  ”平台路径的分隔符

  ”);

  hashKey.put(”line.separator”,

  ”平台文本行的分隔符

  ”);

  hashKey.put(”user.name”,

  ”当前用户的帐户名称

  ”);

  hashKey.put(”user.home”,

  ”当前用户的根目录

  ”);

  hashKey.put(”user.dir”,

  ”当前工作目录

  ”);

  Enumeration enum;

  String propertyKey;

  enum=hashKey.keys();

  while(enum.hasMoreElements()){

  propertyKey=(String)enum.nextElement();

  System.out.println((String)hashKey.get(propertyKey)

   “:” _property.getProperty(propertyKey));

  }

  }

  /**

  * 获得系统属性列表

  * @return Properties

  */

  static …

JavaThreadinJVM

归类于: Windows操作系统 - 06 Jan 2009

  本文从JVM的角度探讨Java Thread的语法和编译结果。如果需要获得第一手资料,请直接访问以下的资源――Java语言规范,Java虚拟机规范中有关线程的定义说明。

  本文旨在介绍这些比较重要的线程相关的规范,基本上不另作发挥。(除了提到微软的“公共语言基础构造”。:-)

  Java Language Specification

  http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#30531

  JVM Specification

  http://java.sun.com/docs/books/vmspec/2nd-edition/html/Compiling.doc.html#6530

  http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc9.html

  http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html

  Microsoft CLI — Common Language Infrastructure (sorry, off the topic :-)

  http://msdn.microsoft.com/net/ecma/

  1.synchronized method 的java语言规范

  详见http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#30531。

  用synchronized关键字修饰的方法,分为两种情况:(static)静态方法,和实例方法。

  (static)静态方法的“锁”是这个拥有这个方法的对象的Class对象;实例方法的“锁”是this,拥有这个方法的当前对象实例。

  怎么理解这段话,看一看下面的例子就明白了。

  下面两段代码的效果完全相同。代码1 ==代码2。

  代码1:

  class Test {

  int count;

  synchronized void bump() { count ; }

  static int classCount;

  static synchronized void classBump() {

  classCount ;

  }

  }

  代码2:

  class BumpTest {

  int count;

  void bump() …

Linux平台的JVM性能评测

归类于: Windows操作系统 - 06 Jan 2009

  在Linux平台上,Sun的Hotspot性能很一般,不如同样环境下Windows下的Hotspot表现好;

  IBM的JVM无论在Linux还是Windows平台性能很卓越,不过IBM主要还是把精力放在Linux/Unix平台上,它的Windows平台的JVM到1.3.1性能口碑很好,但是以后就没有再单独发布新版本,因此从IBM网站也只能下载到Windows下1.3.1版本JVM,至于Linux平台下的1.4.1版本的JVM性能表现尚待检验;

  而BEA的JRockit针对Intel 的CPU进行了指令优化,作为服务器的JVM来说在业界似乎一向评价颇好,但是我还不清楚JRockit在Linux上表现如何。这次我是要在SuSE Linux上跑jroller,因此主要关注3个JVM在我的SuSE 9上面的性能表现。

  因为要作为网站服务器来使用,因此我还比较关注JRockit和IBM JVM的License问题,分别查了一下BEA和IBM的协议,看到这两个JVM都是可以免费使用,不管是开发目的,还是产品目的,如果是购买了其公司其他产品,那么可以得到免费的JVM方面的support,如果只是从网站下载使用其JVM,那么就没有免费的support,但是有商业付费的support。

  在TSS上面有一个关于JRockit的Thread:

  http://www.theserverside.com/news/thread.tss?thread_id=22895

  Cameron Purdy对于3个JVM的评价如下:

  引用:

  Every application is different, so there is no single “best JVM.” These JVMs only compete on the x86 platform anyway, and they perform differently on Windows and Linux. The IBM JVM has been much faster …

JVM的垃圾回收机制详解和性能调优

归类于: Windows操作系统 - 06 Jan 2009

  1.JVM的gc概述

  gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。

  在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能。有些垃圾收集专用于特殊的应用程序。比如,实时应用程序主要是为了避免垃圾收集中断,而大多数OLTP应用程序则注重整体效率。理解了应用程序的工作负荷和jvm支持的垃圾收集算法,便可以进行优化配置垃圾收集器。

  垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。

  1.1.引用计数

  引用计数存储对特定对象的所有引用数,也就是说,当应用程序创建引用以及引用超出范围时,jvm必须适当增减引用数。当某对象的引用数为0时,便可以进行垃圾收集。

  1.2.对象引用遍历

  早期的jvm使用引用计数,现在大多数jvm采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

  下一步,gc要删除不可到达的对象。删除时,有些gc只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多gc可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。

  为此,gc需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止,只有gc运行。结果,在响应期间增减了许多混杂请求。另外,更复杂的gc不断增加或同时运行以减少或者清除应用程序的中断。有的gc使用单线程完成这项工作,有的则采用多线程以增加效率。

  2.几种垃圾回收机制

  2.1.标记-清除收集器

  这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。

  2.2.标记-压缩收集器

  有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。

  2.3.复制收集器

  这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,jvm生成的新对象则放在另一半空间中。gc运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。

  2.4.增量收集器

  增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。

  2.5.分代收集器

  这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。

  2.6.并发收集器

  并发收集器与应用程序同时运行。这些收集器在某点上(比如压缩时)一般都不得不停止其他操作以完成特定的任务,但是因为其他应用程序可进行其他的后台操作,所以中断其他处理的实际时间大大降低。

  2.7.并行收集器

  并行收集器使用某种传统的算法并使用多线程并行的执行它们的工作。在多cpu机器上使用多线程技术可以显著的提高java应用程序的可扩展性。

  3.Sun HotSpot 1.4.1 JVM堆大小的调整

  Sun HotSpot 1.4.1使用分代收集器,它把堆分为三个主要的域:新域、旧域以及永久域。Jvm生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后,便获得使用期并进入旧域。在永久域中jvm则存储class和method对象。就配置而言,永久域是一个独立域并且不认为是堆的一部分。

  下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。

  下面的命令是把初始大小设置为128M:

  java ?Xms128m

  ?Xmx256m为控制新域的大小,可使用-XX:NewRatio设置新域在堆中所占的比例。

  下面的命令把整个堆设置成128m,新域比率设置成3,即新域与旧域比例为1:3,新域为堆的1/4或32M:

  java ?Xms128m ?Xmx128m

  ?XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。

  下面的命令把新域的初始值和最大值设置成64m:

  java ?Xms256m ?Xmx256m ?Xmn64m

  永久域默认大小为4m。运行程序时,jvm会调整永久域的大小以满足需要。每次调整时,jvm会对堆进行一次完全的垃圾收集。

  使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时,经常需要增加永久域的最大值。当jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小。为了避免调整,可使用-XX:PerSize标志设置初始值。

  下面把永久域初始值设置成32m,最大值设置成64m。

  java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m

  默认状态下,HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden,用于生成新的对象。另两部分称为救助空间,当Eden充满时,收集器停止应用程序,把所有可到达对象复制到当前的from救助空间,一旦当前的from救助空间充满,收集器则把可到达对象复制到当前的to救助空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制,直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可控制新域子空间的大小。

  同NewRation一样,SurvivorRation规定某救助域与Eden空间的比值。比如,以下命令把新域设置成64m,Eden占32m,每个救助域各占16m:

  java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2

  如前所述,默认状态下HotSpot对新域使用复制收集器,对旧域使用标记-清除-压缩收集器。在新域中使用复制收集器有很多意义,因为应用程序生成的大部分对象是短寿命的。理想状态下,所有过渡对象在移出Eden空间时将被收集。如果能够这样的话,并且移出Eden空间的对象是长寿命的,那么理论上可以立即把它们移进旧域,避免在救助空间反复复制。但是,应用程序不能适合这种理想状态,因为它们有一小部分中长寿命的对象。最好是保持这些中长寿命的对象并放在新域中,因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制,可用-XX:TargetSurvivorRatio控制救助空间的比例(该值是设置救助空间的使用比例。如救助空间位1M,该值50表示可用500K)。该值是一个百分比,默认值是50。当较大的堆栈使用较低的sruvivorratio时,应增加该值到80至90,以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。

  为放置所有的复制全部发生以及希望对象从eden扩展到旧域,可以把MaxTenuring Threshold设置成0。设置完成后,实际上就不再使用救助空间了,因此应把SurvivorRatio设成最大值以最大化Eden空间,设置如下:

  java … -XX:MaxTenuringThreshold=0 ?XX:SurvivorRatio=50000 …

  4.BEA …

Java网络编程之传输控制协议(二)

归类于: Windows操作系统 - 06 Jan 2009

  四、Socket类

  Socket类表现了客户端套接字,它是属于一台或两台计算机的两个TCP通讯端口之间的通讯通道。端口可以连接到本地系统的另一个端口,这样可以避免使用另一台计算机,但是大多数网络软件将使用两台计算机。但是TCP套接字不能与两台以上的计算机通讯。如果需要这种功能,客户端应用程序必须建立多个套接字连接,每台计算机一个套接字。

  构造函数

  java.net.Socket类有几个构造函数。其中两个构造函数允许使用布尔型参数指定是否使用UDP或TCP套接字,我们不赞成使用它们。这儿没有使用这两个构造函数,并且没有列举在此处–如果需要UDP功能,请使用DatagramSocket。

  try

  {

  // 连接到指定的主机和端口

  Socket mySocket = new Socket ( “www.awl.com”, 80);

  // ……

  }

  catch (Exception e)

  {

  System.err.println (”Err - ” e);

  }

  但是还有很多构造函数可以用于不同的情形。除非特别指出,所有的构造函数都是公共的。

  ? protected Socket ()-使用当前套接字产生组件提供的默认实现建立不连接的套接字。开发者一般不应该使用这个方法,因为它不允许指定主机名称和端口。

  ? Socket (InetAddress address, int port)产生 java.io.IOException异常。

  ? java.lang.SecurityException-建立连接到指定的IP地址和端口的套接字。如果不能建立连接,或连接到主机违反了安全性约束条件(例如某个小的服务程序试图连接到某台计算机而不是载入它的计算机时),就产生这种异常。

  ? Socket (InetAddress address, int port, InetAddress localAddress, int localPort)产生java.io.IOException、java.lang.SecurityException异常-建立连接到指定的地址和端口的套接字,并把它绑定到特定的本地地址和本地端口。默认情况下,使用一个自由(空)的端口,但是在多地址主机环境(例如本地主机有两个或多个的计算机)中,该方法也允许你指定一个特定的端口号、地址。

  ? protected Socket (SocketImpl …

新基准下,微软.NET依旧胜出

归类于: Windows操作系统 - 06 Jan 2009

  关于微软公司的.NET应用解决方案和SUN公司的Java解决方案(J2EE)之间的对抗,一直以来都表现的比较尖锐。尤其自去年的PDC大会以来,微软的.NET和SUN公司的JAVA Pet Store的比较而不断地引发出很大的争论。于此之下,2002年10月28日,J2EE主要在线社区TheServerSide.Com网站发表了题为《J2EE和.NET应用服务器及网络服务基准》的报告,发布了一套新的基准,并申明要使用新基准再次进行微软.NET和SUN公司的J2EE之间的比较,比较内容集中在Web服务、分布式计算的执行及可靠性测试。测试的结果出人意料,两位软件巨人在这一次对话中,呈现出了一边倒的局势:微软全线胜出!在新基准的测试中,微软.NET的各项性能指标都远远超过了SUN公司的J2EE。

  这套新基准是由Middleware公司发布的,内容包括:网络应用基准、分布式计算基准和Web服务基准。有趣的是,测试的最终报告同样来自Middleware公司,而它正是J2EE长期以来的坚定支持者,并且还是TheServerSide.com网站的缔造者。因此,这份报告的权威性和客观性不容置疑。在这报告中,Middleware公司的J2EE开发人员针对微软.NET与SUN公司的J2EE的运行效果和可升级性的比较进行了详细的介绍,这些开发人员建立了一套完全优化的、基于EJB的应用程序,然后在新基准的基础平台之上,把这套应用程序与微软相对应的、用C#开发语言在.NET框架下开发的改进后的应用程序进行了比较。报告显示,经过各种测试,微软.NET在速度上明显比SUN公司的J2EE要快,而且升级性能更好。例如,在Windows.NET Server 2003 系统下,参照新的网络应用基准上,NET 1.1的整体功能要比J2EE 强 339%。

  Middleware公司有10多年的Java综合开发和咨询经验,一向支持J2EE。该公司人员在充分研究了众多对.NET 和Java Pet Store做过比较的JAVA开发人员的回馈意见,并对最近几个月TheServerSide.Com网站上被热烈讨论的应用基准进行了深入的分析。在此基础上,该公司还对J2EE在企业网络应用方面进行了全面的优化,以增加J2EE的应用效果和可升级性。另外,他们还为J2EE增加了基于EJBs/JTA的分配处理功能以及基于SOAP的网络服务功能。当然,与此同时,微软也在升级其.NET产品,最新的.NET 2.0也有强大的分配处理和网络服务功能,可以在MSDN上应用,并能为建立.NET企业应用解决方案提供优秀的设计模式。

  事后,Middleware公司在TheServerSide.com网站上公布了这次检测的结果、相关技术文档、代码以及测试脚本,供用户参考和下载。由于此次关于微软.NET和SUN公司的J2EE在同一新基准下的对比测试都是在Middleware公司的J2EE开发人员的指导下完成的,而且结果得到他们的认证,因此这篇报告就更具有了非同寻常的意义。

  

Java软件架构设计慨论

归类于: Windows操作系统 - 06 Jan 2009

  开始之初的架构设计决定着软件产品的生死存亡。“好的开始相当于成功一半”。

  开始的架构设计也是最难的,需要调研同类产品的情况以及技术特征,了解当前世界上对这种产品所能提供的理论支持和技术平台支持。再结合自己项目的特点(需要透彻的系统分析),才能逐步形成自己项目的架构蓝图。

  比如要开发网站引擎系统,就从Yahoo的个人主页生成工具 到虚拟主机商提供的网站自动生成系统,以及IBM Webphere Portal的特点和局限 从而从架构设计角度定立自己产品的位置。

  好的设计肯定需要经过反复修改,从简单到复杂的循环测试是保证设计正确的一个好办法

  由于在开始选择了正确的方向,后来项目的实现过程也验证了这种选择,但在一些架构设计的细部方面,还需要对方案进行修改,属于那种螺旋上升的方式,显然这是通过测试第一的思想和XP工程方法来实现的。

  如果我们开始的架构设计在技术平台定位具有一定的世界先进水平,那么,项目开发实际有一半相当于做实验,是研发,存在相当的技术风险。

  因此,一开始我们不可能将每个需求都实现,而是采取一种简单完成架构流程的办法,使用最简单的需求将整个架构都简单的完成一遍(加入人工干预),以检验各个技术环节是否能协调配合工作(非常优秀先进的两种技术有时无法在一起工作),同时也可以探知技术的深浅,掌握项目中的技术难易点。这个过程完成后,我们就对设计方案做出上面的重大修改,丰富完善了设计方案。

  设计模式是支撑架构的重要组件

  架构设计也类似一种工作流,它是动态的,这点不象建筑设计那样,一开始就能完全确定,架构设计伴随着整个项目的进行过程之中,有两种具体操作保证架构设计的正确完成,那就是设计模式(静态)和工程项目方法(RUP或XP 动态的)。

  设计模式是支撑架构的一种重要组件,这与建筑有很相象的地方,一个建筑物建立设计需要建筑架构设计,在具体施工中,有很多建筑方面的规则和模式。

  我们从J2EE蓝图模式分类http://java.sun.com/blueprints/patterns/catalog.html中就可以很清楚的看到J2EE这样一个框架软件的架构与设计模式的关系。

  架构设计是骨架,设计模式就是肉

  这样,一个比较丰富的设计方案可以交由程序员进一步完成了,载辅助以适当的工程方法,这样就可保证项目的架构设计能正确快速的完成。

  时刻牢记架构设计的目标

  由于架构设计是在动态中完成的,因此在把握架构设计的目标上就很重要,因此在整个项目过程中,甚至每一步我们都必须牢记我们架构设计的总体目标,可以概括下面几点:

  1. 最大化的重用:这个重用包括组件重用 和设计模式使用等多个方面。

  比如,我们项目中有用户注册和用户权限系统验证,这其实是个通用课题,每个项目只是有其内容和一些细微的差别,如果我们之前有这方面成功研发经验,可以直接重用,如果没有,那么我们就要进行这个子项目的研发,在研发过程中,不能仅仅看到这个项目的需求,也要以架构的概念去完成这个可以称为组件的子项目。

  2. 尽可能的简单明了:我们解决问题的总方向是将复杂问题简单化,其实这也是中间件或多层体系技术的根本目标。但是在具体实施设计过程中,我们可能会将简单问题复杂化,特别是设计模式的运用上很容易范这个错误,因此如何尽可能的做到设计的简单明了是不容易的。

  我认为落实到每个类的具体实现上要真正能体现系统事物的本质特征,因为事物的本质特征只有一个,你的代码越接近它,表示你的设计就是简单明了,越简单明了,你的系统就越可靠。更多情况是,一个类并不能反应事物本质,需要多个类的组合协调,那么能够正确使用合适的设计模式就称为重中之重。

  我们看一个具备好的架构设计的系统代码时,基本看到的都是设计模式,宠物店(pet store)就是这样的例子。或者可以这样说,一个好的架构设计基本是由简单明了的多个设计模式完成的。

  3. 最灵活的拓展性:架构设计要具备灵活性 拓展性,这样,用户可以在你的架构上进行二次开发或更加具体的开发。

  要具备灵活的拓展性,就要站在理论的高度去进行架构设计,比如现在工作流概念逐步流行,因为我们具体很多实践项目中都有工作流的影子,工作流中有一个树形结构权限设定的概念就对很多领域比较通用。

  树形结构是组织信息的基本形式,我们现在看到的网站或者ERP前台都是以树形菜单来组织功能的,那么我们在进行架构设计时,就可以将树形结构和功能分开设计,他们之间联系可以通过树形结构的节点link在一起,就象我们可以在圣诞树的树枝上挂各种小礼品一样,这些小礼品就是我们要实现的各种功能。

  有了这个概念,通常比较难实现的用户级别权限控制也有了思路,将具体用户或组也是和树形结构的节点link在一起,这样就间接实现了用户对相应功能的权限控制,有了这样的基本设计方案的架构无疑具备很灵活的拓展性。

  

构造和析构成员函数

归类于: Windows操作系统 - 06 Jan 2009

  类有一个特殊的成员函数叫做构造成员函数,它通常用于初始化类的数据成员。在创建对象时,会自动调用类的构造成员函数。Java中的构造成员函数必须与该类具有相同的名字,另外,构造成员函数一般都应用public类型来说明,这样才能在程序任意的位置创建类的实例--对象。

  下面是一个Rectangle类的构造成员函数,它带有两个参数,分别表示矩形的长和宽:

  public Rectangle(int w,int h)

  width=w;

  height=h;

  area=getArea(w,h);

  除了构造成员函数以外,类还提供了析构成员函数,当对象被从内存中删除时,该成员函数将会被自动调用。通常,在析构成员函数内,你可以填写用来回收对象内部的动态空间的代码。

  

开发Java的又一利器-VisualCafe

归类于: Windows操作系统 - 06 Jan 2009

  适合于Windows 95和Windows NT平台下载的VindowsNT平台下载的Visual CafePreview Release1已于1996年9月正式上市了。它提供给用户开发Java语言的可视化、快捷应用 开发工具。

  Visual Cafe Preview Release1包括⑶

  ●可视化的开发环境

  ●交互作用极强的Interaction Wizard

  ●高级的调试器视图

  ●双向开发

  应注意的是,Visual CafePR1不包括系统程序库及设计管理支援,这一问题渴望在几周后的PR2中得到解决。对于产品开发来说,请继续使用Cafe1.5。

  Symantec公司推出的适用于Windows平台下载的Visual Cafe是第一个适合于Java 语言的完整的快速应用开发RAD(RapidAppli-cation Develop-ment)环境。有媒体称Visual Cafe如同当年Delphi超越微软公司的Visual Basic 3.0一样,今天,它也超越了Bor-land 的Delphi。

  Visual Cafe的核心是快捷应用程序开发工具(RAD:Rapid Application Devel-opment), 比如说图形化用户界面编译器、组件程序库和Interaction Wizard。当Visual Cafe生 成Java代码时,这些工具可以帮助用户以图形化的方式编译应用程序组件,除此之外,用 户不必使用复杂的应用程序开发工具即可通过使用Visual Cafe来将交互性和动画加入 您的应用程序中。Symantec公司Internet部经理Mansour Safai对此评价说:“通过成 功地采用了Visual Cafe产品,现在我们已经可以提供给用户所要求的可视化应用程序开 发编程技术了。”

  Cafe是一个具有强化功能的RAD系统,它主要具有以下显著的特点:

  ●具有一个强大的综合形式设计工具的开发环境

  ●对象库包含了形式、窗口及数据库的系统集成

  ●支持对扩展的对象库进行三级控制

  ●强大的交互功能允许用户指定基于形式对象的操作

  ●程序设计器读取源代码并反映源变化,确保源代码及可视化工具间的同步

  ●产生用户应用程序模板

  ●项目窗口显示项目,包括项目中的收录对象或标准源文件

  ●资源窗口显示事件的文本表及其相应处理方法

  ●变量窗口与一个扩展变量作用域合并

  ●观看窗口允许用户浏览及修改其变量值

  ●观看窗口支持包括函数在内的表达式求值

  ●修改变量值及继续调试均不需要再次下载

  ●设置基于一个表达式的条件断点

  ●源窗口帮助用户快速浏览变量值

  ●所有的调试窗口均提供了便于显示的栏

  ●强化的高速编译器

  ●强化的字节代码编译器生成编译的Java文件

  Visual Cafe强大的交互作用给用户提供了以图形化方式指定所进行操作的功能。Visual Cafe为所指定的关系自动生成或更新必要的Java代码。

  利用Visual Cafe,用户可以从一个标准对象数据库中集合完整的Java应用程序和Applet,而不必再编写源代码。Visual Cafe还提供了一个扩充的源代码开发工具集。

  Visual Cafe综合了Java软件的可视化源程序开发工具,它允许开发人员在可视化视图和源视图之间进行有效地转换。在可视化视图中进行的修改立即反映在源代码中。对源代码的改变自动更新可视化视图。

  Visual Cafe将自动生成所指明关系的必要Java代码。

  Visual Cafe可以在Windows95和Win-dowsNT平台下运行,Symantec公司也准备 为Java开发工作提供一个在Power …

用Java测试网络代码

归类于: Windows操作系统 - 06 Jan 2009

  网络代码被证明是很难进行完全彻底的测试,这是因为测试组件不依赖其他服务器,以独立进程形式工作时效果最好。本文中,Nelson Minar描述了两种单元测试网络代码的方法。首先,他提出您设计网络代码时应该尽可能地做到逻辑上与网络独立。接着,他建议使用Java的协议处理器类模拟网络连接而不是使用实际的网络。使用这些原则,您就可以很轻松地生成网络测试软件。

  测试网络代码并是一件很困难的事情。优秀的单元测试组件运行速度非常快,这样开发人员在每次编译之后就能够进行测试。当然,测试流也要能够稳定地运行,这样它们才可以持续捕获代码中的任何错误。然而,实践证明,网络代码(例如,从URL上读取的代码)是很难快速并稳定地测试的。而且,如果测试组件本身进行网络调用,测试会因为依赖网络和其他服务器将会变得非常缓慢并十分不稳定。

  设想一个可以从网页上下载、格式化并显示XML数据的程序。该程序的本地测试流将需要从一个运行的Web服务器上获取XML数据。但是程序的很多部分――XML解析器、格式化程序和显示程序――可能不需要依赖网络就可以独立测试。请记住这个例子,我将在本文中举例说明两种可以测试与网络相关代码的方法。当测试进行时,这两种方法可以避免使用网络。

  我首先描述简单的网络激活演示程序PrintRSS,然后再讨论如何使用简单的 Reader 和Writer 对象而不是网络连接来设计简化测试的PrintRSS程序。最后我将介绍一个允许程序员合成特殊的testurl库:使用正常http中的URLs绕过网络。注意: 测试将使用JUnit 测试框架的 assert() 方法。

  PrintRSS演示程序

  PrintRSS是一个可以从URL读取数据并对数据进行处理的程序。它可以很好的演示网络代码的测试。PrintRSS 使用RSS格式读取数据,这个数据格式可以简单地将新鲜内容并入XML。本文中,这个重要的RSS结构定义如下:

  

  Channel Title

  Item 1

  Item 2 …

  

  PrintRSS从某个URL下载RSS文档,规定内容的具体布局,然后以一种易读的方式将标题输出到System.out:

  Channel Title

  Item 1

  Item 2

  PrintRSS执行四个主要操作:

  ● 打开与某一URL的连接

  ● 使用XML进行读取

  ● 格式化数据

  ● 输出到System.out

  PrintRSS程序将上述的四种功能封装在一个单独的方法(printURL(URL))中。然而,很难对这个方法进行测试,原因有两个:

  首先代码依赖于从URL上读取的数据;如果URL 是一个http: URL,这就要涉及到网络。而且,输出到System.out所产生的影响使代码自己的行为也被隐藏起来。好好考虑一下这些问题,您又能如何更好地设计Printress来进行测试呢?

  使用eaders和writers封装数据

  简单地解析和格式化XML代码而不是连接网络,您就能分解代码并独立测试数据的逻辑性。虽然再分解代码看起来有点令人畏惧,但是这样的努力是为了得到更好的代码。这是因为代码是经过测试的同时设计也更标准。

  记住,您可以将printURL()的代码解析和格式化功能分解为一个新的方法formatReader(Reader, Writer),这个方法专门用于对一个带有XML数据的Reader对象进行解析然后将结果报告输出到提供的Writer。

  测试 formatReader(Reader, Writer)现在变得简单了:

  testFormatReaderGoodData():

  String goodRSSData = “”

  ”Channel Title”

  ”Item 1″

  ”Item 2″

  ”";

  String …

下一页 »