??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美综合二区,国模精品娜娜一二三区,国产精品夜间视频香蕉http://www.aygfsteel.com/Duffblog/articles/79712.htmlq球?/dc:creator>q球?/author>Tue, 07 Nov 2006 14:39:00 GMThttp://www.aygfsteel.com/Duffblog/articles/79712.htmlhttp://www.aygfsteel.com/Duffblog/comments/79712.htmlhttp://www.aygfsteel.com/Duffblog/articles/79712.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/79712.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/79712.html本文主要讲述的是Dom4j在把Document保存到文件过E中出现的一个中文问题,本文?a class="l2" target="_blank">?0前?/font>一文一P以Spring目无关Q请?a class="l2" target="_blank">春迷”们自重、没事勿扎ͼ文中不之处Ƣ迎大家批评指教?br />  Dom4j是一个比较优U的java开源xml解析目Q支持DOM, SAX and JAXP.Qƈ提供对XPath查询语言的强大支持。因此,?EasyJF团队的很多开源项目中Q如EasyJWeb、EasyDBO{都是用Dom4j来处理xml文g相关操作?br /> 
1、从一个xml文g中蝲入一个Dom到内存:
  FileInputStream in = new FileInputStream(new File(fileName));
  SAXReader reader = new SAXReader();
  doc = reader.read(in);
2、把Dom中的数据写入到xml文g?br />  使用Dom4jQ要把一个Dom中的数据写入到文仉常简单,API如下Q?br />   public void write(Writer writer) throws IOExceptionQ?br />  因此Q假如我们要把一个Document写入到c:\test.xml文g中,可以单的使用下面的代码即可:
java.io.Writer wr= new java.io.FileWrite(filename);
  doc.write(wr);
 wr.close();//注意Q必要执行close()ҎQ才会实现真正的写入
  
  q种用法也是Dom4j所推荐我们使用的非常简单的Ҏ。然而,当我们的dom中包含有中文字符数据的时候,q种Ҏ写入的xml文档却无法直觉打开。会提示cM如下的错误:
   org.dom4j.DocumentException: invalid byte 1 of 1-byte UTF-8 sequence (0xb2) Nested exception: invalid byte 1 of 1-byte UTF-8 sequence (0xb2)
 at org.dom4j.io.SAXReader.read(SAXReader.java:484)
 at org.dom4j.io.SAXReader.read(SAXReader.java:343)
 at 
  我们可以看生成的xml文g~码Q内Ҏutf-8的,但文件格式确是ANSI的,如下图所C:

 
原因分析Q?br />  ׃FileWriter默认的输出编码是ANSI~码Q而Dom4j中的wirteҎ提供的内容实际是以UTF-8保存的,因此造成了包括中文字W的XML文g无法正常阅读?br /> 
解决ҎQ?br />   不能使用单的FileWriterQ而应该是使用一个能指定具体输出~码的WriterQ在JDK的io包中Q OutputStreamWriter可以指定输出~码?br />  正确的代码如下:
java.io.OutputStream out=new java.io.FileOutputStream(fileName);
   java.io.Writer wr=new java.io.OutputStreamWriter(out,"UTF-8");   
   doc.write(wr);   
   wr.close();
   out.close();
  化一下可以写成下面的样式Q?br />   java.io.Writer wr=new java.io.OutputStreamWriter(new java.io.FileOutputStream(fileName),"UTF-8");   
   doc.write(wr);   
   wr.close();

结Q?br />  ׃大多CU的基性开源项目都是老外开发,他们不大可能在中文^Cq行试Q用例数据也很少会用中文^収ͼ因此Q我们即使按照这些开源项目的通用说明文档及用h南去操作Q也会出现很多不可预知的错误。这也是Z么本参与l徏开源团队EasyJFQ提倡搞国开源,q开发一些基性的开源框架如EasyJWeb、EasyDBO的一个初街?br />  当然Q这里提出的中文问题Q算是一个还“没来得及商量”以及要通过一些罕见的处理才能正确q行的中文问题。因此,同样归ƈC“中文问题没商量”系列中?br />
http://blog.lupaworld.com/blog/htm/do_showone/tid_2261.html

]]>
理 Eclipse 环境(Eclipse l护的神U艺?http://www.aygfsteel.com/Duffblog/articles/77560.htmlq球?/dc:creator>q球?/author>Fri, 27 Oct 2006 02:46:00 GMThttp://www.aygfsteel.com/Duffblog/articles/77560.htmlhttp://www.aygfsteel.com/Duffblog/comments/77560.htmlhttp://www.aygfsteel.com/Duffblog/articles/77560.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/77560.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/77560.html

理插g

什么是插gQؓ什么我需要关心插Ӟ

插gQplug-inQ也UCؓ bundleQ是 Eclipse 的功能块。在 Eclipse 中,所有的一切都有其相应的插Ӟq包括:

  • 透视囑֒视图
  • ~辑?/li>
  • 建模工具
  • d和其他核心功?/li>

事实上,整个 Eclipse IDE 是被构Zؓ一个大的插仉合。其他基?Eclipse 的品,例如 IBM Rational] Software ArchitectQ通过d新插件增Z基本?Eclipse?/p>

一l相关的插gl成Ҏ?/i>。特性和它们的插件存在于 Eclipse E序目录中(在这个例子中QEclipse 被安装在 /opt/eclipse 目录中)。下面是目录布局的一个示例:


清单 1. Eclipse Ҏ和插g目录l构


/opt/eclipse/ 
   features/ 
      org.eclipse.jdt_3.1.1/
         feature.xml 
         ... 
   plugins/
      org.eclipse.jdt.ui_3.1.1.jar
      ...
      

Eclipse 可以有许多相同的插gQ针Ҏ个不同的版本有一个这L插g。它知道如何解决插g依赖性、避免版本冲H,因此您永q不必担心同时安装两?Subclipse 插g?/p>

在长期?Eclipse 的过E中Q您L会通过下蝲W三Ҏ件或是创建您自己的插件来增加新的功能。跨不同?Eclipse 版本理q些插g可能是个ȝ。因为插件存在于 Eclipse E序目录中,所以如果您安装 Eclipse 的新版本Q它们就会丢失。这意味着如果您有多个 Eclipse 安装Q就必须保存大量插g的多个副本;甚至Q在每次惌升 Eclipse Ӟ您只能很ȝ地全部重新安装?/p>

如果插件存储于 Eclipse E序目录以外的独立位|,当升U到 Eclipse 的新版本Ӟ׃需要重新安装它们,而且Q可以跨多个 Eclipse 版本׃n插g?/p>

实施控制Q方?1 —?手动的文件系l扩?/span>

有三U方法对插g实施控制。第一U方法是手动创徏一个可以保存插件的目录Q称之ؓ产品扩展Q,插件移到该目录Q然后告?Eclipse 在这里寻扄性和插g?/p>

在我们的例子中,我们会创Z个名?/opt/eclipse-plugins 的位|用来存储插件。ؓ了让 Eclipse 在这里存储插Ӟ您必首先创建如下的目录l构和文Ӟ


清单 2. Eclipse 产品扩展目录l构


/opt/eclipse-plugins/ 
   eclipse/ 
      .eclipseextension
      features/ 
      plugins/
      

注意Q除了创些目录以外,您还必须?eclipse 目录Q在我们的例子中Q是?/opt/eclipse-plugins/eclipseQ中创徏一个名?.eclipseextension 的文件。这个文件让 Eclipse 知道在这里可以找到扩展。它应该有如下内容:


id=org.eclipse.platform name=Eclipse Platform
version=3.1.1

.eclipseextension 文g中的 version 属性应该设|ؓ使用q个产品扩展?Eclipse 的版本。该属性可以是特定的(3.1.1Q、比较一般的Q?.0.0Q或者非怸般的Q?.0.0Q。在撰写本文Ӟ版本号似乎对产品扩展的功能ƈ没有M影响?/p>

注意Q如果您使用的是 Windows]Q则无法通过 Explorer shell 创徏 .eclipseextension 文g。通过打开 NotePadQ输入文件的内容Qƈ其保存?.eclipseextensionQ确保文件类型选中?“所有文件”,否则 Notepad 会在文件名后添?.txtQ,可以创徏q样的文件?/p>

下一件事是将q个插g位置告诉 EclipseQ以便它知道以后在这里寻找插件。选择 Help > Software Updates > Manager Configuration 得到 Product Configuration ManagerQ在q里完成q项工作?/p>

使用 Product Configuration ManagerQ您可以d新的 Eclipse 扩展。ؓ了启用上面创建的扩展Q?opt/eclipse-pluginsQ,我们需要将它作Z个扩展位|添加。每一个h都已l有一个扩展位|,那就?Eclipse 安装中的插g文g夏V在 Eclipse Platform 上右击,选择 Add > Extension Location 可以添加另一个扩展?/p>
?1. d扩展位置
d扩展位置

一旦您已经选中了插件所在的目录Q插件就会显C在产品扩展的列表中。在q里Q您可以验插件是否已扑ֈ?/p>
?2. 查看一个扩展位|中的插?/b>
查看一个扩展位|中的插? src=

Product Configuration 屏幕好的斚w是,您可以很Ҏ地禁用整个插件位|?—?q在q行插g开发和试不同配置时很有用?/p>

实施控制Q方?2 —?通过 Configuration Manager d产品扩展

不必在文件系l中创徏文g夹和 .eclipseextension 文gQ您可以?Eclipse 为您创徏产品扩展?/p>

您可以在 Update ManagerQ?b>Help > Software Updates > Find and InstallQ中创徏新的产品扩展。在安装新的插gӞEclipse 最l会提示您所要安装的位置。在q里Q您可以单击 Change Location 以选择一个品扩展?/p>
?3. 选择插g的安装位|?/b>
选择插g的安装位|? src=

选择 Add Location。当您选定一个目录时QEclipse 在那里为您创徏一个品扩展?/p>
?4. 通过 Update Manager 创徏一个新的品扩?/b>
通过 Update Manager 创徏一个新的品扩? src=

当您以后安装插gӞ保它们是被安装到您所惌的插件扩展地点(参见?3 中的 Install Location 区域Q?/p>

实施控制Q方?3 —?创徏理产品扩展?links 文g?/span>

如果在您的文件系l中已经有了产品扩展Q例如我们在 Ҏ 1 中创建的那个Q那么您可以?Eclipse E序目录中创Z些简单的文gQ告?Eclipse 需要检查这些目录以L插g?/p>

首先Q在 Eclipse 安装文g夹(例如 /opt/eclipseQ中创徏一个名?links 的目录。在q个目录中,您可以创?*.link 文gQ例?emfPlugins.linkQ。每一个链接文件指向一个品扩展位|。Eclipse 会在启动时扫描这?links 文g夹,q在每个链接文g中所指向的品扩展中L插g。下面是一个?links 文g夹的 Eclipse 安装布局的例子:


清单 3. 使用 links 文g夹的 Eclipse 安装布局


/opt/eclipse/
     links/
          emfPlugins.link
          webtools.link
          updateManager.link
          ...
     ...
     

链接文g的内容看上去应该像下面这P


path=/opt/plugins/emf/

Windows
在本文中Q我们着重介l?Eclipse ?Linux] 安装。所有提供的CZ清单对于 Windows 都是有效的。您仅仅需要将路径替换为相应的 windows 路径。另外请注意Q在 Windows 中,路径中需要用双反斜杠(例如 path=c:\\plugins\\emfQ?

/opt/plugins/emf/ 有一?Eclipse 产品扩展的目录结构,?清单 1 所C?/p>

q个Ҏ的优势在于,所有的插g位置被作Z个文件夹中的文本文g来存储。这意味着您可以通过单地?links 文g夹复制到新的 Eclipse 安装中,来升U?Eclipse q其指向您的品扩展文件夹。您也可以通过从每?Eclipse 安装建立一个到 links 文g夹的W号链接Q获得一个针Ҏ?Eclipse 安装的公?links 文g夹(如果您的文gpȝ支持W号链接Q?/p>



回页?/b>


理 Eclipse 工作?/span>

?Eclipse 中,工作区的概念被简单地描述成可以通过插g讉K的资源的容器。工作区是终端用户和 Eclipse q_之间交互的枢U。终端用戯够在工作Z创徏目q处理其中的内容。工作区本n作ؓ一个目录存在于文gpȝ中,q且只局限于每个 Eclipse 实例使用一个。工作区q包含一?.metadata 目录Q用来持久存储诸如插件状态这LU有信息?/p>

Z么我需要多?Eclipse 工作区?

单的{案是ؓ了性能。工作区中的目多Q达到开发系l所能处理项目的临界点的Zp大。ؓ了解册个问题,您可以通过 -data 参数划分 Eclipse 工作区,q个参数被传递给 Eclipse 可执行文Ӟ例如 /opt/eclipse/eclipseQ:


清单 4. 指定不同的工作区


/opt/eclipse-3.1/eclipse -data /opt/workspaces/web
/opt/eclipse-3.2M2/eclipse -data /opt/workspaces/web
/opt/eclipse-3.2M2/eclipse -data /opt/workspaces/dev -vmargs -Xmx512m

工作区提C?/b>
您可以通过?Eclipse 可执行文件传?-showlocation 参数来显C工作区位置。此外,您还可以通过 -vmargs -Xms ?Xmx 参数Z同的工作区指定不同的性能特征?

您也可以通过?Eclipse 中选择 File > Switch Workspace 切换工作区,而不必重新启?Eclipse?/p>

q有一U可能的情况是,您有一?“研I?工作区。在q个工作ZQ您需要?Open TypeQ?b>Ctrl+Shift+TQ等?Eclipse 对蝲入的大代码库的代码仔l搜M遍。如果您试图学习一些例子,或者您曄想知道一个开放源码项目是如何处理特定问题的,那么q种Ҏ是极其有用的?/p>

有多个工作区的不利方面在于需要在它们之间׃n开发首选项。因为首选项被持久存储在 Eclipse 中的一个工作区中,所以您必须导出工作区的首选项q将它们导入您所要求的工作区中(File > Export > PreferencesQ?/p>



回页?/b>


理 Eclipse 安装

Z么我需要多?Eclipse 安装Q?/span>

如果您用多个基?Eclipse 的品,必焉要多?Eclipse 安装。例如,如果您用基本的 Eclipse V3.1 来完成日常的 Java?语言~程Qƈ使用带有 WebTool ?Eclipse 来编?IBM WebSphere] 应用E序Q那么您有两个完全独立?Eclipse 安装。在q些Z Eclipse 的品之间共享插件和工作区可以节U时_q免一些升U带来的ȝ?/p>

您在开?Eclipse 的插件时也需要多?Eclipse 安装。当有了多个 Eclipse 安装Ӟ您可以跨不同?Eclipse 版本试您的插g的功能。您也可以将一l不同的插g对应不同?Eclipse 安装Q以便跨多个环境配置试您的插g?/p>

注意Q通过?Eclipse 中选择 Help > Software Updates > Manage ConfigurationQ来考察 Eclipse IDEQ它启用和禁用属于这些特性的插gQ中的特性,可以理哪些插g?Eclipse 使用。在开发自q插gӞ您也可以通过 Run Configuration Manager 来管理运?Eclipse 试实例时哪些插件被启用。我们通常的经验是Q用多?Eclipse 安装是管理多?Eclipse 版本和配|最方便且最便于重用的方法,对于试目的其如此?/p>

多个 Eclipse 安装

Eclipse 安装独立存在于它们自q文g夹中。要使得多个安装q存Q只要下载您所要的 Eclipse 产品和版本ƈ其解压到它们自q目录中即可。下面是一个用来跨不同 Eclipse 版本试插g的示例布局Q?/p>

/opt/eclipse-3.0
/opt/eclipse-3.1
/opt/eclipse-3.2-m1

对于节约所有当前安装的插g安装旉和避免工作区重复Q尽可能地跨 Eclipse 安装q行׃n是一个好L。正如我们前面所讲述的,您可以共享以下内容:

注意Q跨 Eclipse 安装׃n工作区和首选项可能会有问题Q尤其是?Eclipse 版本的主~号不同Ӟ例如 3.1 ?3.2Q?/p>



回页?/b>


l束?/span>

我们的目的有两个Q初步介l?Eclipse 的基本工作要素,比如插g、项目和工作区;告诉您管理多?Eclipse 环境的好处以及一些不利方面。我们希望您能够接受q些知识q将其应用到您的实践中以节约 Eclipse l护的时间?br />
转自Q?a >http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-manage/



]]>
Oracle数据库字W集问题解析http://www.aygfsteel.com/Duffblog/articles/77550.htmlq球?/dc:creator>q球?/author>Fri, 27 Oct 2006 02:13:00 GMThttp://www.aygfsteel.com/Duffblog/articles/77550.htmlhttp://www.aygfsteel.com/Duffblog/comments/77550.htmlhttp://www.aygfsteel.com/Duffblog/articles/77550.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/77550.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/77550.html l常看到一些朋友问ORACLE字符集方面的问题Q我想以q代的方式来介绍一下?br />
W一ơP代:掌握字符集方面的基本概念?/b>
有些朋友可能会认是多此一举,但实际上正是׃对相兛_本概忉|握不清,才导致了诸多问题和疑问?br />首先是字W集的概c?br />我们知道Q电子计机最初是用来q行U学计算的(所以叫做“计机”)Q但随着技术的发展Q还需要计机q行其它斚w的应用处理。这p求计机不仅能处理数|q能处理诸如文字、特D符L其它信息Q而计机本n能直接处理的只有数g息,所以就要求对这些文字、符号信息进行数值编码,最初的字符集是我们都非常熟悉的ASCIIQ它是用7个二q制位来表示128个字W,而后来随着不同国家、组l的需要,出现了许许多多的字符集,如表CƧ字W的 ISO8859pd的字W集Q表C汉字的GB2312-80、GBK{字W集?br />字符?/b>的实质就是对一l特定的W号Q分别赋予不同的数值编码,以便于计机的处理?br />字符集之间的转换?/b>字符集多了,׃带来一个问题,比如一个字W,在某一字符集中被编码ؓ一个数|而在另一个字W集中被~码为另一个数|比如我来创造两个字W集demo_charset1与demo_charset2Q在demo_charset1中,我规定了三个W号的编码ؓQA Q?001Q,BQ?010Q,Q(1111Q;而在demo_charset2中,我也规定了三个符L~码为:AQ?001Q,CQ?011Q,Q(1111Q,q时我接C个Q务,要编写一个程序,负责在demo_charset1与demo_charset2之间q行转换。由于知道两个字W集的编码规则,对于demo_charset1中的0001Q在转换为demo_charset2Ӟ要将其编码改?001Q对?demo_charset1中的1111Q{换ؓdemo_charset2Ӟ其数g变;而对于demo_charset1中的0010Q其对应的字WؓBQ但在demo_charset2没有对应的字W,所以从理论上无法{换,对于所有这cL法{换的情况Q我们可以将它们l一转换为目标字W集中的一个特D字W(UCؓ“替换字W”)Q比如在q里我们可以?作ؓ替换字符Q所以Bp{换ؓ了?Q出C信息的丢失;同样道理Q将demo_charset2 的C字符转换到demo_charset1Ӟ也会出现信息丢失?br />所以说Q在字符集{换过E中Q如果源字符集中的某个字W在目标字符集中没有定义Q将会出C息丢失?br />数据库字W集的选择?/b>
我们在创建数据库Ӟ需要考虑的一个问题就是选择什么字W集与国家字W集Q通过create database中的CHARACTER SET与NATIONAL CHARACTER SET子句指定Q。考虑q个问题Q我们必要清楚数据库中都需要存储什么数据,如果只需要存储英文信息,那么选择US7ASCII作ؓ字符集就可以Q但是如果要存储中文Q那么我们就需要选择能够支持中文的字W集Q如ZHS16GBKQ;如果需要存储多国语a文字Q那p选择UTF8了?br />数据库字W集的确定,实际上说明这个数据库所能处理的字符的集合及其编码方式,׃字符集选定后再q行更改会有诸多的限Ӟ所以在数据库创建时一定要考虑清楚后再选择?br />而我们许多朋友在创徏数据库时Q不考虑清楚Q往往选择一个默认的字符集,如WE8ISO8859P1或US7ASCIIQ而这两个字符集都没有汉字~码Q所?b>用这U字W集存储汉字信息从原则上说就是错误的?/b>虽然在有些时候选用q种字符集好象也能正怋用,但它会给数据库的使用与维护带来一pd的麻烦,在后面的q代q程中我们将深入分析?br />客户端的字符集?/b>
有过一些Oracle使用l验的朋友,大多会知道通过NLS_LANG来设|客L的情况,NLS_LANG׃下部分组成:NLS_LANG=< Language>_<Territory>.<Clients Characterset>Q其中第三部?lt;Clients Characterset>的本意就是用来指明客L操作pȝ~省使用的字W集。所以按正规的用法,NLS_LANG应该按照客户端机器的实际情况q行配置Q尤其对于字W集一Ҏ是如此,q样Oraclep够在最大程度上实现数据库字W集与客L字符集的自动转换Q当然是如果需要{换的话)?br />ȝ一下第一ơP代的重点Q?/b>
字符集:特定的W号集编码ؓ计算够处理的数|
字符集间的{换:对于在源字符集与目标字符集都存在的符P理论上{换将不会产生信息丢失Q而对于在源字W集中存在而在目标字符集中不存在的W号Q理Z转换会产生信息丢失Q?br />数据库字W集Q?/b>选择能够包含所有将要存储的信息W号的字W集Q?br />客户端字W集讄Q?/b>指明客户端操作系l缺省用的字符集?br />
具体看:http://www.itpub.net/276524,1.html


]]>
ORACLE汉字昄的字W集问题(?http://www.aygfsteel.com/Duffblog/articles/77539.htmlq球?/dc:creator>q球?/author>Fri, 27 Oct 2006 01:36:00 GMThttp://www.aygfsteel.com/Duffblog/articles/77539.htmlhttp://www.aygfsteel.com/Duffblog/comments/77539.htmlhttp://www.aygfsteel.com/Duffblog/articles/77539.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/77539.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/77539.html 在国内外大中型数据库理pȝ中,把ORACLE作ؓ数据库管理^台的用户比较多。ORACLE 不论是数据库理能力q是安全性都是无可非议的Q但是,它在汉字信息的显C方面着实给中国用户带来不少ȝQ笔者多q从事ORACLE数据库管理,l常收到周围用户和外地用户反映有关ORACLE数据库汉字显C问题的求援信,主要现象是把汉字昄Z可识别的qQ造成原来大量信息无法使用。本文将p一问题产生的原因和解决办法q行一些探讨,供存在这斚w问题的用h友参考?

1、原因分?/strong>

通过对用户反映情늚分析Q发现字W集的设|不当是影响ORACLE数据库汉字显C的关键问题。那么字W集是怎么一会事呢?字符集是ORACLE 为适应不同语言文字昄而设定的。用于汉字显C的字符集主要有ZHS16CGB231280QUS7ASCIIQWE8ISO8859P1{。字W集不仅需在服务器端存在,而且客户端也必须有字W集注册。服务器端,字符集是在安装ORACLE时指定的Q字W集登记信息存储在ORACLE数据库字典的V$ NLS_PARAMETERS表中Q客LQ字W集分两U情况,一U情冉|sql*net 2.0以下版本Q字W集是在windows的系l目录下的oracle.ini文g中登记的Q另一U情冉|sql*net 2.0以上Q即32位)版本Q字W集是在windows的系l注册表中登记的。要在客L正确昄ORACLE 数据库汉字信息,首先必须使服务器端的字符集与客户端的字符集一_其次是加载到ORACLE数据库的数据字符集必M服务器指定字W集一致。因此,把用户存在的问题归纳分类Q生汉字显C异常的原因大致有以下几U:

1. 1服务器指定字W集与客户字W集不同Q而与加蝲数据字符集一致?

q种情况是最常见的,只要把客L的字W集讄正确卛_Q解军_法见2.1?

1. 2服务器指定字W集与客户字W集相同,与加载数据字W集不一致?

q类问题一般发生在ORACLE版本升或重新安装系l时选择了与原来服务器端不同的字W集Q而恢复加载的备䆾数据仍是按原字符集卸出的场合,以及加蝲从其它用不同字W集的ORACLE数据库卸出的数据的情c这两种情况中,不管服务器端和客L字符集是否一致都无法昄汉字。解军_法见2.2?

1.3服务器指定字W集与客户字W集不同,与输入数据字W集不一致?

q种情况是在客户端与服务器端字符集不一致时Q从客户端输入了汉字信息。输入的q些信息即便是把客户端字W集更改正确Q也无法昄汉字。解军_法见2.3?

2Q解军_?/strong>

下面分别对上述三种情况l出解决办法。ؓ了叙q方便,假设客户端用WINDOWS95/98环境Qƈ已成功地配置了TCP/IP协议Q安装了ORACLE的sql*netQsql*pluse产品?

2.1 讄客户端字W集与服务器端字W集一?

假设当前服务器端使用US7ASCII字符集?

Q?Q查看服务器端字W集

通过客户端或服务器端的sql*plusdORACLE的一个合法用P执行下列SQL语句Q?

SQL > select * from V$NLS_PARAMETERS
parameter value
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
? ?
NLS_CHARACTERSET US7ASCII
NLS_SORT BINARY
NLS_NCHAR_CHARACTERSET US7ASCII
从上q列表信息中可看出服务器端ORACLE数据库的字符集ؓ'US7ASCII'?

Q?Q按照服务器端字W集对客Lq行配置

配置Ҏ有两U:

安装ORACLE的客L软g时指?
在安装ORACLE的客L产品软gӞ选择与ORACLE服务端一致的字符集(本例为US7ASCIIQ即可?

修改注册信息的方?
ҎORACLE 客户端所选sql*net 的版本分Z列两U情况:

a. 客户端ؓ sql*net 2.0 以下版本

q入Windows的系l目录,~辑oracle.ini文gQ用US7ASCII替换原字W集Q重新启动计机Q设|生效?

b. 客户端ؓ sql*net 2.0 以上版本

在WIN98 ?q?行REGEDIT,W一步选HKEY_LOCAL_MACHINE,W二步选择SOFTWAREQ?W三步选择 ORACLEQ?W四步选择 NLS_LANGQ???与服 ???????W?集(本例为:AMERICAN_AMERICAN.US7ASCIIQ?

2.2 强制加蝲数据字符集与服务器端字符集一?

假设要加载数据从原ORACLE数据库卸出时的字W集为US7ASCIIQ当前ORACLE服务器字W集为WE8ISO8859P1。?br />
有过一些Oracle使用l验的朋友,大多会知道通过NLS_LANG来设|客L的情况,NLS_LANG׃下部分组成:NLS_LANG=< Language>_<Territory>.<Clients Characterset>Q其中第三部?lt;Clients Characterset>的本意就是用来指明客L操作pȝ~省使用的字W集。所以按正规的用法,NLS_LANG应该按照客户端机器的实际情况q行配置Q尤其对于字W集一Ҏ是如此,q样Oraclep够在最大程度上实现数据库字W集与客L字符集的自动转换Q当然是如果需要{换的话)?/font>

下面提供三种解决ҎQ?

Q?Q?服务器端重新安装ORACLE

在重新安装ORACLE 旉择与原卸出数据一致的字符集(本例为US7ASCIIQ?

加蝲原卸出的数据?

q种情况仅仅使用于空库和h同一U字W集的数据?

Q?Q强行修Ҏ务器端ORACLE当前字符?

在用imp命o加蝲数据前,先在客户端用sql*plusdsystem DBA用户Q执行下列SQL语句q行当前ORACLE数据库字W集修改Q?

SQL > create database character set US7ASCII
* create database character set US7ASCII
ERROR at line 1:
ORA-01031: insufficient privileges
你会发现语句执行q程中,出现上述错误提示信息Q此时不用理会,实际上ORACLE数据库的字符集已被强行修改ؓUS7ASCIIQ接着用imp命o装蝲数据。等数据装蝲完成以后Qshutdown 数据库,再startup 数据库,用合法用L录ORACLE数据库,在sql>命o提示W下Q运行select * from V$NLS_PARAMETERSQ可以看到ORACLE数据库字W集已复原,q时再查看有汉字字符数据的表Ӟ汉字已能被正显C?

Q?Q利用数据格式{储,避开字符集限?

q种Ҏ主要用于加蝲外来ORACLE数据库的不同字符集数据。其Ҏ如下Q?

先将数据加蝲到具有相同字W集的服务器上,然后用{换工具卸Zؓfoxbase 格式或access格式数据库,再用转换工具转入C同字W集的ORACLE数据库中Q这样就避免了ORACLE字符集的困扰。目前数据库格式转换的工具很?象power builder5.0以上版本提供的pipelineQMicrosoft Access数据库提供的数据导入/导出功能{。{换方法参见有兌料说明?

2.3匚w字符集替换汉?

对于1.3提到的情况,没有很好的办法,只能先把客户端与服务器端字符集匹配一致后Q根据原输入汉字的特征码替换汉字字符部分?/font>

]]>
Windows中查看端口占用的单用法?/title><link>http://www.aygfsteel.com/Duffblog/articles/75703.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Tue, 17 Oct 2006 09:41:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/75703.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/75703.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/75703.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/75703.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/75703.html</trackback:ping><description><![CDATA[ 用这个命令,在DOSH口执行Qnetstat -ano<br /><br />看看占用0.0.0:80端口的PID是多?br /><br />然后在“Q务管理器”中查到与该PID对应的程序?br /><br />如果d理器的q程中看不到PID栏,则在d理器的菜单〖查看〗〖选择列〗中选择一?br />-----------------------------------------------------------------------------------------------------<br />好东西呀。。。?br />netstat q个命o太有用了?img src ="http://www.aygfsteel.com/Duffblog/aggbug/75703.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-10-17 17:41 <a href="http://www.aygfsteel.com/Duffblog/articles/75703.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM的内存管理机?java.lang.OutOfMemoryError: PermGen space http://www.aygfsteel.com/Duffblog/articles/71676.htmlq球?/dc:creator>q球?/author>Mon, 25 Sep 2006 03:06:00 GMThttp://www.aygfsteel.com/Duffblog/articles/71676.htmlhttp://www.aygfsteel.com/Duffblog/comments/71676.htmlhttp://www.aygfsteel.com/Duffblog/articles/71676.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/71676.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/71676.htmlPermGen space的全U是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决Ҏ也一定是加大内存。说说ؓ什么会内存益出Q这一部分用于存放Class和Meta的信?Class在被Load的时候被攑օPermGen space区域Q它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主E序q行期对PermGen spaceq行清理Q所以如果你的APP会LOAD很多CLASS的话,很可能出现PermGen space错误。这U错误常见在web服务器对JSPq行pre compile的时候?/p>

ҎҎQ?Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

我已l试q了Qok?/p>

]]>
IT从业人员必看?0个论??http://www.aygfsteel.com/Duffblog/articles/68488.htmlq球?/dc:creator>q球?/author>Fri, 08 Sep 2006 05:13:00 GMThttp://www.aygfsteel.com/Duffblog/articles/68488.htmlhttp://www.aygfsteel.com/Duffblog/comments/68488.htmlhttp://www.aygfsteel.com/Duffblog/articles/68488.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/68488.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/68488.htmlIT斚w的论坛太多了Q有l合Q有专业Q有行业Q在各个论坛里؜了几q_体会颇深Q以前是论坛哪里人多Q往哪里去,新浪论坛Q网易是l常ȝQh多啊Q好几十万,M以后才发现没有意思,没有共同的语aQ于是逛专业论坛,行业论坛Q终于找C共同语言Qȝ一下论坛的l验Qh不在多,有仙则灵Q脓不在多,有精则行Q逛了大半辈子Q一个IT人发展方向一定要除了技术外Q业务,理论Q思想一个都不能,于是我推荐如下这些论坛,或许真能帮助您,做论坛,都是赔本的买卖,不收费还帮助你学习,得向斑竹们致敬啊?
  
    以下论坛排名不分先后Q还有许多业界知名的论坛Q主要有点偏门,q个不做概述Q呵c?
  
    IT技术开发综合类
  
    http://community.csdn.net/
  
    适合人群Q只适合软g开发?
  
    技术开发最全面的论坛,里面可以遇到很多牛hQ版面也很全Q什么J2EEQ?NET啊,该有的全上,在这里基本上可以提出M问题Qh气也是最旺的Q不q一般提出的意见都有正方两面的,所以最l解决问题,q是靠自己?
  
    评hQ专业,很牛|是速度慢?
  
    www.itpub.net
  
    适合人群Q数据库开发h?
  
    数据库方面是非常著名的,牛h不少Q不q,现在比较杂,什么都做,|络Q操作系l,行业应用Q到体育贴图Q当然有些也不错Qh气非帔RQ特别是灌水斚wQ^_*.
  
    评hQ强Q速度一般;
  
    http://bbs.chinaunix.net/forum/
  
    适合人员Q系l工E师
  
    q里的特色就是操作系l方面在业界是最著名的,牛h不少Q目前,在数据库Q网l方面也颇有建树Q当然灌水方面也不赖Q呵呵,属于温柔?
  
    评hQ强Q速度q可?
  
    bbs.chinajavaworld.com/
  
    适合人员QJAVA开?
  
    JAVA斚w非常l合的论坛了Q牛Z很多Q是一个难得的JAVA论坛Q涉及你惌的关于JAVA目前M技术?
  
    评论Q强Q速度q可以?
  
    http://www.huihoo.com/forum/
  
    适合人员Q中间g开发?
  
    人气不错Q版面风格独特,在开源,中间Ӟ工作方面非怸错,问题讨论都非常深刅R也很专业?
  
    评hQ很好,速度一般;
  
    IT售前技术顾问综合类
  
    http://www.sysvs.com/bbs
  
    适合人员QIT售前及技术顾?
  
    业界知名的售前技术顾问论坛,比较新异的知识点Q各个IT行业版快划分也比较好Q也非常专业Q绝Ҏ我稀饭(喜欢Q的风格Q网站风g内罕见,也有很多专业文章Q没有地方灌_厉害?
  
    评hQ很好,速度比较?
  
    |络工程c?
  
    www.1000bbs.com
  
    适合人员Q布U?|络工程?
  
    人气很旺Q特色是版面比较紧凑Q综合布U这一块很权威Q很H很专,旉非常久了Q颜色比较明快,是太低端了Q?
  
    评hQ不错,速度一?
  
    http://www.sharecenter.net/
  
    适合人员Q网l工E师
  
    之所以我喜欢是这个网站很多做CISCO工程都知道,也是别h介绍我去的,旉非常久了Q颜色比较暗谈,属于忧郁型?
  
    评hQ不错,速度也还可以
  
    IT营销理c?
  
    http://www.topren.net/forum/index.php 
  
    适合人员Q企业策划,CIO
  
    业界知名的知识站点“唐人社区”,信息化管理顾问可以去看看Qh也很多,可惜Q都是下载,实质性内定w要改观,我记得是非常专业的网站?
  
    评hQ不错,速度也还可以?
  
    IT理l合c?
  
    http://club.amteam.org/
  
    适合人群Q大多数Q?
  
    评论cL较多Q基本上在其他媒体上看到的评论,q里都会有,要想了解IT发展的情况,来q里看看?
  
    评hQ很好,休闲工作都可以看?

http://dev.csdn.net/article/72/72374.shtm

]]>
?Java 应用E序中计划重复执行的dQ{Q?/title><link>http://www.aygfsteel.com/Duffblog/articles/66679.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Wed, 30 Aug 2006 08:00:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/66679.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/66679.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/66679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/66679.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/66679.html</trackback:ping><description><![CDATA[ <div> <blockquote>所有类型的 Java 应用E序一般都需要计划重复执行的d。企业应用程序需要计划每日的日志或者晚间批处理q程。一?J2SE 或?J2ME 日历应用E序需要根据用LU定计划闚w旉。不q,标准的调度类 <code><font face="新宋?>Timer</font></code> ?<code><font face="新宋?>TimerTask</font></code> 没有_的灵zL,无法支持通常需要的计划dcd。在本文中,Java 开发h?Tom White 向您展示了如何构Z个简单通用的计划框Ӟ以用于执行Q意复杂的计划d?/blockquote> <p>我将?<code><font face="新宋?>java.util.Timer</font></code> ?<code><font face="新宋?>java.util.TimerTask</font></code> l称?<i>Java 计时器框?/i>Q它们ɽE序员可以很Ҏ地计划简单的dQ注意这些类也可用于 J2ME 中)。在 Java 2 SDK, Standard Edition, Version 1.3 中引入这个框架之前,开发h员必ȝ写自q调度E序Q这需要花费很大精力来处理U程和复杂的 <code><font face="新宋?>Object.wait()</font></code> Ҏ。不q,Java 计时器框架没有够的能力来满多应用程序的计划要求。甚至一w要在每天同一旉重复执行的Q务,也不能直接?<code><font face="新宋?>Timer</font></code> 来计划,因ؓ在夏令时开始和l束时会出现旉跌?</p> <p>本文展示了一个通用?<code><font face="新宋?>Timer</font></code> ?<code><font face="新宋?>TimerTask</font></code> 计划框架Q从而允许更灉|的计划Q务。这个框枉常简?—?它包括两个类和一个接?—?q且Ҏ掌握。如果您习惯于?Java 定时器框Ӟ那么您应该可以很快地掌握q个计划框架?/p> <p> <a name="1.0"> <span id="wmqeeuq" class="atitle2">计划单次d</span> </a> <br />计划框架建立?Java 定时器框架类的基之上。因此,在解释如何用计划框架以及如何实现它之前Q我们将首先看看如何用这些类q行计划?/p> <p>惛_一个煮蛋计时器Q在数分钟之后(q时蛋煮好了Q它会发出声x醒您。清?1 中的代码构成了一个简单的煮蛋计时器的基本l构Q它?Java 语言~写Q?/p> <a name="IDAFLSVB"> <b>清单 1. EggTimer c?/b> </a> <br /> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> package org.tiling.scheduling.examples; import java.util.Timer; import java.util.TimerTask; public class EggTimer { private final Timer timer = new Timer(); private final int minutes; public EggTimer(int minutes) { this.minutes = minutes; } public void start() { timer.schedule(new TimerTask() { public void run() { playSound(); timer.cancel(); } private void playSound() { System.out.println("Your egg is ready!"); // Start a new thread to play a sound... } }, minutes * 60 * 1000); } public static void main(String[] args) { EggTimer eggTimer = new EggTimer(2); eggTimer.start(); } } </code> </pre> </td> </tr> </tbody> </table> <p> <code> <font face="新宋?>EggTimer</font> </code> 实例拥有一?<code><font face="新宋?>Timer</font></code> 实例Q用于提供必要的计划。用 <code><font face="新宋?>start()</font></code> Ҏ启动煮蛋计时器后Q它p划了一?<code><font face="新宋?>TimerTask</font></code>Q在指定的分钟数之后执行。时间到了,<code><font face="新宋?>Timer</font></code> 在后台调用 <code><font face="新宋?>TimerTask</font></code> ?<code><font face="新宋?>start()</font></code> ҎQ这会它发出声韟뀂在取消计时器后q个应用E序׃中止?/p> <p> <a name="2.0"> <span id="wmqeeuq" class="atitle2">计划重复执行的Q?/span> </a> <br />通过指定一个固定的执行频率或者固定的执行旉间隔Q?code><font face="新宋?>Timer</font></code> 可以寚w复执行的dq行计划。不q,有许多应用程序要求更复杂的计划。例如,每天清晨在同一旉发出叫醒铃声的闹钟不能简单地使用固定的计划频?86400000 毫秒Q?4 时Q,因ؓ在钟拨快或者拨慢(如果您的时区使用夏oӞ的那些天里,叫醒可能q晚或者过早。解x案是使用日历法计算每日事g下一ơ计划发生的旉。而这正是计划框架所支持的。考虑清单 2 中的 <code><font face="新宋?>AlarmClock</font></code> 实现Q?/p> <a name="IDABNSVB"> <b>清单 2. AlarmClock c?/b> </a> <p> </p> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> package org.tiling.scheduling.examples; import java.text.SimpleDateFormat; import java.util.Date; import org.tiling.scheduling.Scheduler; import org.tiling.scheduling.SchedulerTask; import org.tiling.scheduling.examples.iterators.DailyIterator; public class AlarmClock { private final Scheduler scheduler = new Scheduler(); private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS"); private final int hourOfDay, minute, second; public AlarmClock(int hourOfDay, int minute, int second) { this.hourOfDay = hourOfDay; this.minute = minute; this.second = second; } public void start() { scheduler.schedule(new SchedulerTask() { public void run() { soundAlarm(); } private void soundAlarm() { System.out.println("Wake up! " + "It's " + dateFormat.format(new Date())); // Start a new thread to sound an alarm... } }, new DailyIterator(hourOfDay, minute, second)); } public static void main(String[] args) { AlarmClock alarmClock = new AlarmClock(7, 0, 0); alarmClock.start(); } } </code> </pre> </td> </tr> </tbody> </table> <p>注意q段代码与煮蛋计时器应用E序非常怼?code><font face="新宋?>AlarmClock</font></code> 实例拥有一?<code><font face="新宋?>Scheduler</font></code> Q而不?<code><font face="新宋?>Timer</font></code>Q实例,用于提供必要的计划。启动后Q这个闹钟对<code><font face="新宋?> SchedulerTask</font></code> Q而不?<code><font face="新宋?>TimerTask</font></code>Q进行调度用以发出报警声。这个闹钟不是计划一个Q务在固定的gq时间后执行Q而是?<code><font face="新宋?>DailyIterator</font></code> cLq其计划。在q里Q它只是计划d在每天上?7:00 执行。下面是一个正常运行情况下的输出:</p> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> Wake up! It's 24 Aug 2003 07:00:00.023 Wake up! It's 25 Aug 2003 07:00:00.001 Wake up! It's 26 Aug 2003 07:00:00.058 Wake up! It's 27 Aug 2003 07:00:00.015 Wake up! It's 28 Aug 2003 07:00:00.002 ... </code> </pre> </td> </tr> </tbody> </table> <p> <code> <font face="新宋?>DailyIterator</font> </code> 实现?code><font face="新宋?> ScheduleIterator</font></code>Q这是一个将<code><font face="新宋?> SchedulerTask</font></code> 的计划执行时间指定ؓ一pd <code><font face="新宋?>java.util.Date</font></code> 对象的接口。然?<code><font face="新宋?>next()</font></code> Ҏ按时间先后顺序P?<code><font face="新宋?>Date</font></code> 对象。返回?<code><font face="新宋?>null</font></code> 会d取消Q即它再也不会运行)—?q样的话Q试囑ֆơ计划将会抛Z个异常。清?3 包含 <code><font face="新宋?>ScheduleIterator</font></code> 接口Q?/p> <a name="listing3"> <b>清单 3. ScheduleIterator 接口</b> </a> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> package org.tiling.scheduling; import java.util.Date; public interface ScheduleIterator { public Date next(); } </code> </pre> </td> </tr> </tbody> </table> <p> <code> <font face="新宋?>DailyIterator </font> </code>?<code><font face="新宋?>next()</font></code> Ҏq回表示每天同一旉Q上?7:00Q的 <code><font face="新宋?>Date</font></code> 对象Q如清单 4 所C。所以,如果Ҏ构徏?<code><font face="新宋?>next()</font></code> c调?<code><font face="新宋?>next()</font></code>Q那么将会得C递给构造函数的那个日期当天或者后面一天的 7:00 AM。再ơ调?<code><font face="新宋?>next()</font></code> 会返回后一天的 7:00 AMQ如此重复。ؓ了实现这U行为,<code><font face="新宋?>DailyIterator</font></code> 使用?<code><font face="新宋?>java.util.Calendar</font></code> 实例。构造函C在日历中加上一天,Ҏ历的q种讄使得W一ơ调?<code><font face="新宋?>next()</font></code> 会返回正的 <code><font face="新宋?>Date</font></code>。注意代码没有明地提到夏o时修正,因ؓ <code><font face="新宋?>Calendar</font></code> 实现Q在本例中是 <code><font face="新宋?>GregorianCalendar</font></code>Q负责对此进行处理,所以不需要这样做?/p> <a name="IDAHRSVB"> <b>清单 4. DailyIterator c?/b> </a> <br /> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> package org.tiling.scheduling.examples.iterators; import org.tiling.scheduling.ScheduleIterator; import java.util.Calendar; import java.util.Date; /** * A DailyIterator class returns a sequence of dates on subsequent days * representing the same time each day. */ public class DailyIterator implements ScheduleIterator { private final int hourOfDay, minute, second; private final Calendar calendar = Calendar.getInstance(); public DailyIterator(int hourOfDay, int minute, int second) { this(hourOfDay, minute, second, new Date()); } public DailyIterator(int hourOfDay, int minute, int second, Date date) { this.hourOfDay = hourOfDay; this.minute = minute; this.second = second; calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, second); calendar.set(Calendar.MILLISECOND, 0); if (!calendar.getTime().before(date)) { calendar.add(Calendar.DATE, -1); } } public Date next() { calendar.add(Calendar.DATE, 1); return calendar.getTime(); } } </code> </pre> </td> </tr> </tbody> </table> <p> <a name="3.0"> <span id="wmqeeuq" class="atitle2">实现计划框架</span> </a> <br />在上一节,我们学习了如何用计划框Ӟq将它与 Java 定时器框架进行了比较。下面,我将向您展示如何实现q个框架。除?清单 3 中展C的 <code><font face="新宋?>ScheduleIterator</font></code> 接口Q构成这个框架的q有另外两个c?—?<code><font face="新宋?>Scheduler</font></code> ?<code><font face="新宋?>SchedulerTask</font></code> 。这些类实际上在内部使用 <code><font face="新宋?>Timer</font></code> ?<code><font face="新宋?>SchedulerTask</font></code>Q因划其实就是一pd的单ơ定时器。清?5 ?6 昄了这两个cȝ源代码:</p> <a name="IDASSSVB"> <b>清单 5. Scheduler</b> </a> <br /> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> package org.tiling.scheduling; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class Scheduler { class SchedulerTimerTask extends TimerTask { private SchedulerTask schedulerTask; private ScheduleIterator iterator; public SchedulerTimerTask(SchedulerTask schedulerTask, ScheduleIterator iterator) { this.schedulerTask = schedulerTask; this.iterator = iterator; } public void run() { schedulerTask.run(); reschedule(schedulerTask, iterator); } } private final Timer timer = new Timer(); public Scheduler() { } public void cancel() { timer.cancel(); } public void schedule(SchedulerTask schedulerTask, ScheduleIterator iterator) { Date time = iterator.next(); if (time == null) { schedulerTask.cancel(); } else { synchronized(schedulerTask.lock) { if (schedulerTask.state != SchedulerTask.VIRGIN) { throw new IllegalStateException("Task already scheduled " + "or cancelled"); } schedulerTask.state = SchedulerTask.SCHEDULED; schedulerTask.timerTask = new SchedulerTimerTask(schedulerTask, iterator); timer.schedule(schedulerTask.timerTask, time); } } } private void reschedule(SchedulerTask schedulerTask, ScheduleIterator iterator) { Date time = iterator.next(); if (time == null) { schedulerTask.cancel(); } else { synchronized(schedulerTask.lock) { if (schedulerTask.state != SchedulerTask.CANCELLED) { schedulerTask.timerTask = new SchedulerTimerTask(schedulerTask, iterator); timer.schedule(schedulerTask.timerTask, time); } } } } } </code> </pre> </td> </tr> </tbody> </table> <p>清单 6 昄?<code><font face="新宋?>SchedulerTask</font></code> cȝ源代码:</p> <a name="IDACTSVB"> <b>清单 6. SchedulerTask</b> </a> <br /> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> package org.tiling.scheduling; import java.util.TimerTask; public abstract class SchedulerTask implements Runnable { final Object lock = new Object(); int state = VIRGIN; static final int VIRGIN = 0; static final int SCHEDULED = 1; static final int CANCELLED = 2; TimerTask timerTask; protected SchedulerTask() { } public abstract void run(); public boolean cancel() { synchronized(lock) { if (timerTask != null) { timerTask.cancel(); } boolean result = (state == SCHEDULED); state = CANCELLED; return result; } } public long scheduledExecutionTime() { synchronized(lock) { return timerTask == null ? 0 : timerTask.scheduledExecutionTime(); } } } </code> </pre> </td> </tr> </tbody> </table> <p>像煮蛋计时器,<code><font face="新宋?>Scheduler</font></code> 的每一个实例都拥有 <code><font face="新宋?>Timer</font></code> 的一个实例,用于提供底层计划?code><font face="新宋?>Scheduler</font></code> q没有像实现煮蛋计时器时那样使用一个单ơ定时器Q它一l单ơ定时器串接在一P以便在由 <code><font face="新宋?>ScheduleIterator</font></code> 指定的各个时间执?<code><font face="新宋?>SchedulerTask</font></code> cR?/p> <p>考虑 <code><font face="新宋?>Scheduler</font></code> 上的 public <code><font face="新宋?>schedule()</font></code> Ҏ —?q是计划的入口点Q因为它是客戯用的Ҏ。通过调用 <code><font face="新宋?>ScheduleIterator</font></code> 接口?<code><font face="新宋?>next()</font></code>Q发现第一ơ执?<code><font face="新宋?>SchedulerTask</font></code> 的时间。然后通过调用底层 <code><font face="新宋?>Timer</font></code> cȝ单次 <code><font face="新宋?>schedule()</font></code> ҎQ启动计划在q一时刻执行。ؓ单次执行提供?<code><font face="新宋?>TimerTask</font></code> 对象是嵌入的 <code><font face="新宋?>SchedulerTimerTask</font></code> cȝ一个实例,它包装了d和P代器QiteratorQ。在指定的时_调用嵌入cȝ <code><font face="新宋?>run()</font></code> ҎQ它使用包装的Q务和q代器引用以侉K新计划Q务的下一ơ执行?code><font face="新宋?>reschedule()</font></code> Ҏ?<code><font face="新宋?>schedule()</font></code> Ҏ非常怼Q只不过它是 private 的,q且执行一l稍有不同的 <code><font face="新宋?>SchedulerTask</font></code> 状态检查。重新计划过E反复重复,为每ơ计划执行构造一个新的嵌入类实例Q直CQ务或者调度程序被取消Q或?JVM 关闭Q?/p> <p>cM?<code><font face="新宋?>TimerTask</font></code>Q?code><font face="新宋?>SchedulerTask</font></code> 在其生命周期中要l历一pd的状态。创建后Q它处于 <code><font face="新宋?>VIRGIN</font></code> 状态,q表明它从没有计划过。计划以后,它就变ؓ <code><font face="新宋?>SCHEDULED</font></code> 状态,再用下面描述的方法之一取消d后,它就变ؓ <code><font face="新宋?>CANCELLED</font></code> 状态。管理正的状态{?—?如保证不对一个非 <code><font face="新宋?>VIRGIN</font></code> 状态的dq行两次计划 —?增加?<code><font face="新宋?>Scheduler</font></code> ?<code><font face="新宋?>SchedulerTask</font></code> cȝ复杂性。在q行可能改变d状态的操作Ӟ代码必须同步d的锁对象?/p> <p> <a name="3.1"> <span id="wmqeeuq" class="atitle3">取消d</span> </a> <br />取消计划d有三U方式。第一U是调用 <code><font face="新宋?>SchedulerTask</font></code> ?<code><font face="新宋?>cancel()</font></code> Ҏ。这很像调用 <code><font face="新宋?>TimerTask</font></code> ?<code><font face="新宋?>cancel()</font></code>ҎQQ务再也不会运行了Q不q已l运行的d<i>仍会</i>q行完成?<code><font face="新宋?>cancel()</font></code> Ҏ的返回值是一个布|表示如果没有调用 <code><font face="新宋?>cancel()</font></code> 的话Q计划的d是否q会q行。更准确地说Q如果Q务在调用 <code><font face="新宋?>cancel()</font></code> 之前?<code><font face="新宋?>SCHEDULED</font></code> 状态,那么它就q回 <code><font face="新宋?>true</font></code>。如果试囑ֆơ计划一个取消的Q甚x已计划的QQ务,那么 <code><font face="新宋?>Scheduler</font></code> ׃抛出一?<code><font face="新宋?>IllegalStateException</font></code>?/p> <p>取消计划d的第二种方式是让 <code><font face="新宋?>ScheduleIterator</font></code> q回 <code><font face="新宋?>null</font></code>。这只是W一U方式的化操作,因ؓ <code><font face="新宋?>Scheduler</font></code> c调?<code><font face="新宋?>SchedulerTask</font></code> cȝ <code><font face="新宋?>cancel()</font></code>Ҏ。如果您想用q代器而不是Q务来控制计划停止旉Ӟq得上q种取消d的方式了?/p> <p>W三U方式是通过调用?<code><font face="新宋?>cancel()</font></code> Ҏ取消整个 <code><font face="新宋?>Scheduler</font></code>。这会取消调试程序的所有Q务,q它不能再计划Md?/p> <p> <a name="4.0"> <span id="wmqeeuq" class="atitle2">扩展 cron 实用E序</span> </a> <br />可以计划框架比?UNIX ?<code><font face="新宋?>cron</font></code> 实用E序Q只不过计划ơ数的规定是强制性而不是声明性的。例如,?<code><font face="新宋?>AlarmClock</font></code> 实现中用的 <code><font face="新宋?>DailyIterator</font></code> c,它的计划?<code><font face="新宋?>cron</font></code> 作业的计划相同,都是׃ <code><font face="新宋?>0 7 * * *</font></code> 开始的 <code><font face="新宋?>crontab</font></code> Ҏ定的Q这些字D分别指定分钟、小时、日、月和星期)?/p> <p>不过Q计划框架比 <code><font face="新宋?>cron</font></code> 更灵zR想像一个在早晨打开热水?<code><font face="新宋?>HeatingController</font></code> 应用E序。我xC它“在每个工作日上?8:00 打开热水Q在周未上午 9:00 打开热水”。?<code><font face="新宋?>cron</font></code>Q我需要两?<code><font face="新宋?>crontab</font></code> (<code><font face="新宋?>0 8 * * 1,2,3,4,5</font></code> ?code><font face="新宋?> 0 9 * * 6,7</font></code>Q。而?<code><font face="新宋?>ScheduleIterator</font></code> 的解x案更z一些,因ؓ我可以用复合(compositionQ来定义单一q代器。清?7 昄了其中的一U方法:</p> <a name="IDA51SVB"> <b>清单 7. 用复合定义单一q代?/b> </a> <br /> <table cellspacing="0" cellpadding="5" width="100%" bgcolor="#cccccc" border="1"> <tbody> <tr> <td> <pre> <code> int[] weekdays = new int[] { Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY }; int[] weekend = new int[] { Calendar.SATURDAY, Calendar.SUNDAY }; ScheduleIterator i = new CompositeIterator( new ScheduleIterator[] { new RestrictedDailyIterator(8, 0, 0, weekdays), new RestrictedDailyIterator(9, 0, 0, weekend) } ); </code> </pre> </td> </tr> </tbody> </table> <p> <code> <font face="新宋?>RestrictedDailyIterator</font> </code> cd?<code><font face="新宋?>DailyIterator</font></code>Q只不过它限制ؓ只在一周的特定日子里运行,而一?<code><font face="新宋?>CompositeIterator</font></code> cd得一l?<code><font face="新宋?>ScheduleIterator</font></code>sQƈ日期正排列到单个计划中?/p> <p>有许多计划是 <code><font face="新宋?>cron</font></code> 无法生成的,但是 <code><font face="新宋?>ScheduleIterator</font></code> 实现却可以。例如,“每个月的最后一天”描q的计划可以用标?Java 日历法来实玎ͼ?<code><font face="新宋?>Calendar</font></code> c)Q而用 <code><font face="新宋?>cron</font></code> 则无法表辑֮。应用程序甚x需使用 <code><font face="新宋?>Calendar</font></code> cR在本文的源代码中,我加入了一个安全灯控制器的例子Q它按“在日落之前 15 分钟开灯”这一计划q行。这个实C用了 Calendrical Calculations Software Package Q用于计当圎ͼl定l度和纬度)的日落时间?/p> <p> <a name="5.0"> <span id="wmqeeuq" class="atitle2">实时保证</span> </a> <br />在编写用计划的应用E序Ӟ一定要了解框架在时间方面有什么保证。我的Q务是提前q是延迟执行Q如果有提前或者gq,偏差最大值是多少Q不q的是,对这些问题没有简单的{案。不q在实际中,它的行ؓ对于很多应用E序已经_了。下面的讨论假设pȝ旉是正的Q有关网l时间协?Network Time Protocol)的信息)?/p> <p>因ؓ <code><font face="新宋?>Scheduler</font></code> 计划委托给 <code><font face="新宋?>Timer</font></code> c,<code><font face="新宋?>Scheduler</font></code> 可以做出的实时保证与 <code><font face="新宋?>Timer</font></code> 的一栗?code><font face="新宋?>Timer</font></code> ?<code><font face="新宋?>Object.wait(long)</font></code> Ҏ计划d。当前线E要{待直到唤醒它,唤醒可能Z以下原因之一Q?/p> <ol> <li>另一个线E调用对象的 <code><font face="新宋?>notify()</font></code> 或?<code><font face="新宋?>notifyAll()</font></code> Ҏ?</li> <li>U程被另一个线E中断?</li> <li>在没有通知的情况下Q线E被唤醒Q称?<i>spurious wakeup</i>QJoshua Bloch ?<i>Effective Java Programming Language Guide</i> 一书中 Item 50 对其q行了描q?Q?</li> <li>规定的时间已到?</li> </ol> <p>对于 <code><font face="新宋?>Timer</font></code> cL_W一U可能性是不会发生的,因ؓ对其调用 <code><font face="新宋?>wait()</font></code> 的对象是U有的。即便如此,<code><font face="新宋?>Timer</font></code> 实现仍然针对前三U提前唤醒的原因q行了保护,q样保证了线E在规定旉后才唤醒。目前,<code><font face="新宋?>Object.wait(long)</font></code> 的文档注释声明,它会在规定的旉“前后”苏醒,所以线E有可能提前唤醒。在本例中,<code><font face="新宋?>Timer</font></code> 会让另一?<code><font face="新宋?>wait()</font></code> 执行Q?code><font face="新宋?>scheduledExecutionTime - System.currentTimeMillis()</font></code>Q毫U,从而保?i>d永远不会提前执行</i>?/p> <p>d是否会gq执行呢Q会的。gq执行有两个主要原因Q线E计划和垃圾攉?/p> <p>Java 语言规范故意没有对线E计划做严格的规定。这是因?Java q_是通用的,q对于大范围的g及其相关的操作系l。虽然大多数 JVM 实现都有公^的线E调度程序,但是q一Ҏ有Q何保?—?当然Q各个实现都有不同的为线E分配处理器旉的策略。因此,?<code><font face="新宋?>Timer</font></code> U程在分配的旉后唤醒时Q它实际执行其Q务的旉取决?JVM 的线E计划策略,以及有多其他线E竞争处理器旉。因此,要减~Q务的延迟执行Q应该将应用E序中可q行的线E数降至最。ؓ了做到这一点,可以考虑在一个单独的 JVM 中运行调度程序?/p> <p>对于创徏大量对象的大型应用程序,JVM 花在垃圾攉QGCQ上的时间会非常多。默认情况下Q进?GC Ӟ整个应用E序都必ȝ待它完成Q这可能要有几秒钟甚x长的旉Q?code><font face="新宋?>Java</font></code> 应用E序启动器的命o行选项 <code><font face="新宋?>-verbose:gc</font></code> 导致向控制台报告每一?GC 事gQ。要这些由 GC 引v的暂停(q可能会影响快速Q务的执行Q降x,应该应用程序创建的对象的数目降x低。同P在单独的 JVM 中运行计划代码是有帮助的。同Ӟ可以试用几个微调选项以尽可能地减?GC 暂停。例如,增量 GC 会尽量将L集的代h分散到几个小的收集上。当然这会降?GC 的效率,但是q可能是旉计划的一个可接受的代仗?/p> <p> <a name="5.1"> <span id="wmqeeuq" class="atitle3">我被计划C么时候?</span> </a> <br />如果d本n能监视ƈ记录所有gq执行的实例Q那么对于确定Q务是否能按时q行会很有帮助?code><font face="新宋?>SchedulerTask</font></code> cM?code><font face="新宋?> TimerTask</font></code>Q有一?<code><font face="新宋?>scheduledExecutionTime()</font></code> ҎQ它q回计划d最q一ơ执行的旉。在d?<code><font face="新宋?>run()</font></code> Ҏ开始时Q对表达?<code><font face="新宋?>System.currentTimeMillis() - scheduledExecutionTime()</font></code> q行判断Q可以让您确定Q务gq了多久执行Q以毫秒为单位)。可以记录这个|以便生成一个关于gq执行的分布l计。可以用q个值决定Q务应当采取什么动?—?例如Q如果Q务太q了Q那么它可能什么也不做。在遵@上述原则的情况下Q如果应用程序需要更严格的时间保证,可参?Java 的实时规范?/p> <p> <a name="6.0"> <span id="wmqeeuq" class="atitle2">l束?/span> </a> <br />在本文中Q我介绍?Java 定时器框架的一个简单增强,它得灵zȝ计划{略成ؓ可能。新的框架实质上是更通用?<code><font face="新宋?>cron</font></code> —?事实上,?<code><font face="新宋?>cron</font></code> 实现Z?<code><font face="新宋?>ScheduleIterator</font></code> 接口Q用以替换单U的 Java <code><font face="新宋?>cron</font></code>Q这是非常有用的。虽然没有提供严格的实时保证Q但是许多需要计划定期Q务的通用 Java 应用E序都可以用这一框架?/p> <p>下蝲本文中用的 <a ><u>源代?/u></a>?br /><br /><a >http://www.dingl.com/view.shtml?xh=362</a></p> </div> <img src ="http://www.aygfsteel.com/Duffblog/aggbug/66679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-08-30 16:00 <a href="http://www.aygfsteel.com/Duffblog/articles/66679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java虚拟机的 10 q??http://www.aygfsteel.com/Duffblog/articles/66677.htmlq球?/dc:creator>q球?/author>Wed, 30 Aug 2006 07:56:00 GMThttp://www.aygfsteel.com/Duffblog/articles/66677.htmlhttp://www.aygfsteel.com/Duffblog/comments/66677.htmlhttp://www.aygfsteel.com/Duffblog/articles/66677.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/66677.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/66677.html当我们说到“Java”这个词的时候,指的是四个相互关联的概念QJava语言、Java API、Java Class文g格式、Java虚拟机。整个Java体系是基于Java 虚拟机构造的Q正因ؓ如此Q才能实现Java的安全性和|络Ud性。Javaq是第一个采用“虚拟机”概늚体系Q但却是W一个得到广泛运用的虚拟机^台?“虚拟”,是一U隔ȝ理资源与逻辑资源的手DcJava虚拟机的“虚拟”,则是用来隔离物理机器、底层操作系l与Java语言规范实现的手Dc?br />虽然Java是一U面向对象的语言Q我们^时大量用的Q是对象间的多态、组?Composition)、委z(DelegationQ?但当我们讨论虚拟机的时候,我们看见的基本概念却是“栈(Stack)”和“堆(Heap)”。根据冯Z曼的“存储计”模型,所有的代码都保存在代码I间中,随着E序计数器指针的变化q行E序的执行、蟩转。Java虚拟Z没有寄存器的概念Q方法调用是采用“栈”进行的Q这是一U安全、简z的Ҏ?br />Java虚拟机通过c装载器支持对类的隔,q也是Java实现安全性的基础。每个类都具有自q命名I间Q在h不同安全U别的沙׃q行Q因此不会生低安全U别的代码来权讉K高别代码的Z。类装蝲器的出现是Java虚拟Z大部分用C实现的虚拟机的显著不同之处?br />Java虚拟机的另外一个显著特点就是实C自动的垃圾收集。在往常,写程序的时候要牢记对象之间的关联,在每个程序块中假若申请了对象I间Q就必须在出口释放掉Q方法调用往往同时也就是对象的边界。而自动垃圾收集带l开发者的最大好处,是可以非常方便C整体上把pȝ的对象组l成一张对象图Q只需往q张图中d对象Q维护对象之间的兌Q却不需要自己做复杂的清扫工作。正是有了这U思维单纯的对象图的支持,OR Mapping(关系数据库与对象映射Q技术在最q得以大行其道,设计模式也更Ҏ被Java体所接受?br />
虚拟机的优化
1995q第一代的Java出台之时Q其虚拟机执行是依靠“字节码解释器(Byte Code InterceptorQ”的Q也是说每条指令都p拟机来当释执行,q造成速度令h抓狂地缓慢。更有甚者有人开始ȝ许多的“速度优化l验”,比如_“尽量把所有的代码都放在较大的Ҏ中执行”与“少用接口”等{,q完全与Java语言的设计目的背道而驰Q现在看h是多么可W的奇谈怪论Q当时却是很多程序员z|乐道的经验之谈。无他,Java本n执行太慢了。Java生命的前十分之三是如此~慢地渡q的?br />于是QSun的工E师开始拼命想着提高执行速度。JIT静态编译器的出现是?996q十月,Sun攑և了第一个编译器。JIT~译器在每段代码执行前进行编译,~译的结果ؓ本地静态机器码Q执行速度有了质的提高。Symantec公司当时凭借其傲h的JIT~译器,在整个Java界受到热烈的q捧。在其后?998q_Java 1.2发布的时候,附带了JIT~译器,从此Java的用者终于可以抛开上面说的那些奇怪的“速度优化l验”了?br />JIT静态编译器虽然可以解决一些问题,但是性能仍然和C/C++有很大的差距。对一D늨序而言Q一名优U的程序员是如何来改进q行速度的呢Q首先,他不会傻到把所有的代码都来优化Q他会观察、思考到底哪D代码对整体性能影响最大?然后集中_֊来优化这一D代码。按照经验,整个E序 10%-20%的代码,会占?80%-90%的运行时间。用q种ҎQ在同样的时间、付出同L度的努力后,q名优秀的程序员使整个程序的性能得到了很大程度的优化。HotSpot引擎Q就是模仿h工的q种Ҏq行优化的。在E序q行的开始,Java代码仍然解释执行Q但HotSpot引擎开始进行采?Profiling)。根据采Ll果Q决定某D늨序是占用较多q行旉的,p为它是“HotSpot”,它也是目前E序的瓶颈, 引擎开始启动一个单独的U程q行优化。因Z象原始的 JIT~译器那h差别的编译所有代码,HotSpot引擎可以集中_֊来对HotSpot代码q行深度优化Q这栯部分代码执行h更加q捷。之前的静态编译器只能按照预定的策略进行编译优化,而HotSpot引擎的优化是Z采样的结果的Q因此这U方法对所有的应用E序都有效?999q??7日,Sun攑և了第一个HotSpot引擎。在随后?000q?月的JDK 1.3中,包含了HotSopt引擎Q这也1.3成了一个具有里E碑意义的发行版本。到q里QJava的十q生命,已经q去了一半?br />HotSpot代表的是一U动态编译的技术。对Javaq种大量使用委派、组合等面向对象Ҏ的E序来说Q动态编译比起静态编译来有显著的优势。比如Method Inlining。方法的调用是一个很耗时的操作,假若可以把方法调用直接内嵌到调用者的代码中,可以节省大量的旉Q?q被UCؓ“Method Inlining”。因为涉及到cȝ重蝲Q静态优化很隄切知道哪些属性、方法被重蝲Q因此很隑֯methodq行合ƈQ只好在Ҏ内部q行静态编译,假若每个Ҏ都很,静态优化能起到的作用也比较小。而动态编译因为可以完全随时掌握类的重载情况,可以把相关的方法合q进行深度优化。现代的JavaE序Q特别是在设计模式教育得到普及之后,大量使用cȝl承、委z,形成了很多短的ҎQ动态编译的优势更加明显?br />自从出现了HotSpot之后Q整个Java界ؓ之一振?br />最q的五年Q就是l优化的五年。l进行优化的Ҏ有几条\Q一是研I新的采L法。因为采样关pd不同的优化策略,会对整体性能有比较大的媄响。二是研I深度优化的Ҏ。三是研I垃圾收集的法。垃圾收集会带来E序短暂的停,q会带来负面的用户体验。于是,如何提高垃圾攉的效率,减少延迟Q出C五花八门的算法,比如渐进式收集、火车算法等。在多处理器的时候,如何利用多处理器q行q行攉也是研究的一个热炏V这斚wQBEA的JRocket走在了前面?br />
现实生活中的虚拟?br />最后,让我们来盘点一下目前市面上可见的各个虚拟机?br />首先要提到的Q毫无疑问是Sun的虚拟机。作为大众心目中的“官方实现”,Sun拥有最大的用户,q且拥有“兼容基准”的CQ其他虚拟机都必要考虑和Sun虚拟机的兼容性问题。比?JRocket׃在某些特D情况下表现出和Sun不同的特性,可能对程序运行有影响。不qSun也的没有让q大用户失望Q虽然在早期性能比不上Symantec,后来?.2 的时候性能又被IBM越Q但Sun一直在努力革新Q特别是 1.4.2之后Q性能有了长的进步。虽然JDK 1.5的虚拟机在性能上没有什么提高,但是增强了稳定性,据说修改?000处bugQ真是让人汗不止。原来我们在1.4.2下面一直在享受q么多bug啊?br />其次是老牌劲旅IBM。IBM的JDK?.3的时代创下了最好的性能记录Q从此树立了高端形象。特别是在其WebSphere产品中得C很好的评仗其JDK也是最早支?4bit的JDK之一。到了现在,IBM JDK在高端仍然是和BEA可以一拼的?br />然后是后起之UQBEA的JRocket。说到BEAH然在JVM领域一夜之间异军突P多少让h有些瞠目Q不q它采取的战略特别简单:自己没有Q烦性花׃了在此领域深有研I的JRocketQ在前面加上BEA的标志就可以了。JRocket瞄准高端服务器市场,在多处理器环境下有不俗的表现?br />除此之外Q还有几个开放源代码的JVM值得一提。首先就是大名鼎鼎的JikesRVM。说起其大名Q大多数人都知道Jikes~译器是 IBM开发的Q效率比同等的javac~译器高得多Q很多开发者都使用Jikes~译器来取代javac。而JikesRVM则是IBM开源出来的一整套虚拟机技术,包含了JITQGC的完整实玎ͼ在其|站上也有众多的论文Q实在是惌深入研究JVM者的l佳资源([url]http://jikesrvm.sourceforge.net)[/url]?br />Kaffe是一个老牌的JVM,不过现在已经很少听到了。作者撰写此文时Q[url]www.kaffe.org[/url]|站已经没有响应Q也不知道现在的情况如何了?br />GNU则有两个计划QGCJ和GNU classpath。GNU classpath是一个底层实玎ͼ而GCJ是支持java的预~译器?br />
l束?br />时光{Q蘪轰烈烈的Java虚拟机性能争论仿佛q在而回响Q现在新的争论却已经是“Java的性能是否已经越C/C++”。Joakim Dahlstedt ?JRockit 的主要架构设计师之一Q他坚持认ؓQJaval不是一U速度慢,效率低的语言QJVM 是一个关键的lgQ确保了pȝ的部|与q行和开发一样快速、轻松。特别是在目前开发趋势是采用大量预制的框架时Q动态编译有可能比C/C++q样的静态优化获得更好的性能?br />

J2EE五年: 从v源到目的
?刘天?br />

L
在“J2EE”这个羃略语被第一ơ介l给世h的时刻,也许没有几个人可以预料出它在日后的奇特历E。那是在1999q?月的JavaOneq会上,时QSun公司Java企业开发部门主的Mala Chandra兴奋地预告了Java世界的这位新成员。那些不熟悉背景的听众们Q揣摩着Ҏ说中出现的一串串全新术语Q表情大概又是惊喜、又是迷?一个完整的“多层企业开发架构”、以“容器”和“组件”的形式提供服务、一套“厂商中立的开放技术规范”、对开发者隐藏了不同q_和“中间g”的技术细节、实C企业U应用间的“无~集成”等{。在今天的开发者看来,q些g都已l是老生常谈Q但在当时的场景下,闪动在灯片上的每一个口P都意味着听众们事后又要经历一D困隄学习q程?br />q怺Chandra有一副了不v的口才;q位本科念徏{学的印度裔高层ȝQ谈赯Y件架构来也有特强的空间想象力。她清晰地说明了设计J2EE架构的两个初P首先Q对于厂商,J2EE意味着一套开放标准,加入q个标准Q他们的产品可以运行在各种不同的操作系l和工作环境下,成ؓ一个成熟的企业q算体系中可替换的部Ӟ其次Q对于开发者,J2EE是一套现成的解决ҎQ采用这个方案,企业应用开发中的很多技术难题(包括跨^台移植、事务处理、安全性等{)׃q刃而解Q“信息像一条不间断的河,l过各种各样的^台和讑֤Q从企业应用pȝ的这一端流向那一端”?br />要想理解q段话在当时的实际效应,我们仍然要把旉指针拨回1999q。除了预备迎接千q虫之外Q?9q你做了什么?Z回答q个犀利的问题Q我d6q前的工作记录,发现了自己那时参与的一个项目的规格说明书,它正好能提供一q“Java企业开发”在1999q的标准照。这是一家日本知名IT厂商的企业信息管理系l,q行在NetScape 3.0 Gold览器中的Java Applet界面Q通过一个专用的中间层系l与Oracle 8数据库连接。这个中间层已经相当现成、完善,能够提供q程对象调用、事务处理等一pd的底层服务;留给我们的Q务只是完成服务器端业务对象代码,以及相应的客L交互开发?br />除了Applet客户端有些特别之外,上述pȝ与今天常见的J2EE架构很接q;其是业务对象编码也由homecRPKQ主键)cRentitycȝ部分构成Q很多机刉与EJB如出一辙——只不过q些cdƈ没有l承javax.ejb包的接口Q而是采用了专用的API。它与EJB之间的相g像是偶然的,设计者肯定参照了Sun?997q底推出的EJB 1.0技术规范?br />换言之,在J2EE诞生伊始的语境中Q市面上已经存在着很多E度不一的“准J2EE中间件”了。它们主要用于解决三大类问题Q事务处理、分布式对象理和Webh处理。首先,事务处理理器(Transaction Processing MonitorQ一直是高端企业计算领域的热门品,著名的应用服务器厂商BEAQ正是通过收购事务处理软gTuxedoq入中间件市场的。另一斚wQ从90q代初开始,来多的h把“N层分布式对象架构?当成传统的客L/服务器架构的替代Ҏ。那时刚刚兴LCORBA技术是推动q一势的重要力量(比如_前面提到的那个由日本厂商自行开发的专用中间层,采用了CORBA作ؓ基础架构Q。最后,Java技术在Web领域中的应用也是当时初露头角的热炏V?997q?月,Sun在发布一䏀Java Web Server”的同时W一ơ公布了Servlet APIQ没惛_q项技术副产品Q连?998q问世的JSPQ正好迎合了厂商的战略需要。对于上面提到的N层架构来_HTTP服务是一个非常理想的前端Q所以基于Java的Web引擎Q也在此时成了企业Java解决Ҏ的一个必不可的部分?br />Java、Web、事务、分布式对象Q这几股开发潮汇合在一处,形成了当时最热门的品“应用服务器QApplication ServerQ”或“中间gQMiddlewareQ”。ؓ了给定语“最热门”作个注释,我们可以参照一下BEA公司?998q收购Web应用服务器厂商Weblogic的成交hQ?.92亿美元。而这q不是一桩孤立的收购QNetScape和Sun也以相近的hg下了另外两家企业Kiva和NetDynamics。而这也正是J2EE规范出台的背景:几乎所有要厂商都推Z、或是正在赶制自q应用服务器品,但这个“应用服务器”究竟应该是什么东西,竞争者们又各有表q、莫衷一是?br />说到q里Q我们才梳理ZJ2EE技术规范的W一个版本在1999q?2月问世的实际意义。首先,它ؓJava企业开发提供了一q清晰的全景Q各分支技术在q个领域中的C和作用得C客观、准的定义。至此大家才对一个Java企业解决Ҏ的构成要素有了基本共识。其ơ,它用“容器”和“组件”等概念描绘了Java企业pȝ的一般架构,明确地划分了中间件厂商和应用开发者的职责所在。最后(但绝非最不重要地Q,J2EE通过一套公开标准规定了应用服务器产品的具体行为,在执行此标准的厂商品之间实C一定程度的可替换性和互操作性。当时的媒体用“B2B开发的默认标准”之cȝ说法Ƣ呼q项里程式的成——那些撰Eh哪里知道Q在J2EE与那个被UCؓ“B2B?的短命新贵之_其实q不会有太多故事发生Q同P他们也不会想刎ͼJ2EE要想成ؓ一U真正成熟的开发范式,前方q有一D远辛的旅程?br />
C֌的Ş?br />记得Kruglinski在名著《Inside Visual C++》的某个版本中给Z一个Web览器的代码例子Q在q一节的开头他说到Q如果你几年前开发了一个Web览器,那肯定会l你带来上千万的收益Q但如果你现在才惛_开发这个东襎쀔—那也就是个C++语言的练习Ş了。在今天的程序员gQ应用服务器g也成了hg廉(如果不是全然免费Q的日用消费品。所以,惌理解它们在那几年的大行其道,非得借助Kruglinskiq样的智慧不可。在1999q底Q市面上可以扑ֈ30U以上自U“Java应用服务器”的产品Q可见当时这cY件是|络风险投资的宠ѝ但是此时出台的J2EE规范像是一阵席h个业的劲风Q在一夜之_所有h都有了判断什么是一个“应用服务器”的权威途径?br />Z获得一张J2EE竞技场的入场券,各家厂商面两项考验Q首先,要具有能够覆盖J2EE中所有主要技术的产品Uѝ这在当时是一w常苛ȝ要求Q在没有开源品可供参照的情况下,短时间内推出包括EJB容器、Web引擎和JMS中间件的整体解决ҎQ这决不是随便哪家创业公叔R能办到的。完成了若干ơ成功的q购之后QBEA在这一点上抢占了先机,完整的品线使它成了Z心目中的首选J2EEq_提供商。其ơ,要让产品通过Sun的J2EE兼容性测试。要做到q一点同样不易:pIBM的WebSphere也一时还没达到百分之癄EJB支持。到2000q底为止Q共?5家厂商能够提供完整的J2EE解决ҎQ其?Ӟ包括Sun本nQ实C“J2EE兼容”,他们中间包括了日后这个领域的主要竞争者。毫无疑问,q是一ơ非常残L行业z牌Q但留在场内的厂商也相应地Ş成了推动J2EE发展的主体力量?br />上面说过Q在它的孵化阶段QSun的J2EE团队ȝ是女ZhMala ChandraQ她本h虽不是工E师nQ但Ҏ术有着很强的感知能力和惌力;J2EE一出台p够ؓZ提供一q完整、直观而不失深邃的图景Q此中当然有Chandra本h的大量A献。在她直接领g工作的几位工E师Q也都是Sun内部非常杰出的h才。无论是制定了JDBC、JMS{规范的Mark Hapner、JavaMail的设计者Bill ShannonQ还是EJB的主要设计者Vlada MatenaQ后来都是业界一a九鼎的技术领袖。这个班子的合作旉q不太长Q?000q左右的那个时期正是IT界创业的黄金q月QChandra很快和Sun公司Java部门的总裁Q也是创造Java的功臣之一QAlan Baratz一PC家刚h的Email中间件公司Zaplet淘金MQ捷克裔的开发天才Matena也离开Sun开办了自己的公司。留下的两个人Hapner和Shannon先后担Q了J2EE技术的首席设计师?br />多年以后QHapner回忆起J2EE初创的那个时期,深感如今Sun对Java的左双力已l大不如前:“现在,Java事实上属于整个技术社区,它的发展有赖全体参与者的推动。”的,如今Sun已经不太可能重演当年的开拓性功l,很难再ؓ一个已l成形的领域重绘版图。但正如上文所_即是在1999q_J2EE设计者们面对的也不是一张从未着墨的白纸。他们的设计始终要以各大厂商的现有品ؓ出发点,q也是天才的设计师们做出的设计却q非完美的原因之一Q与从头设计一门全新的~程语言不同QJ2EE规范从一开始就是各方博弈和妥协的物?br />很容易注意到QJ2EE与JavaC֌的决{机制JCPQJava Community ProcessQ是几乎同步产生的。J2EE下属的各U技术规范,包括1.4版之后的J2EE本nQ都作ؓ待决规范议案QJSRQJava Specification RequestQ被U_了JCP的议E。这些议案的审议q程很少是一帆风的Q几乎每一个都要经?8个月以上的拉锯战。在多项技术规范的审议q程中,我们都见Cq样的现象:最初列名审议委员会的某家主要厂商,没能{到该规范通过已l被收购或倒闭了。与微Y?NETq_上的乑ֈ独断相比QJ2EE发展中的q个“牛步”特征虽说是审慎和民ȝ表现Q但l归不符合Y件演化应有的速度?br />J2EEC֌中的另一股重要力量,当然是种cLZ富的开放源代码目?002q以来,在J2EE领域的各个层面上Q几乎所有主品都有来自开源项目的替代ҎQ在其中很多位置上,开源品反而是胜过商业产品的首选。但请别误解Q这里的“开源”ƈ不意味着完全的自动自发,J2EE世界中的开源项目也与Linux或PHP世界颇ؓ不同。在很多非常成功的J2EE开源项目背后,我们都能发现商业机构的推动作用:Apache的JakartaC֌是IBM扶植的结果;实现了开源应用服务器JOnAS的ObjectWebQ则是许多法国IT厂商Q包括若q政府部门)合资支持的一个联盟组l……这些有商业背景的开源项目资金雄厚,人员齐整Q更重要的是Q从投资者到开发者,参与q些目的很多h都体C软g工业中难得的非功利心态,因而最l推出的产品质量甚至高于同类型的商业软g。在L厂商之外Q它们是支撑J2EE大厦存在的一l基矟?br />另一斚wQ不开发者也间接地通过自己的开源品获得了可观的盈利。这些h大多以免费的开源品ؓ依托Q以收费方式提供附加的咨询、方案实施以及技术支持服务。Marc FleuryQ开源应用服务器的JBoss创始人,不无矛盾地把自己倡导的这U商业模式称为“职业开源开发”?br />无论叫它什么,高端产品的开源化/免费化运动注定要在J2EE产业的发展过E中刉显著的后果。“JBoss的行径恶化了J2EE的商业环境,”这是McNealy先生2002q的著名论断。他的推理过E如下:只有做好商业推广QJ2EE产品才能最l击溃邪恶的.NETq_Q但开源服务器会降低主厂商的销售利润;销售利润越低,用于商业推广的预就少Q因此,整个J2EE阵营都将受损于JBoss?br />但在狂热的开源运动支持者看来,以上的大前提是可疑的。“难道只有会做广告的软g才是好YӞMySQL有过多少q告预算”争论的双方都认为对手误解了软g商业模型的实质。究竟谁才掌握了q里的真理呢Q也许只有根据J2EE的未来——也是它的目标和终点(TelosQ——才能做出最l的裁决?br />
技术的d?br />考察事物的演化,通常有两U对立的Ҏ。考古学家QArchaeologistQ探I肇始和hQ目的论者(TeleologistQ则揭示目的和终炏V对于前者,“开端(希腊语ArcheQ”从Ҏ上决定了此后的发展,参天大树的繁茂都包含在种子最初的萌芽中;而对于后者,“目的(TelosQ”才是事物的Ҏ和旨归:谁没见过h完善的树,谁也没法弄懂种子到底是怎么回事?br />在J2EE五年之后Qh们只能交替地用这两种目光审视它的演化历程。它的v源与它的目的、“它从何处来”与“它往何处厠Z?的问题紧密地交织在一P谁拾起了其中的一个,谁也pq同另一个一起回{?br />今天的J2EE在多大程度上W合它的初衷Q回{这个问题ƈ不涉及对J2EE技术成败的评判Q而只是要考察一下:它是否还q行在最初开辟的那个I间之中。在事务处理、对象分布化和Webh处理q三个方面中Q也许J2EE对事务和Web保持了一贯的忠诚。我们记得Fleury喜欢重复的一个信?“He who owns the transactional Web owns the WebQ谁掌握了带事务处理的WebQ谁掌握了WebQ”Web接口是今天大部分J2EE应用暴露的唯一接口Q而虽然事务处理的常用Ҏ已经有了很大改变Q借助AOP机制Q很多非EJB架构的系l也自如地实C声明式的事务处理Q,但对事务的重视当然仍是J2EE开发中的要素之一?br />换言之,?q的演化中,J2EE发生的最大变化可能就在于它放弃了对“分布式对象模型”的。EJB2.0引入的本地接口得Web层与EJB层可以运行在同一个Java虚拟ZQ从而Web容器与EJB容器的物理分部|变成一U昂늚冗余QJ2EE 1.4以后版本支持的Web Services兼容性,使得客户端可以通过_粒度的Web接口调用q程服务——这两次变化事实上都是在“分布式对象架构”的无用性。h们发玎ͼ同一pȝ的各个分层最好采用细_度接口调用Qƈ且运行在同一个进E中Q之所以划分不同的层次Q与其说是ؓ了实现物理上的可扩展性,不如说是设计学上的考虑。而对于异质系l之间的调用Q则应该量选用异步的、粗_度的服务接口(所以Web Services成ؓ了非常理想的选择Q。换句话_传统上的“分布式对象架构”,现在看来g只适合于银行远E支付等要求极ؓ苛刻的应用场景,而绝不是所有J2EE应用都该考虑的标准方案?br />前面描述的离心现象毕竟还遵@了J2EE发展的内在逻辑Q说到底QEJB的革新和Web Services的引入更多地是主厂商倡导的结果。但在近q来Q还有一股更强劲的离心潮在深刻地媄响着J2EE的演q,它肇始于上文提到的开源Y件运动。最初它只在Rickard Oberg的动态代理RMI设计与JBoss服务器的微内核架构中Nq邪恶的一角,但是两三q来Q经q多个项目、各U技术杂?论坛/Blog的折和攑֤Q它已经形成了一个名为“轻量容器架构”的完整解决ҎQƈ暴露出完全取代传lEJB架构的终极野心。按照这一q动信徒们的说法QJ2EE的发展史上只出现q一个错误——不q的是,q个错误名叫EJB。与EJB提供的重量架构不同Q借助AOP和IoC机制Q轻量容器能够最大程度地降低代码对于专用接口的依赖性,以简短、轻ѝ专注、可UL的方式实C务对象。从“轻量容器架构”这个词被发明出来的那一刻vQh们对J2EEq景的考虑发生了Ҏ性的分裂QSun和大部分L厂商更多地关注于“Web Services”和“快速开发工具”这些利润增长点Q而一部分ȝ叛道的独立专家和开发者则认ؓQ如果不把轻量容器U_规划QJ2EE的发展蓝囑ְ注定无U道。其实,双方争执的关键是传统意义上的“应用服务器”的存亡——如果所有企业服务都可以通过AOP机制提供l普通Java对象Q如果管理业务对象生命周期的可以是一个最微不道的“微内核”,那么q重铠的应用服务器q有什么存在理由?而如果失M应用服务器的q个产品cdQ那些靠q项销售v家的厂商又将何以自处Q?br />正是在这里,两个阵营之间存在着最深刻的利益分歧;而这Z执的l局当然也将军_J2EEQ乃至Java企业开发)的最l走向。或怸q之后,我们从U争中胜利者一方的角度重述J2EE的整部历叜y—或怸q之后的J2EE本n也将随着U争的解册成为历双Ӏ但让我们换个乐观的口吻Q问世五q_J2EE的历史仍在持l的创生之中Q此时善待这树种的hQ也必在今后的树荫下获得它的福?br />
Java十年有成
——谈J2ME的发展历?br />?王森


Java本来是Z嵌入式系l而生
1990q?2月,Sun内部由James Gosling、Patrick Naughton以及Mike Sheridan成立了一个叫做Green Team的小l。Green Team组的主要目标,是要发展一U新架构Q而这U架构必能够在消费性电子品作业^Cq行Q现在我们普遍认识的PDA、手机或是信息家?IA)Q都是属于这U架构的目标q_。接着QGreen Team?992q的9?P发表了一ƄJava 技术之?James Gosling所领军研发Q名叫Star Seven(*7)的机器,研发Z部交互式的掌上型家用׃装置Q可透过使用动画触碰式屏q的使用者接口来控制其它电子讑֤?br />l过?3q的旉Q现在我们检视J2ME的发展历Ԍ我们可以发现Q虽然在1999q_Java被切割成J2SE、J2ME、J2EEQ所以有了J2MEq个名词的出现。但是Javaq1999q开始才开始发展嵌入式pȝ上的应用。其实,Java本来是Z嵌入式系l而发展的一U架构。即使目前大家多半将Java的应用聚焦于企业上的J2EE应用。但是严格来_J2ME才是Java真正“回归本心”的领域?br />
半\杀出的Personal Java
Personal Java是正规Java版本的一个分支,其目的在于能够让PDA或高阶手机执行JavaE序Q目前在Windows Mobile或Symbian OS(仅限采用UIQ或Nokia Series 80的行动电?q_上都可以开发Personal Java应用E序?br />虽然从Java 1.0发表之后QJavapq泛C用在桌上型应用程序以及Applet的开发上Q但是,从Java 1.1开始,Java又回C它一开始的老\-也就是嵌入式pȝ斚w的应用,在当时Sun Microsystems发表了Embedded Java与Personal JavaQ也有hUCؓPJavaQ这两项规格。Personal Java的规格是从Java 1.1之中所分支出来Q因此Personal Java的规格是ҎJava 1.1的规D制定的Q但是ƈ非Java 1.1的全部规格都包含q来Q所以Personal Java只能是Java 1.1q_的子集合?br />Personal Java特别适合用在h丰富囑Ş昄能力的消Ҏ电子品上面,于是我们可以发现Sun Microsystems|站上对于Personal Java的参考实作是建立在Windows Mobile产品(q去叫做Pocket PC)上头的?br />?999q_一般PDA或手机的能力Q离Personal Java所需要的g条g仍有很大的一D差距,因此Personal Javaq不是一个很成功的品。因此Sun Microsystems在此时将Java区分成J2SE、J2EE、J2MEq三块,希望可以重新塑造整个架构,其是J2MEQ希望Java可以在嵌入式pȝ的领域有所发展?br />
J2ME从何而来?
谈到J2MEQ大家就会联惛_KVMq个名词Q?KVM的设计者Antero TaivalsaariQ最早在Sun Microsystems参与Spotless ProjectQ这个项目才是J2ME的最早v源。由于Antero Taivalsaari曄在世界知名电信设备制造商工作Q所以他有了在手Z开发JVM的概念,后来得到公司支持Q就有了各位所知的KVM(K Virtual Machine)?br />最早应用KVM的品,是一个可以在Palm OS上执行的KJava。KJavaq不是一个正式品,只能是一个概忉|试品。开发h员会开发名为Spotlet的应用程序,透过工具和KVM的辅助,应用E序可以在PDA上执行。虽然KJava早已成ؓq去式,但是仍有电信厂商使用q个名词Q作为手ZJavaq_的名Uͼ不过Q已l不是真正的KJava了。有了KJava的发展经验,Sun着手设计J2ME的架构,让J2ME可以应付未来嵌入式系l的发展?br />
J2ME整体架构
J2ME最基本的规范制定在JSR-68(Java规格~号W?8?Q在此规格里头定义了J2ME的技术架构。根据此规范QJ2ME׃U类型的规范堆栈而成Q分别是Configuration、Profile以及Optional Packages。这三种cd的规范定义由其它的规范所定义?br />在最底层的Configuration规范Q定义了g所必须具备的能力,比方说硬件至具备多ROM、RAMQCPU的频率最应该是多少Q连接网l时频宽臛_要多快。Configuration规格之中定义了一l低阶的APIQ这代表Java臛_必须提供的低阶功能,q组低阶的API是核心cd函数库的子集合?br />在Configuration之上的规范称为Profile。Profile针对各种不同机器的特性定义了高阶的APIQ这些高阶的API通常都是与其它^C相关的扩充类别函数库。这些高阶API军_了该U机器上JavaE序的撰写方法。比方说行动通讯装置(手机、PDA{?q类型装|上JavaE序的撰写方式,以及能够调用的APIQ都定义在MIDP(Mobile Information Device Profile)之中?br />q是同cd的装|,有些功能也不一定具?有些厂商的机器可能有Q有些厂商的机器可能没有Q例如手Z的照相机、和弦铃声等)Q这些功能就定义在“厂商选择性实现套?Optional Package)”之中,比方_有的厂商会提供简单的数据库管理系l?DBMS)在该装置上,那么他们׃实现JDBC Optional Package。不提供数据库管理系l的厂商׃需要实现JDBC Optional Package。所以称作厂商选择性实现套件?br />所谓的厂商选择性实现套Ӟ意思是_q是一l和其它规格(或API)没有M怾性的cd函数库,如果厂商愿意提供q样的功能给E序设计?通常是因为硬件具有充分的能力可以完成规格之中所制定的功?Q就会将q组cd函数库实现出来,E序设计师也可以利用q些功能开发出功能更多的应用程序?br />
MIDP工业标准
虽然J2ME架构完整Q但是目前的发展Q除了Personal Profile之外Q最大的应用在于架构在CLDC之上的MIDP。目前所有标C可以支持Java的手机,所支持的都是MIDPQ几乎所有的无线通讯厂商皆采用MIDP作ؓ其开发程序的标准?br />在MIDP 1.0的时代,׃规格上本w的功能不Q得许多厂商不得不加入自己专属的APIQ例如震动、背光、声音等扩充功能(例如:Nokia UI API)Q以弥补MIDPq_的不?br />CMIDP 2.0Q增加了许多众所期盼的功能,但是Q即使规格更清楚了,即很多新功能都已经由JCP制定成标准的Optional PackagesQ这些问题依然无解。市面上的MIDPq_仍然处于混ؕ状态。开发者必d执行时期侦测各种专属API和Optional Package的存在,q会增加多余的程序代码。^台的混ؕ会造成在某个装|上可以利安装及执行,而到了其它装|时Q有可能无法执行Q甚x可能q安装都有问题,所以开发者通常要开发好几种版本的MIDP应用E序供各U厂牌、各U型L装置使用?br />Z解决上述问题Q进一步提高MIDP应用E序的可UL性,Sun Microsystems以MIDP 2.0规格为核心,设计了JTWI规格。未来的无线通讯q_Q将不会只有W合MIDP 2.0规格Q而是必须要符合JTWI规格。这是J2ME软g在可UL性上的一大突破。JTWI(Java Technology for Wireless Industry)是一个统合性的规格Q其目的是ؓ了确保MIDP软g的可UL性。所以JTWI规格除了规范无线通讯q_(特别是手?所必须支持的J2ME标准之外Q也Ҏ有规g模糊不清的地方与以加强。所以新Ƅ手机Z加强UL性,都会支持JTWI标准。JTWI只是一个统合性的规范Qƈ没有制定M新功能,目的只是要统一当前q_混ؕ的现象,让J2ME应用E序更具可移植性。JTWI主要分成几个部分:
1 .规定q_必须支持的API?br />2 .l一的应用程序执行环境?br />3 .既有规格的理清与加强?br />在规定^台必L持的API的部分,JTWI规定臛_必须支持CLDC 1.0、MIDP 2.0以及WMA 1.1:

所以,只要厂商宣称支持JTWIq_Q那么代表一定支持CLDC 1.0、MIDP 2.0以及WMA 1.1规格之中的所有功能。另外,厂商可以Ҏ装置本n的能力,CLDC 1.0提升成CLDC 1.1Q可以加入MMAPI 1.1。因此实际上JTWIq_会有一下几U组合方?
其中QCLDC 1.1 + MIDP 2.0 + WMA 1.1 + MMAPI 1.1是最完整、功能最强^台?br />在统一应用E序执行环境斚wQ过去让J2ME应用E序开发者最为头大的问题有以下几?
?应用E序的大可以多?
?执行时期的内存有多少可以使用?
?有多内存空间可以作为永久储存之?
׃规范中对于J2ME应用E序本n的大和执行环境没有很详l地规范Q得每家厂商都有自q规范Q比方说Nokia限制应用E序最大只?0 KBQMotorola则可以支?0 KB以上的应用程序。这些规范都严重地困扰着开发h员。这些问题在JTWI之中都获得改善?br />JTWI定义了应用程序的标准大小(Standard-size Application)。JTWI规定Q可以执行J2ME应用E序的行动通讯装置Q至可以容许大ؓ64 KB以上的程序主?JAR文g)? KB以上的应用程序描q文?JAD文g)、以?0 KB以上的永l储存空间、执行时期的内存(Heap Memory)?56 KB。上q大只是底U,厂商可以视装|的实际能力支持更大的内存空间。标准应用程序大?Standard-size Application)成Z个计用的单位,举例来说Q厂商会说这个装|可以安?0个标准应用程序,开发者所撰写的程序可以说q个E序需要占?个标准应用程序的I间?br />至于Ҏ有规格的理清与加强的部分Q我们将在往后章节一一说明。最重要的一ҎQJTWI规定Q该装置所支持的Q何媒体格?例如囄、声韟뀁媄像等)都应该能够用HTTP 1.1获取Q也是_存取q些媒体时所使用的URL都必能够接受http作ؓ存取的通讯协议?br />

Java开发环境的
q去、现在和来
?EclipseCN


1995q??3日,San Jose Mercury Newsd一题为“Why Sun thinks Hot Java will give you a lift”的文章Q在那篇文章里预aJava技术将是下一个重大事Ӟq个预言现在看来q不仅仅是商家的宣传伎俩Q虽然文章是当时Sun的公关经?Lisa Poulson安排撰写的。从世h知道Java那一刻v到现在,v来已l过L整十q_回顾q去的十q值得ȝ的东西有许多Q但在这里笔者只惛_Java 开发环境谈些个人的x与朋友们交流一下?br />现在的Y件开发h员在整个软g的开发生命周期里Q也怼Ҏ需要用各式各L开发工h完成相对复杂的开发Q务,而在几十q以前,Zq只是用文本编辑器、编译器和Debuggerq行开发,对于q个阶段的开发环境h们称之ؓCLEs(Command Line Environments)?而当Z发现如果那些单独分开的开发工具集成v来就可以有效的提高开发效率时QIDEs(Integrated Development Environments)出C。Java的出现尽只有十q_但其开发环境也大至l历了从CLEs到IDEs再到XDEsq三个阶D,现在卛_q入CDEs阶段。在上述Java开发环境发展过E中Q有许多值得我们大家x的地斏V?br />
Java开发环境的历史回顾
U观q去十年Java开发环境的发展Q大致可以粗略的划分为如下几个阶D?
● ?995Q命令行开发环境CLEs
● ?996-2000Q集成开发环境IDEs
● ?001-2004Q扩展开发环境XDEs
● ?005至今Q协同开发环境CDEs
1995q_不^凡的一q_q一qJava 获得了成功。可令h尬的是?995qƈ没有一个o人满意的Java开发环境,开发h员在q行Java~程Ӟ大多使用文本~辑器编辑源E序Q然后再使用命o行的方式q行~译处理。那时的Java开发环境还处于CLEs时代Q开发效率非怽Q这预示着在Java开发工具上会有一番激烈的竞争?br />有hU?996qؓ互联|年Q有人却UC为Javaq_q有人称之ؓWeb开发年Q但不论如何U呼1996q_它都反映了一个事实:Bill JoyJava与互联网相结合的{略取得了成功。这一q的9月Sun推出了其Java开发环?Java WorkShopQ这是一Ƒ֟于浏览器的Java开发工P但由于当?Java在许多方面还不成熟,所以实际上Java WorkShopq不成功Q同q发布的Symantec Visual Cafe׃q是采用C/C++语言q行开发,所以性能与成熟度上就比WorkShop好得多。提到Visual Cafe׃能不提Eugene WangQ因为Eugene Wang常常是与计算机间谍这个词同时出现的h物,有h甚至讲当时Symantec的老板Gordon Eubanks与Eugene Wang{Ӟ也同时签下了监狱里的一个单元。Visual Cafe是由Eugene Wangq行主要{划的,它是在同一q发布的Java开发环境中Q唯一解决了与数据库连接问题的开发环境,带有一套可以与数据库相q接的组Ӟ无需太多~程使用拖拽的方式就可完成大部分工作Q这一优点使得Visual Cafe受到了Java开发h员的Ƣ迎。这一qIBM收购了OTI公司Q从而得CDave Thomas的弟子John Duimovich、Dave Thomson、Mike Wilson{一大批软g_英Q这之中q包括“生zd技术刀锋上的开发者”Brian Barry?br />1997q_׃微Y垄断案,使得微Y在Java开发环境上的努力受C限制QVisual Cafe׃界面直观易用Q可以很Ҏ地连接各U数据源{功能再ơ受到开发h员的Ƣ迎。这一qIBM发布VisualAge for Java。VisualAge for Java是面向代码库的开发环境,它提供代码库和项目管理以便于开发团队在 C/S环境下进行项目开发。但׃大多数Java开发h员比较熟悉面向文件的开发环境,q不太习惯面向代码库的开发,再加上VisalAge for Java对系l资源的要求比较高等因素Q得VisualAge for Java一开始未被Java开发h员所认可?br />1998q至2000q比较成功的Java开发环境是JBuilderQ这是由于Borland较好的把握住 J2SE、J2EE和J2ME发布后,Java技术升U的时机Q全面支持Java1.1和Java1.2开发^収ͼ它还提供了多U工h便用户从旧的q_q移到新的Javaq_。JBuilder本n80%是基于JDK1.2q行开发的Q它支持JavaBeans, Enterprise JavaBeans, JDBC{方面的应用开发,可以q接多种关系数据库。ؓ支持分布式应用开发,JBuilderq集成了 VisiBroker ORB、JSP server、数据库和EJB AppServerQƈ提供Open Tools API便于W三方工具集成。上q种U的优点使得JBuilder一举超Visual CafeQ成为当时最受欢q的Java开发环境。在众多Java开发环境中Q?999qIBM发布的VisualAge for Java Micro Edition是比较有特色的开发环境,它是由Erich Gamma和与Erich Gamma有“焦不离孟、孟不离焦”之U的John Wiegand共同q行设计的,采用了Java 扩展机制Qƈ集成了JUnit试框架Q其当时所采用的架构深深地影响了后来Eclipse1.0所采用的架构。同Ӟ通过VisualAge for Java Micro Edition的开发,那些来自“未来世界?Smalltalk们总认Z们来自计机的未来世?的Y件精׃Q全面彻底地对Java技术进行了评估Q得Z许多l论性的东西Q这之中包括现在闹得沸沸扬扬的Swing和SWTҎ。此外,Sun其收购的NetBeans变成了开源的Java IDE也是一件不大不的事情?br />U观1996q至2000q这五年旉里,随着Java及其相关开发应用的发展QJava开发环境也不断的完善,从CLEsq入到IDEs阶段。ؓ了提高Java开发h员的开发效率,Java开发环境主要从两个斚wq行改进与提高。一斚w是提高集成在Java IDEs当中开发工L性能和易用性,另一斚w是将Java开发环境尽可能的覆盖到整个软g的开发生命周期。随着ZWEBQ采用N-层结构的应用开发成为Java开发h员主要从事的开发Q务,Java开发环境需要支持越来越多的技术,比如:XML、JSP、EJB和CORBA{,q就造成了Java IDEs的规模变得越来越大,许多Java开发环境都集成了数据库、JSP Server和AppServerQY件的研究人员上qIDEs不断膨胀的现象称为“IDEs大爆炸”?br />“IDEs大爆炸”现象发生以后,有关Java开发环境是走少而精的发展方向,q是走大而全的发展方向就成了q大Java开发h员关注的问题?001qJava开发h员达C200万,成ؓ每个软g供应商都无法忽视的力量,q一qJetBrains推出了Java开发环境少而精的代表: IntelliJ IDEA?IntelliJ IDEA明确的表C只做最好的Java代码~辑器,不做什么文仉可以~写的编辑器。它xJava开发h员的工作实际q将q些工作q行了优化。由于减掉了一些可有可无的工具Q所以hg相对合理公道。当qIntelliJ IDEA击|JBuilder成ؓ最受Java开发h员欢q的Java开发环境,不过2002q随着JBuilder大而全的功力再提升一步,UML建模工具、JUnit试框架以及Apache Struts{开发工具集成进来,大而全的发展方向又一ơ受到Java开发h员追捧。最全还是最好似乎Java开发h员在选择Java开发环境时处于两难状况Q但实际上当Eclipse 1.0发布Ӟq个问题已经得到了初步的解决Q最好和最全是可以兼顾的?br />Eclipse的出C是从天上掉下来的Q也不是某个天才拍脑袋想出来的,它是一Y件精׃集体智慧的结果。早?998qIBM打开发新一代的工具q_以便它现有的各U开发工L一hQƈ减少开发各U工h重复的劳动,同时希望在新的^C建立新的Java开发环境。经q一D|间的准备Q?IBM开始徏立v一个开发团队,人员构成主要来自VisualAge for Java Micro Edition和VisualAge for Java两个目的开发h员,选择的标准是q去10q至开发过5?个IDE。此外,IBMq联合了9家公司共同成立了一个开源组lEclipse基金会,Eclipse提供l开发h员用,q在开源社区的帮助下进一步完善Eclipse本n。Eclipse在最初设计时Q插件模型是静态的Q不能实现插件的x即用功能Q即便是大受Ƣ迎的Eclipse 2.1也还是静态的。所以到2004q发布Eclipse 3.0ӞEclipseq行了重大改q,采用OSGi的插件模型,初步实现了插件的x即用功能Q至此一个完的、可扩展的开发环境展现在Java开发者面前,q时Java开发h员已l达?00万?br />
Java开发环境的现状
2004qEclipse 3.0的发布极大刺Ȁ了Eclipse用户的增长,l过一q以后,Java开发h员现在用Java开发环境的状况是如何的呢?看了下面的表格里的数据也许可以了解一个大致的状况?br />首先需要指明的是上q的数据q不是当前Java用户使用Java开发环境的准确反映Q但我们可以从中了解一个大致的状况。现在的Java环境可以分ؓ三个集团Q第一集团是Eclispe它大U占?/3的䆾额,W二集团?IntelliJ IDEA、NetBeans 和JBuilder占据另外1/3的䆾额,怺之间旗鼓相当Q第三集团是以JDeveloper和WSADZ表的十几UJava开发环境占据剩下的 1/3份额Q但每种开发环境占M额的比重不超q?%。我们考察Eclipse、intelliJ IDEA、NetBeans 和JBuilderq些L开发环境,可以发觉它们有一个共同的特点那就是可扩展Q尽在实现手段上各有不同。这是Z么称现在的Java开发环境ؓXDEs(eXtended Development Environments)的原因,IDEs已经M?q_专业的开发h员需要了解这个事实,因ؓXDEs也快M?br />׃市场的压力,一个Y件企业不仅要提高开发h员个体的工作效率Q还要提高整个开发团队以及整个企业的开发效率,但在现有的Java开发环境XDEs下无法完全做到这些,所以新一代开发环境CDEs (Collaborative Development Environments)׃生。Grady Booch和Alan W. Brown的研I表明一个程序员一天工作时间的分配是这LQ分析占16%(?%?0%不等)Q?设计?4%(?%?0%不等)Q编E占16%(?%?0%不等)Q测试占10%Q打电话?%Q阅d7%(电子邮gQ文档,月刊和杂?Q参加开发会议占10%Q无关的会议?% 。从q些数据可以发现Q开发h员用于交的旉U占工作旉?/3Q开发h员的怺交流非常重要。可是现有的LJava开发环境一般仅分析、设计、编E和试{工具集成进来,却未包括用于交流的工Pq显然不合理。因此,所谓CDEs是用于h与h、h与团队以及团对于团队q行交流的工具集成进来的开发环境,比如QCDEs常具有发送电子邮件、进行及旉讯和屏q分享等功能Q通过实现无损耗过E的交流提高开发团队的开发效率?br />现在已经商业化的CDEs是CodeBeamer Collaborative Development Platform和CodePro AnalytiXQ上qCƾY仉提供Eclipse的插Ӟ可以与Eclipse集成在一P使Eclipse升成ؓ一个CDEs。大家肯定知道Borland已经宣布开发基于Eclipse的新版JBuilder-“Peloton”,Peloton是一个CDEs(Collaborative Development Environments)Q当它明q上半年发布Ӟ意味着Java开发环境进入CDEs时代Q现在Java开发环境还处于XDEs与CDEs交替的阶Dc?

Java开发环境的未来
在可以看得见的将来,Java的开发环境还会是以CDEs的Ş式存在。开源组l或开发工具供应商会努力Y件的开发创Z个绝对光滑的q面 (Frictionless Surface)Q实现无损耗的开发过E,以提高开发效率。ؓ了实现无损耗的开发过E,Java的开发环境将会关注以下几个方?
●  v步阶D|?
●  协作开发方?
●  维护开发团队有效沟通方?
●  多个Q务的旉协调斚w
●  相互协商方?
●  资料有效性方?
但这里必L认未来Java开发环境是如何具体d现无损耗的开发,q需要时间给与答案,因ؓ现在所能采用的Ҏ未必是最好的Q比如,使用面向文g?CVSq行协同开发就有需要改q的地方?br />
ȝ
|里|唆一大堆Q归Uv来不q就?一个目的、三U手D以及一条规律?br />一个目?十年Java开发环境的演变Q其目的是Z提高开发效率?br />三种手段:
●  提高集成在Java开发环境中开发工L性能和易用?
●  将Java开发环境尽可能的覆盖到整个软g的开发生命周?
●  集成h与h、h与团队以及团对于团队q行交流的工?
一条规?软g开发环境的发展q程是从CLEs到IDEs再到XDEs最后进入CDEsQ这是由Grady Boochȝ出来的,套在Java开发环境上也适用?


参考文?br />?Grady Booch and Alan W. Brown, "Collaborative Development Environments",  Advances in Computers 59, Aug. 2003.
?Li-Te Cheng,Cleidson R. B. de Souza,Susanne Hupfer,John Patterson, Steven Ross, "Building Collaboration into IDEs", ACM Queue vol. 1, no. 9 - December/January 2003-2004
?J. des Rivie` res,J. Wiegand, "Eclipse: A platform for integrating development tools", IBM System Journal,Volume 43, Number 2, 2004
?The Java Extension Mechanism.
?Grady Booch, "History of Development Environments", January 29, 20


J2SE发展演变?br />?Matirx JavaC֌ 杨洪波 王志?br />

J2SE:怀?br />Java的历史可以追溯到1991q?月,Sun公司的James Gosling领导的绿色计?Green Project)开始着力发展一U分布式pȝl构Q其能够在各种消费性电子品上q行Q他们用了C/C++/Oak语言。由于多U原因,l色计划逐渐陷于停滞状态?br />直至 1994q下半年Q由于Internet的迅猛发展和环球信息|的快速增长,W一个全球信息网l浏览器Mosaic诞生了;此时Q工业界寚w合在网l异构环境下使用的语a有一U非常急迫的需?Games Gosling军_改变l色计划的发展方向,他们对Oakq行了小规模的改造,pPJava?995q的3?3日诞生了QJava的诞生标志着互联|时代的开始,它能够被应用在全球信息网l的q_上编写互动性及强的AppletE序Q?995q的Applet无疑能给Z无穷的视觉和脑力震荡?br />但没有相应的开发库而只靠Java语言来进行开发肯定是困难重重Q所以Sun公司?996q的1?3日发布了JDK 1.0来帮助开发h员的开发。JDK包括两大部分:q行环境和开发工兗紧跟着QSun公司?997q??8日发布了JDK 1.1。JDK1.1相对于旧版本最大的改进Q是推出了JIT(Just-In-Time)~译器,另外一个改q是AWT 1.1?br />在JDK 1.1时代QJavaq_分ؓPersonalJava与EmbeddedJavaQ前者比较适用于运资源和内存丰富的设备,而资源有限者适用于后者。这L分类明显不符合时代发展的潮流Q所以,Javaq_处处蕴藏着新的d覆地的革命…?br />
J2SE1.2:诞生
JDK 1.2?998q?2?日的隆重发布Q标志着Java2q_的诞生。Java 2的J2SE 1.2时代是一个大变革时代Q它q行了如下的三大革命:

?市场推广革命
Sun公司在Java 1.2版以后将JDK 1.2改名为J2SDKQ将Java改名为Java 2。在1999qSun公司q将Java 2q_分ؓ三大?J2SEQJ2EEQJ2ME。这ơ市场推qK命顺应了|络急速发展的潮流Q对Java 2q_的发展vC很好的催化剂的作用?br />
?API供应标准革命
而随着供应商的不同QJava的API分ؓ三大c?
Java Core API:由Sun公司制定的基本的APIQ所有的Javaq_都应该提供?br />Java Optional API:由Sun公司制定的扩充APIQJavaq_可以有选择地提供?br />ҎAPI:qD厂商或者组l提供的API?br />
?API制定q程的革?br />如果你有需求不能通过遵@标准的API来实?可以向JCP提出制定新的API的请?l过审核,你的h可能被通过或者驳?如果是被通过,则开始进入制定该API的程序?br />J2SE 1.2时代q行的这些革命Ş成的制度一直沿用到现在,对Java技术的发展形成了深q的影响?br />除了上述的三大革命,Java 2q支持ƈ新增了许多新Ҏ,最受追捧的当属Swing库。Swing是轻量的APIQ它不但有各式各样先q的lgQ而且q组仉格都可抽换。Swing出现之后Q大家很快地׃太用AWT了。Java 2q废弃了一些APIQ最重要的莫q于ThreadcM对suspend(),resume()和stop(){方法的废弃。由于JDK 1.1的集合类库中的VectorcdHashTablec都考虑了同步,在^常的使用中媄响效率,所以Java 2专门d了对应的非同步类Qƈ完善了集合类库?br />
J2SE1.3:拓广
Java 2q_推出后,得到了市场的强烈反响Q所以,?000q??日推出的J2SE 1.3对J2SE 1.2的改q,主要是对各种已有API的加强和ҎAPI的拓展?br />数字q算:加入了java.lang.StrictMath,方便我们的一般的数字q算?br />新的Timer API:怿大家对其中的java.util.Timer和java.util.TimerTask一定不陌生?br />Collections?加入了一些新的APIQ方便我们的使用?br />虚拟机停止钩?J2SE 1.3q加入了一个强大的功能Q那是虚拟机停止钩?Virtual Machine Shutdown Hooks)Q这个功能得我们能够在虚拟机停止时完成我们自己的操作,比如关闭|络q接或者保存会话状态或者清除时文件等{?br />DNS服务:在JNDI接口斚wQ加入了一个DNS服务的实现?br />Jini实现:J2SE 1.3包含了一个Jini实现Q这使得我们可以方便地把诸如打印机、摄像机和磁盘驱动设备插入现有网l中Qƈ且能自动搜烦已在|上的设备可以提供的服务qn用这些服务?br />XML支持Q由于计机|络和XML技术的快速发展, J2SE 1.3在Optional API中引入了Java API for XML包?br />HotSpot虚拟?J2SE 1.3引入了HotSpot虚拟机。在Solaris版的JDK 1.3中,已经不支持传l的虚拟机,而Windows版的JDK 1.3同时支持传统虚拟机和HotSpot虚拟机?br />从上面的分析可以看出QJ2SE 1.3主要是对J2SE 1.2查漏补缺和拓展新的API。从应用领域斚w考虑QJ2SE 1.3已经늛了数据库、WEB、多媒体、网l、电话、媄像、加解密、图形等{大部分的信息技术领域?br />在这个时期Java 2q有一个重要活动就是推出SCSL(SunC֌源代码许?许可协议。Sun公司开放源代码目的“女1号”Danese Cooper?999q加入公司,负责SunQ包括JavaQ和开放源代码C֌之间的协调工作。Sun一直尽可能在赢利和开放源代码之间L更好的^衡?br />Java的大行其道引起了Microsoft的警惕ƈ直接D?Net的生,q同时也宣布了Java作ؓ独一无二的Internetq_C的结束。这两个Ҏ在较量中怺学习Q现在在技术架构上的目标上已趋相同?br />
J2SE 1.4:快?br />J2SE 1.4q_的推出发生在2002q??3日,׃此前在Javaq_?NETq_间发生了规模大的孰优孰劣的论战Q而论战中QJavaq_最大的~点是性能问题Q所以J2SE 1.4q_把性能的改善放在了最重要的位|?br />HotSpot虚拟?HotSpot虚拟够很大程度上提高性能Q所以J2SE 1.4已经不支持传l的虚拟机。现在,启动应用E序应该通过-client或?server选项来启动?
锁机?׃旧版的HotSpot虚拟机的锁机制会导制严重的性能和功能问题,J2SE 1.4已经改写了该锁机制?br />安全API:JCE、JSSE和JAASq三大安全API从optional APIUd了core API中。这PJ2SE 1.4的安全域(SecureRandom)实现可以利用操作pȝ提供的安全机Ӟ以便~短应用E序的启动时间?br />RandomAccess标记接口:加入了RandomAccess标记接口Q如果一个List实现了该接口Q则表示它支持快速的随机讉KQ这样可以提高List讉K的速度?br />LinkedHashMap:加入了LinkedHashMapQ这是一个插入排序的Map实现Q但它的q行速度和HashMap一样快?br />反射:很多产品中都要用反?Reflection)机制Q但大家知道Q反是相当耗时的,所以,J2SE 1.4中重写了java.lang.reflect.Field、java.lang.reflect.Method.invoke()、java.lang.reflect.Constructor.newInstance()和Class.newInstance(){方法,使得我们利用反射也能写出高性能的应用程序?br />64位计?J2SE 1.4支持64位计?br />新的I/O API:J2SE 1.4在API层面最大的变动Q就是它更新了原有的java.io包,以及加入了一l更有效率更多功能的New I/O API?br />断言和日志处?J2SE 1.4版本在Java语言层面上加入了断言Qassert关键字)Q在API层面上加入日志处理APIQ这些ؓE序的调试提供了强有力的支持?br />从上面的分析可以看出QJava 2q_在经q数q的发展后,已经比较成熟E_QJ2SE 1.4主要是对q_的性能q行较多的考虑和修攏V在分布式程序方面,1.4版比1.3版的q行效率提高了一半以上;而在客户端程序方面,1.4版比1.3版的效率提高?/3?br />J2SE 1.4版是J2SEW一个参与了 Java共同体过E?JCP)的J2SE版本?像Borland、Compaq、Fujitsu?SAS?Symbian?IBMq样的公司,和Sun一起定义ƈ发展了J2SE 1.4规范。在开放、良好的文档~撰与管理的q程中,形成了一个高质量的、代表了Java共同体的多样性的规范?br />
J2SE5.0:易用
?004q十月J2SE 5.0发布的时候,Sun公司q样解释q次版本名称不是J2SE 1.5而是J2SE 5.0的原因:“从Java诞生至今已有9q时_而从有J2SEv也有5个年头了Q在q样的背境下Q将该版本号?.5改ؓ5.0可以更好的反映出新版的J2SE的成熟度、稳定性、可伸羃性、安全性。?br />J2SE的这ơ变更之重大和意义之pQ的也值得我们Z把版本号变换到J2SE 5.0。我们再看看Sun公司|站对J2SE 5.0的features描述:“通过增强Javaq_的力量,允许开发者更ҎC用,Java~程语言的这些改q将吸引大量各种Java开发者”,q是“Java技术发展历E的一个重要里E碑?。从q个描述我们可以看出QJ2SE 5.0最大的目标是通过提供易用性而吸引各U开发?当然包括以前的C/C++开发? Q而它对以前版本的修改q不仅仅是API的升U,而且包括对Java语言层面的改q,被誉为是”自Java问世以来的最大一ơ语a标准变化”?br />讉K环境变量:最初的Java语言有一个访问环境变量的ҎSystem.getenv()Q但因ؓJava宣称的”Write Once,Run AnyWhere”特性,所以在JDK 1.0中去掉了q个能够讉Kq_专有信息的方法。在J2SE 5.0中,它又来了Qƈ有所扩充。由此可见J2SE 5.0对编E方便性的重视E度?br />泛型:J2SE 5.0提供了强大的泛型机制Q让E序员可以减代码重复,q个变化应该可以吸引部分的C#开发h员吧?br />增强的for循环:Z克服普通for循环的代码臃肿特点,J2SE 5.0提供了增强的for循环Q我们现在可以这样写一个for循环:

public void printAll(Collection coll)
{
for(String str : coll)
{
  System.out.println(str);
}
}

怎么P是不是简单了很多Q?br />自动的装?拆箱:
可变参数数目J2SE 5.0开始支持Varargs(不固定自变量个数)QJ2SE 5.0中还加入了以前抛弃的枚D和C风格的格式化输出Q这应该是ؓ了吸引以前的C开发者吧。毕?在C开发中枚D和格式化输出用的是太多了?br />q发 J2SE 5.0中加入了java.util.concurrent包,q向集合框架中加入了Queue接口QJ2SE 5.0qؓ各种集合提供了ƈ发情况下的实现?br />Propertiescd?׃XML的普及性应用,J2SE 5.0为java.util.Propertiescd入了从XML文g中装载属性和把属性值存储到XML文g中的Ҏ?br />Annotation功能J2SE 5.0提供了注?annotation)/元数据(metadataQ功能,怿以后的大部分应用产品都将充分利用它的注解而实C品的各种Ҏ?br />其它J2SE 5.0q在多线E(q发机制Q、安全、国际化、UI{方面进行了大规模的变更Q得我们能够更方便地进行Java开发?br />其实Q上面的q些变更Qƈ不是我们E序员非要不可的内容。我们完全可以通过自己的办法来辑ֈq些变更实现的功能。但J2SE 5.0的目标就是让我们E序员能够更加方便地q行开发,所以,我们在基于J2SE 5.0开发时Q应该能够明昄体会到它的易用性?br />
展望
时至今日QJ2SE已经发展Z个覆盖面qѝ效率高、易用性强的技术^?见如下的J2SE API体系l构?Q但Javaq没有停止前q的脚步。Mustang版本的J2SE正在紧锣密鼓的开发当中,按以前的惯例Q每两年会发布一个全新的J2SE版本Q所以Mustang开发版对应的J2SE 6.0发布版将?006q完成?br />2005q??3日是Java技术十周年庆典日,在这十年的发展中QJavaq_吸引了四百万开发者,在网l计遍及全球的今天Q更是有17.5亿台讑֤使用了Java技术。作为Java技术的基础QJ2SE的功l不可掩没,我们期望J2SE伴随Javaq_一路走好!

MATRIXC֌介绍:
MatrixQ面向Java爱好者的非赢利性组l。成立以来,Matrix一直不遗余力地为推动中国Java技术和开源Y件的q步和发展而努力,发布了Jasmin反编译器QJmatrix全站pȝ{开源品。加入MatrixQ与JavapQ[url]www.matrix.org.cn[/url]Q?br />
中国企业走近JCP
?黄v?br />
对Java开发h员,JCPQJava Community ProcessQ这个名词ƈ不陌生。但对国内大部分Java开发h员来_JCP更多的是一个符P一个国际Java开发社区的象征。而对JCPq个l织的来源、组成、运作模式以及JCP对中国Y件业,甚至是我们自w工作事业的影响可能不甚了了。由于历史原因、文化语a的差异,国内Java厂商一直未能对JCP引v_重视Q从而导致国内的软g厂商无法参与到JCP的行业标准的制定q程中去Q结果就使我们只能跟随制定好的标准,而不能媄响标准向着有利于国内Y件业的方向发展?br />
跟随的劣势是很明昄Q以万众期待的下一代Java持久化标准EJB 3Z。EJB 3规范目前仍在早期规范阶段Q预计要刎ͼQ0Q年中期才能完成最l版本,但EJB 3专家l中的Java厂商都已l根据讨论的初步意见开始了产品开发,有些甚至开始发布预览版本。而国内的J2EE厂商却可能要{到EJB 3的最l版才可以着手进行研I和开发(Ҏ早期规范不可靠,变动通常很大Q,差距自然巨大。在其他诸如如商业智能、工作流、数据挖掘等领域都存在类似情c?br />
可喜的是国内软g业的Java行业l织和管理部门都已经认识刎ͼl箋徘徊在JCP的门外不利于国内Java产业的生存和发展Q也和国内庞大的软g市场不相W合。在许许多多有志之士Q很多是W者的前辈Q他们ؓ国内软g业发展默默努力,实在让h钦佩Q的共同努力下,JCP的中国分支也卛_成立。而作为第一个尝试,中国的Java应用体验认证实验室在国家应用软g产品质量监督验中心、Sun计算机系l(中国Q有限公司、中国Y件行业协会中间g分会、北京Y件与信息服务业促q中心四单位共同努力下在北京成立Qؓ中国的Java软g厂商在国内进行Y件的JCP认证和兼Ҏ试?br />http://www.souzz.net/bbs/archiver/?tid-49.html

]]>
~译原理学习D(?http://www.aygfsteel.com/Duffblog/articles/64817.htmlq球?/dc:creator>q球?/author>Mon, 21 Aug 2006 08:24:00 GMThttp://www.aygfsteel.com/Duffblog/articles/64817.htmlhttp://www.aygfsteel.com/Duffblog/comments/64817.htmlhttp://www.aygfsteel.com/Duffblog/articles/64817.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/64817.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/64817.html大学评Z?strong>?/strong>开讄译原理呢Q这门课E关注的是编译器斚w的生原理和技术问题,g和计机的基领域不沾边,可是~译原理却一直作为大学本U的必修评Q同时也成ؓ了研I生入学考试的必考内宏V编译原理及技术从本质上来讲就是一个算法问题而已Q当然由于这个问题十分复杂,其解决算法也相对复杂。我们学的数据结构与法分析也是讲算法的Q不q讲的基法Q换句话说讲的是法DQ而编译原理这门课E讲的就是比较专注解决一U的法了。在20世纪50q代Q编译器的编写一直被认ؓ是十分困隄事情Q第一Fortran的编译器据说׃18q的旉才完成。在Z试~写~译器的同时Q诞生了许多跟编译相关的理论和技术,而这些理论和技术比一个实际的~译器本wh值更大。就犹如数学家们在解册名的哥d巴赫猜想一P虽然没有最l解决问题,但是光诞生不少名著的相x论? 推荐参考书 虽然~译理论发展C天,已经有了比较成熟的部分,但是作ؓ一个大学生来说Q要自己写出一个像Turboc C,Java那样的编译器来说q是太难了。不仅写~译器困难,学习~译原理q门评也比较困难? 正是因ؓ~译原理学习相对困难Q那么就要求有好的教师和好的教材。教师方面不是我们能自己更改的,而在教材斚w我们却可以按自己的意愿来阅读。我下面推荐几本好的~译原理的教材。我推荐的书c都是国外的l典教材Q因为在国内的教材中Q确实还没发C么让人满意的? W一本书的原名叫《Compilers Principles,Techniques,and Tools?另外一个响亮的名字是龙书。原因是q本书的面上有条红色的龙,也因为獗臼樵诒嘁朐砘×煊蛉肥堤忻?所以很多国外的学者都直接取名为龙书。最q机械工业出版社已经出版了此书的中文版,名字叫《编译原理》。该书出的比较早Q大概是?5?6q编写完成的Q作者之一q是著名的贝实验室的科学家。里面讲解的核心~译原理至今都没有变q,所以一直到今天Q它的h值都非凡。这本书最大的特点是一开始就通过一个实际的例子,把编译原理的大致内容|列出来Q让很多~译原理的初学者很快心里有了个?也知道ؓ什么会有这些理论,怎么q用q些理论。而这一Ҏ我感觉国内的教材~Z的东西,所以国内的教材都不是写l愿意自学的读者,M让h看了半天Q却不知道里面的东西有什么用? W二本书的原名叫《Modern Compiler Design?中文名字叫做《现代编译程序设计》。该书由人民邮电出版C所出。此书比较关注的是编译原理的实践Q书中给Z不少的实际程序代码,q有很多实际的编译技术问题等{。此书另外一个特点就是其“现代”而字。在传统的编译原理教材中Q你是不可能看到如同Java中的“垃圑֛收”等法的。因为Javaq样的解释执行语a是在q几q才行h的东ѝ如果你x入学习编译原理的理论知识Q那么你肯定得看前面那本龙书Q如果你惌己动手做一个先q的~译器,那么你得看这本《现代编译程序设计》? W三本书是很多国内的编译原理学者都推荐的那本《编译原理及实践》。或许是q本书引入国内比较早吧,我记得我是在高中׃了这本书Q不q也是在前段旉才把整本书看完。此书作为入门教E也的确是个不错的选择。书中给出的~译原理讲解也相当细_虽然不如前面的龙书那么深入,但是很多地方都是点到为止Q作为大学本U教学已l是十分深入了。该书的特点是注重实践Q不q感觉还不如前面那本《现代编译程序设计》的实践味道更重。此书的重点q是在原理上的实践,而非前面那本那样的技术实c《编译原理及实践》在讲解~译原理的各个部分的同时Q也在逐步实践一个现代的~译器Tiny C.{你把整本书看完Q差不多自己也可以写一个Tiny C了。作者还对Lex和Yaccq两个常用的~译相关的工兯行了很详l的说明Q这一点也是很隑֜国内的教材中看到的? 推荐了这三本教材Q都有英文版和中文版的。很多英文好的同学只喜欢看原版的书,不我的感觉是q三本书的翻译都很不错,没有必要特别M英文版的。理解理论的实质比理解表面的文字更ؓ重要? ~译原理的实?/b> 前面已经说过Q学习编译原理其实也是学习法而已Q没什么特别的。只不过q些法的生已lŞ成了一套理论。下面我来看看编译原理里面到底有什么高q理论吧? 几乎每本~译原理的教材都是分成词法分析,语法分析QLL法Q递归下降法QLR法Q,语义分析Q运行时环境Q中间代码,代码生成Q代码优化这些部分。其实现在很多编译原理的教材都是按照85,86出版的那本龙书来安排教学内容的,所以那本龙书的内容格式几乎成了现在~译原理教材的定式,包括国内的教材也是如此。一般来_大学里面的本U教学是不可能把上面的所有部分都认真讲完的,而是比较偏重于前面几个部分。像代码优化那部分东西,像个无底洞一P如果要认真讲Q就是单独开一个学期的课也不可能讲得清楚。所以,一般对于本U生Q对词法分析和语法分析掌握要求就相对要高一点了? 词法分析相对来说比较单。可能是词法分析E序本n实现h很简单吧Q很多没有学q编译原理的Z同样可以写出各种各样的词法分析程序。不q编译原理在讲解词法分析的时候,重点把正则表辑ּ和自动机原理加了q来Q然后以一U十分标准的方式来讲解词法分析程序的产生。这L做法道理很明显,是要让词法分析从程序上升到理论的地步? 语法分析部分比较麻烦一点了。现在一般有两种语法分析法QLL自顶向下法和LR自底向上法。LL法q好_CLR法的时候,困难来了。很多自学编译原理的都是遇到LR法的理解成问题后就攑ּ了自学。其实这些东襉K是只要大家理解就可以了,又不是像词法分析那样非得自己写出来才真正的会。像LR法的语法分析器Q一般都是用工具Yacc来生成,实践中完全没有比较自己来实现。对于LL法中特D的递归下降法Q因为其实践十分单,那么应该要求每个学生都能自己写。当Ӟ现在也有不少好的LL法的语法分析器Q不q要是换在非Cq_Q比如Java,Delphi,你不能运用YACC工具了,那么你就只有自己来写语法分析器? {学到词法分析和语法分析时候,你可能会出现q样的疑问:“词法分析和语法分析到底有什么?”就从编译器的角度来Ԍ~译器需要把E序员写的源E序转换成一U方便处理的数据l构Q抽象语法树或语法树Q?那么q个转换的过E就是通过词法分析和语法分析的。其实词法分析ƈ非一开始就被列入编译器的必备部分,只是我们Z化语法分析的q程Q就把词法分析这U繁琐的工作单独提取出来Q就成了现在的词法分析部分。除了编译器部分Q在其它地方Q词法分析和语法分析也是有用的。比如我们在DOS,Unix,Linux下输入命令的时候,E序如何分析你输入的命o形式Q这也是单的应用。MQ这两部分的工作是把不“规则”的文本信息转换成一U比较好分析好处理的数据l构。那么ؓ什么编译原理的教程都最l把要分析的源分析{换成“树”这U数据结构呢Q数据结构中有Stack, Line,List…这么多数据l构Q各自都有各自的特点。但是Treeq种l构有很强的递归性,也就是说我们可以把Tree的Q何结点Node提取出来后,它依旧是一颗完整的Tree。这一点符合我们现在编译原理分析的形式语言Q比如我们在函数里面使用函树Q@环中使用循环Q条件中使用条g{等Q那么就可以很直观地表示在Treeq种数据l构上。同P我们在执行Ş式语a的程序的时候也是如此的递归性。在~译原理后面的代码生成的部分Q就会介l一U堆栈式的中间代码,我们可以Ҏ分析出来的抽象语法树Q很ҎQ很机械地运用递归遍历抽象语法树就可以生成q种指o代码。而这U代码其实也被广泛运用在其它的解释型语言中。像现在行的Java,.NETQ其底层的字节码bytecode,可以说就是这中基于堆栈的指o代码的? 关于语义分析Q语法制导翻译,cd查等{部分,其实都是一U完善前面得到的抽象语法树的q程。比如说Q我们写C语言E序的时候,都知道,如果把一个QҎ直接赋值给一个整敎ͼ׃出现cd不匹配,那么C语言的编译器是怎么知道的呢Q就是通过q一步的cd查。像C++语言q中支持多态函数的语言Q这部分要处理的问题更多更复杂了。大部编译原理的教材在这部分都是讲解一些比较好的处理策略而已。因为新的问题L在发生,旧的办法不见得够解冟? 本来_作ؓ一个编译器Qv作用的部分就是用戯入的源程序到最l的代码生成。但是在讲解最l代码生成的时候,又不得不讲解机器q行环境{内宏V因为如果你不知道机器是怎么执行最l代码的Q那么你当然无法知道如何生成合适的最l代码。这部分内容我自我感觉其意义甚至过了编译原理本w。因为它会把一个计机的程序的q行q程都通通排在你面前Q你来可能不会从事~译器的开发工作,但是只要是和计算Y件开发相关的领域,都会涉及到程序的执行q程。运行时环境的讲解会让你更清楚一个计机E序是怎么存储Q怎么装蝲Q怎么执行的。关于部分的内容Q我强烈大家看看龙书上的讲解Q作者从最基本的存储组l,存储分配{略Q非局部名字的讉KQ参C递,W号表到动态存储分?malloc,new)都作了十分详l的说明。这些东襉K是我们编写^常程序的时候经常要做的事情Q但是我们却去探求其内部是如何完成?

]]>
Z么SAX|DOM同时存在?(?http://www.aygfsteel.com/Duffblog/articles/64659.htmlq球?/dc:creator>q球?/author>Sun, 20 Aug 2006 13:30:00 GMThttp://www.aygfsteel.com/Duffblog/articles/64659.htmlhttp://www.aygfsteel.com/Duffblog/comments/64659.htmlhttp://www.aygfsteel.com/Duffblog/articles/64659.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/64659.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/64659.html 所以SAX 和 DOM都是Z同样的目的而存?q就是用户可以利用M~程语言讉K存入XML文档中的信息(要有一个那U编E语a的解析器)。虽然他们在提供l你讉K信息的方法上大不相同?/p>

什么是DOM?

DOM 可以让你以分层次对象模型来访问储存在XML文档中的信息。DOM生成一节Ҏ(以XML文档的结构和信息为基)你可以通过q棵树来讉K你的信息。在XML文档中的文本信息转变成一l树的节炏V?br /> 不管你的XML文档中的信息的类型?不管是表格数?或是一列items,或者只是文?, DOM在你创徏一个XML文档的文档对象时创徏一节? 树。 DOM你用树状模?像 Swing TreeModel)去访问你的XML文档中的信息。这U模式确实不错因为XML原本是分层ơ的? q也是DOMZ么可以把你的信息攑ֈ一|中的原因(即信息是表格式的或者简单的列表????q里不知道该怎么d文是Q? even if the information is actually tabular or a simple list??????)?/p>

因ؓ在DOM?每一个元素节点实际上都有一pd的其他节点作为它的孩子。这些孩子节点可以包含文本值或者是其他元素节点。乍看v来,通过遍历讉K一个元 素的所有孩子节Ҏ讉Kq个节点的值是没有必要?举例来说:节点 "<name> Nazmul </name>",  Nazmul是?。如果每个元素只有值的话,q确实是没有必要的。但是,元素可能含有文本数据或者其他元?q是你要在DOM中做额外的工作来获取? 素节点值的原因。 通常当你的文档中只有U数据时,把所有的数据压成一个“块“放到字串中q让DOM把那个字串当成某个特定元素节点的D回是适当的。这 U方式ƈ不适合如果在你的XML文档中的数据是个文档Q比如像WORD文档或者FRAMEMAKER文档Q 在文档中,元素的顺序是非常重要的。对于纯? ?像一个数据库?元素的顺序是不要紧的。 之所以DOM保持从XML文档中读出的元素的顺序,因ؓ它把所有的事物都当成文档来处理。 文档对像模型的 叫法由此而来?/p>

如果你计划用DOM做ؓJAVA对象模型用于你存储在XML文档中的信息Q那么你不需要考虑SAX。可是如果你发现DOM不是一个可以用于处理XML文档 信息的好的对象模式,那么你可能想看看SAX了。在一些必M用自定义对象模型的案例中使用SAX是非常普遍的。说一句让事情看来有些p涂的话Q你也可? 在DOM的基之上创徏自己的对象模式。面向对象真是个好东东?/p>

什么是SAX?

SAX让你讉K储存在XML文档中的信息Q不是通过节点树,而是一pd的事件。你会问Q这有什么益处?回答是,SAX选择不在XML文档上创建JAVA对象模型(像DOM做的那样)。 这样得SAX更快, 同时使下面所q成为必?

创立你自q自定义对像模?br /> 创徏一个监听SAX事g的类同时创徏你自q对象模型
注意q些步骤对DOM而言是不必要的,因ؓDOM已经Z创徏了一个对象模?你的信息用一节Ҏ表示)?/p>

在用DOM的情况下,解析器做了绝大多C? dXML文档, 在这基础之上创徏JAVA对象模型Q然后给你一个对q个对象的引?一?  Document对象)Q因而你可以操作使用它。SAX被叫做Simple API for XML不是没有原因? 她真的很单。 SAX没有期待 解析器去做这么多工作Q所有SAX 要求的是解析器应该读入XML文档,同时Ҏ所遇到的XML文档的标{֏Zpd事g。你要自己写一个XML文档处理 器类QXML document handler classQ来处理q些事g,q意味着使所有标{事件有意义q有用你自己的对象模型创建对象。所以你? 完成:

控制所有XML文档信息的自定义对象模型Q或者源文档在这里的写法从来没有见过Q或者怀疑源文档在这里有排版错误Q先q么MQ?br /> 一个监听SAX事g(事g由SAX解析器读取你的XML文档时?的文档处理器Q还有解释这些事件创Z自定义对象模型中的对?br /> 如果你的对象模型单的话那么SAX在运行时会非常快。在q种情况下,它会比DOM?因ؓ它忽略了Z的信息创Z个树形对象模型的q程。从另一斚w来说Q你必须写一个SAX 文档处理器来解释所有的SAX事g(q会是一件很J重的工??/p>

什么类型的SAX事g被SAX解析器抛Z? q些事g实际上是非常单的。SAX会对每一个开始标{抛Z?Ҏ一个结束标{也是如此。它? #PCDATA和 CDATA 部分同样抛出事g。你的文档处理器 (对这些事件的监听?要解释这些事件同时还要在他们基础之上创徏你自定义的对象模 型。 你的文档处理器必须对这些事件做释,同时q些事g发生的顺序是非常重要的。SAX同时也对processing instructions,  DTDs, comments, 抛出事g. 但是它们在概念上是一L, 你的解析器要解释q些事g(q有q些事g的发生顺?以及使他们有意义?/p>

什么时候用DOM

如果你的XML文档包含文档数据(例如, Framemaker documents stored in XML format), 那么DOM是? 的解x案的最自然选择。如果你要创Z些类g文档信息理的系l,那么你不得不处理大量的文档数据。Datachannel RIO 产品是q么一 个例?它可以烦引和l织各种cd文档资源中的信息(例如Word和Excel 文g)。在q种情况下,DOM是非常合适程序去讉K存贮在这些文档中的信 息的?/p>

然?如果你主要处理的是结构化的数?在XML中的序列化的JAVA对象the equivalent of serialized Java objects in XML)QDOM不是最好的选择。那是SAX会比较合适的地方?/p>

什么时候用SAX

如果在你XML文档中的信息是机器易ȝ(和机器生成的)数据Q那么SAX是让你可以访问这些信息的合适的API。机器易d生成的数据类型包含像下面q些东东:

存成XML格式的Java对象属?br /> 用一些以文本为基的查询语?SQL, XQL, OQL)表示的查?br /> 由查询生成的l果?q也许包含关pd数据库表中的数据~码成XML).
q么看来机器生成的数据是你一般要在java中生成数据结构和cȝ信息。一个简单的例子是包含个Z息的地址,在上图所C。这个地址xml文g不像字处理器文档Q它是一个包含已l被~码成文本的U数据的XML文档?/p>

当你的数据是q种样式Q你要创Z自己的数据结构和c(对象模型Q来理操作以及持箋保存q些数据。SAX容许你快速创Z个可以生成你的对象模型实例的 处理器类。一个实例是Q一个SAX文档处理器。它完成的工作有d包含我的地址薄信息的XML文档Q创Z个可以访问到q些信息的AddressBook cRSAX指南告诉你该怎么做到q些。这个地址薄XML文档包含person元素Qperson元素中有name和email元素。我? AddressBook对象模型包括下面的类Q?/p>

AddressBook c?Person对象的容?br /> Person c?String 型的name和email的容?br /> q样我的“SAX 地址文档处理器”可以把person元素转变成Person对象了,然后把它们都存入AddressBook对象。这个文档处理器name和email元素转变为String对象?/p>
l论

--------------------------------------------------------------------------------

你写的SAX文档处理器(SAX document handlerQ做了将元素映射为对象的工作。如果你的信息被l构化成可以Ҏ创徏q样的映,你应该用SAX API。从另一斚w来说Q如果你的数据更适宜用树来表C那么你应该使用DOM


]]>
用开源实现系l托??http://www.aygfsteel.com/Duffblog/articles/63346.htmlq球?/dc:creator>q球?/author>Sun, 13 Aug 2006 09:49:00 GMThttp://www.aygfsteel.com/Duffblog/articles/63346.htmlhttp://www.aygfsteel.com/Duffblog/comments/63346.htmlhttp://www.aygfsteel.com/Duffblog/articles/63346.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/63346.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/63346.html1.Windows Tray Icon ( http://jeans.studentenweb.org/java/trayicon/trayicon.html )


2.SysTray for Java ( http://systray.sourceforge.net/ )


q两个都是开源的...可以Ҏ上面的下?

相对来说,我更喜欢SysTray for Java,原因很简?SysTray for Java实现了我所要的功能而且相对来说比Windows Tray Icon 要简?

使用SysTray是很单的.下蝲下来的文件有个例子Example.java,照着q个实现你所需要的功能应该不算困难.

主要是菜单和按钮的操?和操作一般的JFrame一?

下面是一个例子程?
         package qiya.systray;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import snoozesoft.systray4j.SysTrayMenu;
import snoozesoft.systray4j.SysTrayMenuEvent;
import snoozesoft.systray4j.SysTrayMenuIcon;
import snoozesoft.systray4j.SysTrayMenuItem;
import snoozesoft.systray4j.SysTrayMenuListener;

public class MainFrame extends JFrame implements ActionListener,
  SysTrayMenuListener {

 static final int INIT_WIDTH = 400;// 默认H口宽度

 static final int INIT_HEIGHT = 244;// 默认H口高度

 private static final String toolTip = "宽带计费接口";// 提示文字

 static final SysTrayMenuIcon icon = new SysTrayMenuIcon("rocket.gif");// 囄信息

 SysTrayMenu menu;// 菜单

 private JButton launchButton = new JButton();// 启动按钮

 private JButton exitButton = new JButton();// 退出按?

 private JLabel statusLabel = new JLabel();// q行状?

 public static void main(String[] args) {
  try {
   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  } catch (InstantiationException e) {
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   e.printStackTrace();
  } catch (UnsupportedLookAndFeelException e) {
   e.printStackTrace();
  }

  new MainFrame();
 }

 public MainFrame() {
  super("宽带计费接口");// 标题
  setIconImage(new ImageIcon(getClass().getResource("rocket.gif"))
    .getImage());// 图标
  this.setLayout(null);
  this.setSize(new Dimension(INIT_WIDTH, INIT_HEIGHT));
  Dimension dimScreen = Toolkit.getDefaultToolkit().getScreenSize();
  int xPos = (dimScreen.width - INIT_WIDTH) / 2;
  int yPos = (dimScreen.height - INIT_HEIGHT) / 2;

  statusLabel.setText("pȝ状态监?);
  statusLabel.setBounds(new Rectangle(45, 35, 280, 40));
  statusLabel.setToolTipText("当前pȝ的运行状?);
  statusLabel.setFont(new Font("宋体", 0, 14));

  launchButton.setText("启动");
  launchButton.setBounds(new Rectangle(80, 180, 80, 23));

  exitButton.setText("退?);
  exitButton.setBounds(new Rectangle(230, 180, 80, 23));

  this.getContentPane().add(statusLabel, null);
  this.getContentPane().add(launchButton, null);
  this.getContentPane().add(exitButton, null);

  launchButton.addActionListener(this);
  exitButton.addActionListener(this);

  this.setBounds(xPos, yPos, INIT_WIDTH, INIT_HEIGHT);

  icon.addSysTrayMenuListener(this);
  this.createMenu();
  this.setVisible(true);
 }

 /**
  * 创徏菜单
  *
  */
 private void createMenu() {
  SysTrayMenuItem subItem1 = new SysTrayMenuItem("退?, "退?);
  subItem1.addSysTrayMenuListener(this);

  SysTrayMenuItem subItem2 = new SysTrayMenuItem("关于", "关于");
  subItem2.addSysTrayMenuListener(this);

  SysTrayMenuItem subItem3 = new SysTrayMenuItem("帮助", "帮助");
  subItem3.addSysTrayMenuListener(this);

  menu = new SysTrayMenu(icon, toolTip);// 生成菜单
  menu.addItem(subItem1);
  menu.addSeparator();
  menu.addItem(subItem2);
  menu.addItem(subItem3);
 }

 /**
  * 点击按钮事g
  */
 public void actionPerformed(ActionEvent e) {
  if (e.getActionCommand().equalsIgnoreCase("退?)) {
   System.exit(0);
  } else if (e.getActionCommand().equalsIgnoreCase("启动")) {
   // 启动计费E序

  }
 }

 /**
  * 菜单选择事g
  */
 public void menuItemSelected(SysTrayMenuEvent e) {
  if (e.getActionCommand().equalsIgnoreCase("退?)) {
   System.exit(0);
  } else if (e.getActionCommand().equalsIgnoreCase("关于")) {
   JOptionPane.showMessageDialog(this, "宽带计费接口" + "完成?005-3-27");
  } else if (e.getActionCommand().equalsIgnoreCase("帮助")) {
   JOptionPane.showMessageDialog(this, "宽带计费接口" + "帮助文g待写...");
  }
 }

 /**
  * 左键单击事g
  */
 public void iconLeftClicked(SysTrayMenuEvent e) {
  if (this.isVisible()) {// 如果可见,最化
   this.setVisible(false);
  } else {// 如果不可见显C出?br />   this.setVisible(true);
  }
 }

 /**
  * 左键双击事g
  */
 public void iconLeftDoubleClicked(SysTrayMenuEvent e) {
  if (this.isVisible()) {// 如果可见,最化
   this.setVisible(false);
  } else {// 如果不可见显C出?br />   this.setVisible(true);
  }
 }
}
       

转自Qhttp://www.xjtublog.com/user1/1034/archives/2006/64310.shtml


]]>
Swt/JFace制做pȝ托盘E序(?http://www.aygfsteel.com/Duffblog/articles/63345.htmlq球?/dc:creator>q球?/author>Sun, 13 Aug 2006 09:48:00 GMThttp://www.aygfsteel.com/Duffblog/articles/63345.htmlhttp://www.aygfsteel.com/Duffblog/comments/63345.htmlhttp://www.aygfsteel.com/Duffblog/articles/63345.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/63345.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/63345.html
  // 取得pȝ托盘对象
 2final Tray tray = shell.getDisplay().getSystemTray();
 3
 4if (tray != null{
 5        // 生成托盘对象
 6        final TrayItem item = new TrayItem(tray, SWT.NONE);
 7        // 为托盘对象添加鼠标停留时的文?/span>
 8        item.setToolTipText(“六月天?;
 9        // 为托盘添加事?/span>
10        item.addListener(SWT.Show, new Listener() {
11                public void handleEvent(Event event) {
12                        System.out.println("show");
13                }

14        }
);
15        item.addListener(SWT.Hide, new Listener() {
16                public void handleEvent(Event event) {
17                        System.out.println("hide");
18                }

19        }
);
20        item.addListener(SWT.Selection, new Listener() {
21                public void handleEvent(Event event) {
22                        System.out.println("selection");
23                }

24        }
);
25        item.addListener(SWT.DefaultSelection, new Listener() {
26                public void handleEvent(Event event) {
27                        System.out.println("default selection");
28                }

29        }
);
30        // 为托盘对象添加显C用的图?/span>
31        item.setImage(image);
32        // 生成菜单?/span>
33        final Menu menu = new Menu(shell, SWT.POP_UP);
34        MenuItem miShow = new MenuItem(menu, SWT.PUSH);
35        miShow.setText("S&how");
36        
37        miShow.addSelectionListener(new SelectionListener() {
38                public void widgetSelected(SelectionEvent arg0) {
39                        shell.setVisible(true);
40                        shell.setMaximized(true);
41                }

42        
43                public void widgetDefaultSelected(SelectionEvent arg0) {
44                }

45        }
);
46        
47        MenuItem miExit = new MenuItem(menu, SWT.PUSH);
48        miExit.setText("E&xit");
49        
50        miExit.addSelectionListener(new SelectionListener() {
51                public void widgetSelected(SelectionEvent arg0) {
52                        exitAction.run();
53                }

54                
55                public void widgetDefaultSelected(SelectionEvent arg0) {
56                }

57        }
);
58        
59        // 为托盘对象添加事Ӟ当右键点d标时Q显C?/span>
60        item.addListener(SWT.MenuDetect, new Listener() {
61                public void handleEvent(Event event) {
62                        menu.setVisible(true);
63                }

64        }
);
65}

ȝQswt/jface为javaE序员提供了快速反映的界面Q由于swt/jface本n也是利用JNI来调用系l的界面Q所以在实现界面的同时也为程序员提供了一些与操作pȝ交互的方法。利用这些方法,可以很方便快捷地完成我们的功能?br />
Eclipse的Forms也非怸错,提供了华丽的界面Q写出来的程序就如同|页一P当然要有一定的审美眼光Q有兴趣的朋友不仿研I研I?br />
转自Qhttp://www.aygfsteel.com/hiswing/archive/2006/08/09/62593.html


]]>
SQLServer和Oracle的常用函数对?/title><link>http://www.aygfsteel.com/Duffblog/articles/55171.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Mon, 26 Jun 2006 08:20:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/55171.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/55171.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/55171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/55171.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/55171.html</trackback:ping><description><![CDATA[ ---------数学函数 <p>  1.l对?<br />  S:select abs(-1) value<br />  O:select abs(-1) value from dual</p><p>  2.取整(? <br />  S:select ceiling(-1.001) value <br />  O:select ceil(-1.001) value from dual</p><p>  3.取整Q小Q?<br />  S:select floor(-1.001) value <br />  O:select floor(-1.001) value from dual</p><p>  4.取整Q截取)<br />  S:select cast(-1.002 as int) value <br />  O:select trunc(-1.002) value from dual </p><p>  5.四舍五入<br />  S:select round(1.23456,4) value 1.23460<br />  O:select round(1.23456,4) value from dual 1.2346</p><p>  6.e为底的幂 <br />  S:select Exp(1) value 2.7182818284590451 <br />  O:select Exp(1) value from dual 2.71828182</p><p>  7.取e为底的对?br />  S:select log(2.7182818284590451) value 1<br />  O:select ln(2.7182818284590451) value from dual; 1</p><p>  8.?0为底Ҏ<br />  S:select log10(10) value 1<br />  O:select log(10,10) value from dual; 1</p><p>  9.取^?br />  S:select SQUARE(4) value 16<br />  O:select power(4,2) value from dual 16</p><p>  10.取^Ҏ<br />  S:select SQRT(4) value 2<br />  O:select SQRT(4) value from dual 2</p><p>  11.求Q意数为底的幂<br />  S:select power(3,4) value 81<br />  O:select power(3,4) value from dual 81</p><p>  12.取随机数<br />  S:select rand() value <br />  O:select sys.dbms_random.value(0,1) value from dual;</p><p>  13.取符?br />  S:select sign(-8) value -1<br />  O:select sign(-8) value from dual -1<br />  ----------数学函数</p><p>  14.圆周?br />  S:SELECT PI() value 3.1415926535897931<br />  O:不知?/p><p>  15.sin,cos,tan 参数都以弧度为单?br />  例如Qselect sin(PI()/2) value 得到1QSQLServerQ?/p><p>  16.Asin,Acos,Atan,Atan2 q回弧度</p><p>  17.弧度角度互换(SQLServerQOracle不知?<br />  DEGREESQ弧?〉角?br />  RADIANSQ角?〉弧?/p><p>  ---------数值间比较</p><p>  18. 求集合最大?br />  S:select max(value) value from <br />  (select 1 value<br />  union<br />  select -2 value<br />  union<br />  select 4 value<br />  union<br />  select 3 value)a</p><p>  O:select greatest(1,-2,4,3) value from dual</p><p>  19. 求集合最?br />  S:select min(value) value from <br />  (select 1 value<br />  union<br />  select -2 value<br />  union<br />  select 4 value<br />  union<br />  select 3 value)a</p><p>  O:select least(1,-2,4,3) value from dual</p><p>  20.如何处理null?F2中的null?0代替)<br />  S:select F1,IsNull(F2,10) value from Tbl<br />  O:select F1,nvl(F2,10) value from Tbl</p><p>  --------数值间比较</p><p>  21.求字W序?br />  S:select ascii('a') value<br />  O:select ascii('a') value from dual</p><p>  22.从序h字符<br />  S:select char(97) value<br />  O:select chr(97) value from dual</p><p>  23.q接<br />  S:select '11'+'22'+'33' value<br />  O:select CONCAT('11','22')||33 value from dual</p><p>  23.子串位置 --q回3<br />  S:select CHARINDEX('s','sdsq',2) value <br />  O:select INSTR('sdsq','s',2) value from dual</p><p>  23.模糊子串的位|?--q回2,参数L中间%则返?<br />  S:select patindex('%d%q%','sdsfasdqe') value <br />  O:oracle没发玎ͼ但是instr可以通过W四N刂瞥鱿执问?BR>  select INSTR('sdsfasdqe','sd',1,2) value from dual q回6</p><p>  24.求子?br />  S:select substring('abcd',2,2) value <br />  O:select substr('abcd',2,2) value from dual</p><p>  25.子串代替 q回aijklmnef<br />  S:SELECT STUFF('abcdef', 2, 3, 'ijklmn') value<br />  O:SELECT Replace('abcdef', 'bcd', 'ijklmn') value from dual</p><p>  26.子串全部替换<br />  S:没发?br />  O:select Translate('fasdbfasegas','fa','? ) value from dual</p><p>  27.长度<br />  S:len,datalength<br />  O:length</p><p>  28.大小写{?lower,upper</p><p>  29.单词首字母大?br />  S:没发?br />  O:select INITCAP('abcd dsaf df') value from dual</p><p>  30.左补I格QLPAD的第一个参CؓI格则同space函数Q?br />  S:select space(10)+'abcd' value<br />  O:select LPAD('abcd',14) value from dual</p><p>  31.双I格QRPAD的第一个参CؓI格则同space函数Q?br />  S:select 'abcd'+space(10) value<br />  O:select RPAD('abcd',14) value from dual</p><p>  32.删除I格<br />  S:ltrim,rtrim<br />  O:ltrim,rtrim,trim</p><p>  33. 重复字符?br />  S:select REPLICATE('abcd',2) value <br />  O:没发?/p><p>  34.发音怼性比?q两个单词返回gP发音相同)<br />  S:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe')<br />  O:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe') from dual<br />  SQLServer中用SELECT DIFFERENCE('Smithers', 'Smythers') 比较soundex的差<br />  q回0-4Q?为同韻I1最?/p><p>  --------------日期函数</p><p>  35.pȝ旉<br />  S:select getdate() value<br />  O:select sysdate value from dual</p><p>  36.前后几日<br />  直接与整数相加减</p><p>  37.求日?br />  S:select convert(char(10),getdate(),20) value<br />  O:select trunc(sysdate) value from dual<br />  select to_char(sysdate,'yyyy-mm-dd') value from dual</p><p>  38.求时?br />  S:select convert(char(8),getdate(),108) value<br />  O:select to_char(sysdate,'hh24:mm:ss') value from dual</p><p>  39.取日期时间的其他部分<br />  S:DATEPART ?DATENAME 函数 Q第一个参数决定) <br />  O:to_char函数 W二个参数决?/p><p>  参数---------------------------------下表需要补?br />  year yy, yyyy <br />  quarter qq, q (季度)<br />  month mm, m (m O无效)<br />  dayofyear dy, y (O表星?<br />  day dd, d (d O无效)<br />  week wk, ww (wk O无效)<br />  weekday dw (O不清?<br />  Hour hh,hh12,hh24 (hh12,hh24 S无效)<br />  minute mi, n (n O无效)<br />  second ss, s (s O无效)<br />  millisecond ms (O无效)<br />  ----------------------------------------------</p><p>  40.当月最后一?br />  S:不知?br />  O:select LAST_DAY(sysdate) value from dual</p><p>  41.本星期的某一天(比如星期日)<br />  S:不知?br />  O:SELECT Next_day(sysdate,7) vaule FROM DUAL;</p><p>  42.字符串{旉<br />  S:可以直接转或者select cast('2004-09-08'as datetime) value<br />  O:SELECT To_date('2004-01-05 22:09:38','yyyy-mm-dd hh24-mi-ss') vaule FROM DUAL;</p><p>  43.求两日期某一部分的差Q比如秒Q?br />  S:select datediff(ss,getdate(),getdate()+12.3) value<br />  O:直接用两个日期相减(比如d1-d2=12.3Q?br />  SELECT (d1-d2)*24*60*60 vaule FROM DUAL;</p><p>  44.Ҏ差值求新的日期Q比如分钟)<br />  S:select dateadd(mi,8,getdate()) value<br />  O:SELECT sysdate+8/60/24 vaule FROM DUAL;</p><p>  45.求不同时区时?br />  S:不知?br />  O:SELECT New_time(sysdate,'ydt','gmt' ) vaule FROM DUAL;</p><p>  -----时区参数,北京在东8区应该是Ydt-------<br />  AST ADT 大西z标准时?br />  BST BDT 白oh准时?br />  CST CDT 中部标准旉<br />  EST EDT 东部标准旉<br />  GMT 格林治标准旉<br />  HST HDT 阿拉斯加—夏威夷标准旉<br />  MST MDT 山区标准旉<br />  NST U芬兰标准时?br />  PST PDT 太^z标准时?br />  YST YDT YUKON标准旉<br />  ---------------------------------------</p><img src ="http://www.aygfsteel.com/Duffblog/aggbug/55171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-06-26 16:20 <a href="http://www.aygfsteel.com/Duffblog/articles/55171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse版本介绍http://www.aygfsteel.com/Duffblog/articles/53621.htmlq球?/dc:creator>q球?/author>Sun, 18 Jun 2006 11:18:00 GMThttp://www.aygfsteel.com/Duffblog/articles/53621.htmlhttp://www.aygfsteel.com/Duffblog/comments/53621.htmlhttp://www.aygfsteel.com/Duffblog/articles/53621.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/53621.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/53621.html 可以?/font> eclipse.org |站 ( http://www.eclipse.org/downloads ) 下蝲Q可以发现『最新』与『最好』的版本Q这两种版本通常不一P基本上有五种版本 或徏|?/font> (build) 可供下蝲Q?/font>

n     释出?/span> (Latest Release builds)  E.g.,3.1.2

               Releases are builds that have been declared major releases by the development team - for example "R1.0". Releases are the right builds for people who want to be on a stable, tested release, and don't need the latest greatest features and improvements. Release builds always have an "R" at the beginning of the name i.e. R1.0, R2.0 etc. Non-release builds are named according to the date of the build - for example 20011027 is the build from Oct 27, 2001.

?span lang="EN-US">Eclipse开发团队所宣称的主要稳定版本?span lang="EN-US">Release buildsl过完整试Qƈh一致性、定义清楚的功?能。它的定位就跟上市的商业软g一栗?/font>

n     E_?/span> (Stream Stable  builds) E.g., 3.2RC7

         Stable builds are integration builds that have been found to be stable enough for most people to use. They are promoted from integration build to stable build by the architecture team after they have been used for a few days and deemed reasonably stable. The latest stable build is the right build for people who want to stay up to date with what is going on in the latest development stream, and don't mind putting up with a few problems n in order to get the latest greatest features and bug fixes. The latest stable build is the one the development team likes people to be using, because of the valuable and timely feedback.

?span lang="EN-US">Release buildCU的版本Q经?span lang="EN-US">Eclipse开发团队测试,q认定它相当E_。新功能通常会在此过渡版本出现。它的定位就跟商业Y件的beta版一栗?/font>

n       整合?/span> (Stream Integration  builds) E.g., I20060614-0843

      Periodically, component teams version off their work in what they believe is a stable, consistent state, and they update the build configuration to indicate that the next integration build should take this version of the component. Integration builds are built from these stable component versions that have been specified by each component team as the best version available. Integration builds may be promoted to stable builds after a few days of testing. Integration builds are built whenever new stable component versions are released into the build.

此版本的各个独立的组件已l过Eclipse开发团队认定具有稳定度Q但不保证集成在一h问题。若集成在一?够稳定,它就有可能晋升成Stable build?/font>

n    当日最新版Q?/span> Stream Nightly  builds) E.g., N20060617-0010

                 Nightly builds are produced every night from whatever has been released into the HEAD stream of the CVS repository. They are completely untested and will almost always have major problems. Many will not work at all. These drops are normally only useful to developers actually working on the Eclipse Project.

此版本显然是从最新的原始码生出来的。可惌知Q此版本当然不保证它跑v来没问题Q搞不好q有严重?span lang="EN-US">bug?/font>

 n   l护?/span> (Stream Maintenance Build) E.g.,. R2_1_maintenance Q?/span> R2.1 or R2.1.2

Maintenance builds are produced periodically to incorporate fixes into an existing release. They are typically built from tagged plug-in and feature pojects in a maintenance stream of the CVS repository (i.e. R2_1_maintenance). Maintenance builds are promoted to a minor or service release (i.e. R2.1 or R2.1.2) after development teams have deemed one to be stable following one or more test-fix pass cycles.



]]>
|络l典命ohttp://www.aygfsteel.com/Duffblog/articles/53619.htmlq球?/dc:creator>q球?/author>Sun, 18 Jun 2006 11:11:00 GMThttp://www.aygfsteel.com/Duffblog/articles/53619.htmlhttp://www.aygfsteel.com/Duffblog/comments/53619.htmlhttp://www.aygfsteel.com/Duffblog/articles/53619.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/53619.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/53619.html 1、测试物理网l?/b>

命oQ?font color="#0000ff">ping 192.168.0.8 Qt Q参敎ͼt是等待用户去中断试

友情提示Q这个是最基本Q最常用的网l命?/p>

2.查看DNS、IP、Mac{信?/b>

A.Win98Q?font color="#0000ff">winipcfg

B.Win2000以上Q?font color="#0000ff">Ipconfig/all

3.|络信

命oQ?font color="#0000ff">Net send 计算机名/IP * (q播) 传送内容,注意不能跨网D?/p>

命oQ?font color="#0000ff">net stop messenger 停止信服务Q也可以在面板-服务修改

命oQ?font color="#0000ff">net start messenger 开始信使服?/p>

4.探测Ҏ计算机名Q所在的l、域及当前用户名 Q追捕的工作原理Q?/font>

命oQ?font color="#0000ff">ping Qa IP Qt Q只昄NetBios?/p>

命oQ?font color="#0000ff">nbtstat -aIP 比较全的

5.netstat -a 昄Z的计机当前所开攄所有端?/font>

命oQ?font color="#0000ff">netstat -s -e 

比较详细的显CZ的网l资料,包括TCP、UDP、ICMP ?IP的统计等

6.探测arpl定Q动态和静态)列表Q显C所有连接了我的计算机,昄ҎIP和MAC地址

命oQ?font color="#ff0000">arp -a

7.在代理服务器?/font>

捆绑IP和MAC地址Q解军_域网内盗用IPQ:

命oQ?font color="#0000ff">ARP Qs 192.168.10.59 00 Q?0QffQ?cQ?8Q?5

解除|卡的IP与MAC地址的绑定:

命oQ?font color="#0000ff">arp -d |卡IP

8.在网l邻居上隐藏你的计算?/font>

命oQ?font color="#0000ff">net config server /hidden:yes

命oQ?font color="#0000ff">net config server /hidden:no 则ؓ开?/p>

9.net命o

A.昄当前工作l服务器列表 net viewQ当不带选项使用本命令时Q它׃昄当前域或|络上的计算Z的列表?/p>

比如Q查看这个IP上的׃n资源Q就可以

C:\>net view 192.168.10.8

?192.168.10.8 的共享资?/p>

资源׃n?cd 用?注释

|站服务 Disk

命o成功完成?/p>

B.查看计算Z的用户帐号列?net user

C.查看|络链接 net use

例如Qnet use z: \192.168.10.8\movie 这个IP的movie׃n目录映射为本地的Z?/p>

D.记录链接 net session

例如: C:\>net session

计算?用户?客户cd 打开I闲旉

\192.168.10.110 ROME Windows 2000 2195 0 00:03:12

\192.168.10.51 ROME Windows 2000 2195 0 00:00:39

命o成功完成?br />

10.路由跟踪命o

A.tracert software.pchome.net

B.pathping software.pchome.net 除了昄路由外,q提?25S的分析,计算丢失包的Q?/p>

11.关于׃n安全的几个命?/b>

A.查看你机器的׃n资源 net share

B.手工删除׃nQ可以编个bat文gQ开q行Q把׃n都删了!Q?/p>

命oQnet share c$ /d

命oQnet share d$ /d

命oQnet share ipc$ /d

命oQnet share admin$ /d

注意$后有I格?/p>

C.增加一个共享:

c:\net share mymovie=e:\downloads\movie /users:1

mymovie ׃n成功?/p>

同时限制链接用户Cؓ1人?/p>

12.在DOS行下讄静态IP

A.讄静态IP

CMD

netsh

netsh>int

interface>ip

interface ip>set add "本地链接" static IP地址 mask gateway

B.查看IP讄

interface ip>show address

Arp

昄和修改“地址解析协议 (ARP)”缓存中的项目。ARP ~存中包含一个或多个表,它们用于存储 IP 地址及其l过解析的以太网或o牌环物理地址。计机上安装的每一个以太网或o牌环|络适配器都有自己单独的表。如果在没有参数的情况下使用Q则 arp 命o显C帮助信息?/p>

]]>win XP命o集锦~~ http://www.aygfsteel.com/Duffblog/articles/53609.htmlq球?/dc:creator>q球?/author>Sun, 18 Jun 2006 09:28:00 GMThttp://www.aygfsteel.com/Duffblog/articles/53609.htmlhttp://www.aygfsteel.com/Duffblog/comments/53609.htmlhttp://www.aygfsteel.com/Duffblog/articles/53609.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/53609.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/53609.htmlq日攉了一些XP的命令,有些很有用,列出来共享~
我找了些Q不知道有没有用处~~
winver---------查Windows版本
wmimgmt.msc----打开windows理体系l构(WMI)
wupdmgr--------windows更新E序
wscript--------windows脚本宿主讄
write----------写字?
winmsd---------pȝ信息
wiaacmgr-------扫描仪和照相机向?
winchat--------XP自带局域网聊天
mem.exe--------昄内存使用情况
Msconfig.exe---pȝ配置实用E序
mplayer2-------易widnows media player
mspaint--------d?
mstsc----------q程桌面q接
mplayer2-------媒体播放?
magnify--------攑֤镜实用程?
mmc------------打开控制?
mobsync--------同步命o
dxdiag---------查DirectX信息
drwtsn32------ pȝȝ
devmgmt.msc--- 讑֤理?
dfrg.msc-------盘片整理E序
diskmgmt.msc---盘理实用E序
dcomcnfg-------打开pȝlg服务
ddeshare-------打开DDE׃n讄
dvdplay--------DVD播放?
net stop messenger-----停止信服务
net start messenger----开始信使服?
notepad--------打开C?
nslookup-------|络理的工具向?
ntbackup-------pȝ备䆾和还?
narrator-------屏幕“讲qCh?
ntmsmgr.msc----Ud存储理?
ntmsoprq.msc---Ud存储理员操作请?
netstat -an----(TC)命o查接?
syncapp--------创徏一个公文包
sysedit--------pȝ配置~辑?
sigverif-------文g{֐验证E序
sndrec32-------录音?
shrpubw--------创徏׃n文g?
secpol.msc-----本地安全{略
syskey---------pȝ加密Q一旦加密就不能解开Q保护windows xppȝ的双重密?
services.msc---本地服务讄
Sndvol32-------音量控制E序
sfc.exe--------pȝ文g查器
sfc /scannow---windows文g保护
tsshutdn-------60U倒计时关机命?
tourstart------xp介(安装完成后出现的漫游xpE序Q?
taskmgr--------d理?
eventvwr-------事g查看?
eudcedit-------造字E序
explorer-------打开资源理?
packager-------对象包装E序
perfmon.msc----计算机性能监测E序
progman--------E序理?
regedit.exe----注册?
rsop.msc-------l策略结果集
regedt32-------注册表编辑器
rononce -p ----15U关?
regsvr32 /u *.dll----停止dll文gq行
regsvr32 /u zipfldr.dll------取消ZIP支持
cmd.exe--------CMD命o提示W?
chkdsk.exe-----Chkdsk盘?
certmgr.msc----证书理实用E序
calc-----------启动计算?
charmap--------启动字符映射?
cliconfg-------SQL SERVER 客户端网l实用程?
Clipbrd--------剪脓板查看器
conf-----------启动netmeeting
compmgmt.msc---计算机管?
cleanmgr-------垃圾整理
ciadv.msc------索引服务E序
osk------------打开屏幕键盘
odbcad32-------ODBC数据源管理器
oobe/msoobe /a----查XP是否Ȁz?
lusrmgr.msc----本机用户和组
logoff---------注销命o
iexpress-------木马捆绑工具Q系l自?
Nslookup-------IP地址侦测?
fsmgmt.msc-----׃n文g夹管理器
utilman--------辅助工具理?
gpedit.msc-----l策?/font>
上面彩色的是常用的(臛_是我常用到的Q?.

觉得有用,记得Ҏ藏哦~~



]]>
cglib的应?http://www.aygfsteel.com/Duffblog/articles/53507.htmlq球?/dc:creator>q球?/author>Sat, 17 Jun 2006 12:30:00 GMThttp://www.aygfsteel.com/Duffblog/articles/53507.htmlhttp://www.aygfsteel.com/Duffblog/comments/53507.htmlhttp://www.aygfsteel.com/Duffblog/articles/53507.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/53507.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/53507.htmlCGLib (Code Generation Library)和ASMQ得Java虽然没有RubyQPython般后生可畏,一栯做出强悍的框架?br />   Proxy可以看作是微型的AOPQ明白提供了在承和委托之外的第三个代码装途径Q只要有_的想象力Q可以做得非常好玩,Spring的源码里用Proxyq得很随便Q看得我非常眼红。可惜Proxy必须Z接口。因此Spring的做法,Z接口的用proxy,否则qcglib。AOP么,一般小事非compoent一U的׃ȝAspectJ出手了?br />
    cglib的Enhancer说v来神奇,用v来一늺不到p完了?br />    它的原理是用Enhancer生成一个原有类的子c,q且讄好callback Q?则原有类的每个方法调用都会{成调用实CMethodInterceptor接口的proxy的intercept() 函数Q?br />
public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy)

 在intercept()函数里,你可以在执行Object result=proxy.invokeSuper(o,args);来执行原有函敎ͼ在执行前后加入自q东西Q改变它的参数|也可以瞒天过P完全q别的。说白了Q就是AOP中的around advice?

    AOP没有出现以前Q该领域l典的设计模式是DecoratorQ像Java IO Stream的设计就是如?不过Q如果ؓ每个DAO, 每个Ҏ的写Decorator函数会写Mh的,所以用上cglib的好处是一ơ过拦截所有方法。?br />
     另外Qcglib除了Enhancer之外Q还有BulkBean和TransformQ都是Hibernate持久化的基础Q但文档贫乏Q一时还没去看怎么用?br />
1.AOP里讲了一N阿一N的log aspect在cglib是这样做?


   
public class LogDAOProxy implements MethodInterceptor
   {
       
private Logger log=Logger.getLogger(AOPInstrumenter.class);
       
private Enhancer enhancer=new Enhancer();
        
//q回DAO的子c?/span>
       public Object getDAO(Class clz)
       {
           enhancer.setSuperclass(clz);
           enhancer.setCallback(
this);
           
return enhancer.create();
       }
       
//默认的拦截方?/span>
      public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable
      {
           log.info(
"调用日志Ҏ"+method.getName());
           Object result
=proxy.invokeSuper(o,args);
           
return result;
      }
   }

    应用的代?
    LogDAOProxy proxy = new LogDAOProxy();
    GoodsDAO  dao 
= (GoodsDAO)proxy.getDAO(GoodsDAO.class);
    dao.insert(goods);

2.而在Spring的管理下应该略加修改的高UDecorator
   上面的例子用return enhancer.create();创徏子类实例Q但在Spring理下,一些Bean的实例必ȝSpring来创建和理Q而不由enhancer来创建的。所以我对上q用法略加修改,使它真正当一个Proxy的角Ԍ请对比黑体字的部?br />

  public class LogDAOProxy implements MethodInterceptor
  {
       
private Logger log=Logger.getLogger(AOPInstrumenter.class);
       
private Object dao=null;
       
private Enhancer enhancer=new Enhancer();
        
//q回DAO的子c?/span>
       public Object getDAO(Class clz,Object dao)
       {
           
this.dao = dao;
           enhancer.setSuperclass(clz);
           enhancer.setCallback(
this);
           
return enhancer.create();
       }      
       
//默认的拦截方?/span>
      public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable
      {
           log.info(
"调用日志Ҏ"+method.getName());
           Object result
=proxy.invoke(dao, args);
           
return result;
      }
  }

有点遗憾, intercept函数里MethodProxy的Signature是固定的 , 卛_户如果调用foo(String),你不可以用proxy.invokeh成foo(String,String);


]]>
վ֩ģ壺 | ¯| Թ| ̨ǰ| | | ̨| | | ϲ| ÷| | Ϫ| | Ĭ| | ϳ| ̽| | | | | | ̫| | ɽ| ī| | ʯ¥| | | Ӧ| ɶ| | | | | ŷ| | | |