posts - 35,  comments - 7,  trackbacks - 0

          隨著Hibernate在Java開發(fā)中的廣泛應(yīng)用,我們在使用Hibernate進(jìn)行對象持久化操作中也遇到了各種各樣的問題。這些問題往往都是我們對Hibernate缺乏了解所致,這里我講個我從前遇到的問題及一些想法,希望能給大家一點(diǎn)借鑒。
          ?
          ???????這是在一次事務(wù)提交時(shí)遇到的異常。
          ???????an?assertion?failure?occured?(this?may?indicate?a?bug?in?Hibernate,?but?is?more?likely?due?to?unsafe?use?of?the?session)
          net.sf.hibernate.AssertionFailure:?possible?nonthreadsafe?access?to?session
          注:非possible?non-threadsafe?access?to?the?session?(那是另外的錯誤,類似但不一樣)
          ?
          ???????這個異常應(yīng)該很多的朋友都遇到過,原因可能各不相同。但所有的異常都應(yīng)該是在flush或者事務(wù)提交的過程中發(fā)生的。這一般由我們在事務(wù)開始至事務(wù)提交的過程中進(jìn)行了不正確的操作導(dǎo)致,也會在多線程同時(shí)操作一個Session時(shí)發(fā)生,這里我們僅僅討論單線程的情況,多線程除了線程同步外基本與此相同。
          ?
          ???????至于具體是什么樣的錯誤操作那?我給大家看一個例子(假設(shè)Hibernate配置正確,為保持代碼簡潔,不引入包及處理任何異常)
          ??

          SessionFactory?sf?=?new?Configuration().configure().buildSessionFactory()?;
          Session?s?=?sf.openSession();
          Cat?cat?=?new?Cat();

          Transaction?tran?=?s.beginTransaction();?(1)
          s.save(cat);?(2)(此處同樣可以為update?delete)
          s.evict(cat);?(3)
          tran.commit();?(4)
          s.close();(5)


          ???????這就是引起此異常的典型錯誤。我當(dāng)時(shí)就遇到了這個異常,檢查代碼時(shí)根本沒感覺到這段代碼出了問題,想當(dāng)然的認(rèn)為在Session上開始一個事務(wù),通過Session將對象存入數(shù)據(jù)庫,再將這個對象從Session上拆離,提交事務(wù),這是一個很正常的流程。如果這里正常的話,那問題一定在別處。
          ?
          ????????問題恰恰就在這里,我的想法也許沒有錯,但是一個錯誤的論據(jù)所引出的觀點(diǎn)永遠(yuǎn)都不可能是正確的。因?yàn)槲乙恢币詾橹苯釉趯?shù)據(jù)庫進(jìn)行操作,忘記了在我與數(shù)據(jù)庫之間隔了一個Hibernate,Hibernate在為我們提供持久化服務(wù)的同時(shí),也改變了我們對數(shù)據(jù)庫的操作方式,這種方式與我們直接的數(shù)據(jù)庫操作有著很多的不同,正因?yàn)槲覀儗@種方式?jīng)]有一個大致的了解造成了我們的應(yīng)用并未得到預(yù)先設(shè)想的結(jié)果。
          ?
          那Hibernate的持久化機(jī)制到底有什么不同那?簡單的說,Hibernate在數(shù)據(jù)庫層之上實(shí)現(xiàn)了一個緩存區(qū),當(dāng)應(yīng)用save或者update一個對象時(shí),Hibernate并未將這個對象實(shí)際的寫入數(shù)據(jù)庫中,而僅僅是在緩存中根據(jù)應(yīng)用的行為做了登記,在真正需要將緩存中的數(shù)據(jù)flush入數(shù)據(jù)庫時(shí)才執(zhí)行先前登記的所有行為。
          ?
          在實(shí)際執(zhí)行的過程中,每個Session是通過幾個映射和集合來維護(hù)所有與該Session建立了關(guān)聯(lián)的對象以及應(yīng)用對這些對象所進(jìn)行的操作的,與我們這次討論有關(guān)的有entityEntries(與Session相關(guān)聯(lián)的對象的映射)、insertions(所有的插入操作集合)、deletions(刪除操作集合)、updates(更新操作集合)。下面我就開始解釋在最開始的例子中,Hibernate到底是怎樣運(yùn)作的。
          (1)生成一個事務(wù)的對象,并標(biāo)記當(dāng)前的Session處于事務(wù)狀態(tài)(注:此時(shí)并未啟動數(shù)據(jù)庫級事務(wù))。
          (2)應(yīng)用使用s.save保存cat對象,這個時(shí)候Session將cat這個對象放入entityEntries,用來標(biāo)記cat已經(jīng)和當(dāng)前的會話建立了關(guān)聯(lián),由于應(yīng)用對cat做了保存的操作,Session還要在insertions中登記應(yīng)用的這個插入行為(行為包括:對象引用、對象id、Session、持久化處理類)。
          (3)s.evict(cat)將cat對象從s會話中拆離,這時(shí)s會從entityEntries中將cat這個對象移出。
          (4)事務(wù)提交,需要將所有緩存flush入數(shù)據(jù)庫,Session啟動一個事務(wù),并按照insert,update,……,delete的順序提交所有之前登記的操作(注意:所有insert執(zhí)行完畢后才會執(zhí)行update,這里的特殊處理也可能會將你的程序搞得一團(tuán)糟,如需要控制操作的執(zhí)行順序,要善于使用flush),現(xiàn)在cat不在entityEntries中,但在執(zhí)行insert的行為時(shí)只需要訪問insertions就足夠了,所以此時(shí)不會有任何的異常。異常出現(xiàn)在插入后通知Session該對象已經(jīng)插入完畢這個步驟上,這個步驟中需要將entityEntries中cat的existsInDatabase標(biāo)志置為true,由于cat并不存在于entityEntries中,此時(shí)Hibernate就認(rèn)為insertions和entityEntries可能因?yàn)榫€程安全的問題產(chǎn)生了不同步(也不知道Hibernate的開發(fā)者是否考慮到例子中的處理方式,如果沒有的話,這也許算是一個bug吧),于是一個net.sf.hibernate.AssertionFailure就被拋出,程序終止。
          ?
          我想現(xiàn)在大家應(yīng)該明白例子中的程序到底哪里有問題了吧,我們的錯誤的認(rèn)為s.save會立即的執(zhí)行,而將cat對象過早的與Session拆離,造成了Session的insertions和entityEntries中內(nèi)容的不同步。所以我們在做此類操作時(shí)一定要清楚Hibernate什么時(shí)候會將數(shù)據(jù)flush入數(shù)據(jù)庫,在未flush之前不要將已進(jìn)行操作的對象從Session上拆離。
          ?
          對于這個錯誤的解決方法是,我們可以在(2)和(3)之間插入一個s.flush()強(qiáng)制Session將緩存中的數(shù)據(jù)flush入數(shù)據(jù)庫(此時(shí)Hibernate會提前啟動事務(wù),將(2)中的save登記的insert語句登記在數(shù)據(jù)庫事務(wù)中,并將所有操作集合清空),這樣在(4)事務(wù)提交時(shí)insertions集合就已經(jīng)是空的了,即使我們拆離了cat也不會有任何的異常了。
          前面簡單的介紹了一下Hibernate的flush機(jī)制和對我們程序可能帶來的影響以及相應(yīng)的解決方法,Hibernate的緩存機(jī)制還會在其他的方面給我們的程序帶來一些意想不到的影響??聪旅娴睦樱?br />??

          (name為cat表的主鍵)
          Cat?cat?=?new?Cat();
          cat.setName(“tom”);
          s.save(cat);

          cat.setName(“mary”);
          s.update(cat);(6)

          Cat?littleCat?=?new?Cat();
          littleCat.setName(“tom”);
          s.save(littleCat);

          s.flush();


          這個例子看起來有什么問題?估計(jì)不了解Hibernate緩存機(jī)制的人多半會說沒有問題,但它也一樣不能按照我們的思路正常運(yùn)行,在flush過程中會產(chǎn)生主鍵沖突,可能你想問:“在save(littleCat)之前不是已經(jīng)更改cat.name并已經(jīng)更新了么?為什么還會發(fā)生主鍵沖突那?”這里的原因就是我在解釋第一個例子時(shí)所提到的緩存flush順序的問題,Hibernate按照insert,update,……,delete的順序提交所有登記的操作,所以你的s.update(cat)雖然在程序中出現(xiàn)在s.save(littleCat)之前,但是在flush的過程中,所有的save都將在update之前執(zhí)行,這就造成了主鍵沖突的發(fā)生。
          ?
          這個例子中的更改方法一樣是在(6)之后加入s.flush()強(qiáng)制Session在保存littleCat之前更新cat的name。這樣在第二次flush時(shí)就只會執(zhí)行s.save(littleCat)這次登記的動作,這樣就不會出現(xiàn)主鍵沖突的狀況。
          ?
          再看一個例子(很奇怪的例子,但是能夠說明問題)

          Cat?cat?=?new?Cat();
          cat.setName(“tom”);
          s.save(cat);?(7)
          s.delete(cat);(8)

          cat.id=null;(9)
          s.save(cat);(10)
          s.flush();

          ?
          這個例子在運(yùn)行時(shí)會產(chǎn)生異常net.sf.hibernate.HibernateException:?identifier?of?an?instance?of?Cat?altered?from?8b818e920a86f038010a86f03a9d0001?to?null
          ?
          這里例子也是有關(guān)于緩存的問題,但是原因稍有不同:
          (7)和(2)的處理相同。
          (8)Session會在deletions中登記這個刪除動作,同時(shí)更新entityEntries中該對象的登記狀態(tài)為DELETED。
          (9)Cat類的標(biāo)識符字段為id,將其置為null便于重新分配id并保存進(jìn)數(shù)據(jù)庫。
          (10)此時(shí)Session會首先在entityEntries查找cat對象是否曾經(jīng)與Session做過關(guān)聯(lián),因?yàn)閏at只改變了屬性值,引用并未改變,所以會取得狀態(tài)為DELETED的那個登記對象。由于第二次保存的對象已經(jīng)在當(dāng)前Session中刪除,save會強(qiáng)制Session將緩存flush才會繼續(xù),flush的過程中首先要執(zhí)行最開始的save動作,在這個save中檢查了cat這個對象的id是否與原來執(zhí)行動作時(shí)的id相同。不幸的是,此時(shí)cat的id被賦為null,異常被拋出,程序終止(此處要注意,我們在以后的開發(fā)過程盡量不要在flush之前改變已經(jīng)進(jìn)行了操作的對象的id)。
          ?
          這個例子中的錯誤也是由于緩存的延時(shí)更新造成的(當(dāng)然,與不正規(guī)的使用Hibernate也有關(guān)系),處理方法有兩種:
          1、在(8)之后flush,這樣就可以保證(10)處save將cat作為一個全新的對象進(jìn)行保存。
          2、刪除(9),這樣第二次save所引起的強(qiáng)制flush可以正常的執(zhí)行,在數(shù)據(jù)庫中插入cat對象后將其刪除,然后繼續(xù)第二次save重新插入cat對象,此時(shí)cat的id仍與從前一致。
          ?
          這兩種方法可以根據(jù)不同的需要來使用,呵呵,總覺得好像是很不正規(guī)的方式來解決問題,但是問題本身也不夠正規(guī),只希望能夠在應(yīng)用開發(fā)中給大家一些幫助,不對的地方也希望各位給與指正。
          ?
            總的來說,由于Hibernate的flush處理機(jī)制,我們在一些復(fù)雜的對象更新和保存的過程中就要考慮數(shù)據(jù)庫操作順序的改變以及延時(shí)flush是否對程序的結(jié)果有影響。如果確實(shí)存在著影響,那就可以在需要保持這種操作順序的位置加入flush強(qiáng)制Hibernate將緩存中記錄的操作flush入數(shù)據(jù)庫,這樣看起來也許不太美觀,但很有效。
          posted @ 2006-05-24 13:47 java小記 閱讀(327) | 評論 (0)編輯 收藏

          ???? public ? static ? void ?main(String[]?args)? throws ?Exception? {?
          ????????System.out.println(isWrapClass(Long.
          class ));?
          ????????System.out.println(isWrapClass(String.
          class ));?
          ????}
          ?

          ????
          public ? static ? boolean ?isWrapClass(Class?clz)? {?
          ????????
          try ? {?
          ????????????
          return ?((Class)?clz.getField( " TYPE " ).get( null )).isPrimitive();?
          ????????}
          ? catch ?(Exception?e)? {?
          ????????????
          return ? false ;?
          ????????}
          ?
          ????}
          ?
          posted @ 2006-05-22 16:44 java小記 閱讀(895) | 評論 (0)編輯 收藏
          <script language="javascript">
          ? g_blnCheckUnload = true;
          ? function RunOnBeforeUnload() {
          ? ?? if (g_blnCheckUnload) {window.event.returnValue = 'You will lose any unsaved content';??
          ??? ?}?
          ? }
          </script>
          <body? onbeforeunload="RunOnBeforeUnload()">
          </body>
          posted @ 2006-05-15 09:27 java小記 閱讀(262) | 評論 (0)編輯 收藏

          ?

          import ?java.io.FileOutputStream;
          import ?java.util.List;

          import ?org.jdom.Attribute;
          import ?org.jdom.Document;
          import ?org.jdom.Element;
          import ?org.jdom.input.SAXBuilder;
          import ?org.jdom.output.Format;
          import ?org.jdom.output.XMLOutputter;

          public ? class ?XML? {
          ????
          public ? static ? void ?main(String[]?args)? throws ?Exception? {

          ????????SAXBuilder?builder?
          = ? new ?SAXBuilder();
          ????????Document?doc?
          = ?builder.build( " d:\\destination.xml " );
          ????????Element?root?
          = ?doc.getRootElement();
          ????????root.removeChild(
          " Target " );
          ????????Element?items?
          = ?root.getChild( " Items " );
          ????????List?item?
          = ?items.getChildren( " item " );
          ????????
          for ?( int ?i? = ? 0 ;?i? < ?item.size();?i ++ )? {
          ????????????Element?elem?
          = ?(Element)?item.get(i);
          ????????????Attribute?attr?
          = ?elem.getAttribute( " displayName " );????????????
          ????????????attr.setValue(attr.getValue()?
          + ? " 中國 " );????????????
          ????????}

          ????????
          // ?保存
          ????????Format?format? = ?Format.getCompactFormat();
          ????????format.setEncoding(
          " gb2312 " );
          ????????format.setIndent(
          " ?? " );
          ????????XMLOutputter?XMLOut?
          = ? new ?XMLOutputter(format);
          ????????XMLOut.output(doc,?
          new ?FileOutputStream( " d:\\destination_tmp.xml " ));

          ????}

          }

          posted @ 2006-05-13 09:22 java小記 閱讀(225) | 評論 (0)編輯 收藏
          STUN (Simple Traversal of UDP through NATs (Network Address Translation)) is a protocol for assisting devices behind a NAT firewall or router with their packet routing.
          • STUN enables a device to find out its public IP address and the type of NAT service its sitting behind.
          • STUN operates on TCP and UDP port 3478.
          • STUN is not widely supported by VOIP devices yet.
          • STUN may use DNS SRV records to find STUN servers attached to a domain. The service name is _stun._udp or _stun._tcp

          Definitions (from the RFC)

          • STUN Client: A STUN client (also just referred to as a client) is an entity that generates STUN requests. A STUN client can execute on an end system, such as a user's PC, or can run in a network element, such as a conferencing server.
          • STUN Server: A STUN Server (also just referred to as a server) is an entity that receives STUN requests, and sends STUN responses. STUN servers are generally attached to the public Internet.

          Various types of NAT (still according to the RFC)
          • Full Cone: A full cone NAT is one where all requests from the same internal IP address and port are mapped to the same external IP address and port. Furthermore, any external host can send a packet to the internal host, by sending a packet to the mapped external address.
          • Restricted Cone: A restricted cone NAT is one where all requests from the same internal IP address and port are mapped to the same external IP address and port. Unlike a full cone NAT, an external host (with IP address X) can send a packet to the internal host only if the internal host had previously sent a packet to IP address X.
          • Port Restricted Cone: A port restricted cone NAT is like a restricted cone NAT, but the restriction includes port numbers. Specifically, an external host can send a packet, with source IP address X and source port P, to the internal host only if the internal host had previously sent a packet to IP address X and port P.
          • Symmetric: A symmetric NAT is one where all requests from the same internal IP address and port, to a specific destination IP address and port, are mapped to the same external IP address and port. If the same host sends a packet with the same source address and port, but to a different destination, a different mapping is used. Furthermore, only the external host that receives a packet can send a UDP packet back to the internal host.
          posted @ 2006-05-12 16:19 java小記 閱讀(323) | 評論 (0)編輯 收藏
          1、密碼由6-32位字母、數(shù)字或下劃線構(gòu)成;
          2、至少需要一位小寫字母;
          3、至少需要一位大寫字母;
          4、至少需要一位數(shù)字。

          String?password?=?"password";
          ????????System.out.println(password?
          !=?null?&&?password.length()?>=?6
          ????????????????
          &&?password.length()?<=?32
          ????????????????
          &&?Pattern.compile("[a-z]+").matcher(password).find()
          ????????????????
          &&?Pattern.compile("[A-Z]+").matcher(password).find()
          ????????????????
          &&?Pattern.compile("[\\d]+").matcher(password).find());
          posted @ 2006-05-10 09:10 java小記 閱讀(409) | 評論 (0)編輯 收藏

          ??
          JList組件有一個單獨(dú)的顯示模式ListModel來表示JList的顯示數(shù)據(jù).??
          JList創(chuàng)建以后,JList數(shù)據(jù)元素的值及數(shù)據(jù)元素的數(shù)量可以動態(tài)地改變.??
          JList在它的數(shù)據(jù)模式ListModel中觀察數(shù)據(jù)的改變.因此,一個ListModel 的正確實(shí)現(xiàn)應(yīng)當(dāng)在每次數(shù)據(jù)發(fā)生改變時(shí),通知事件的監(jiān)聽者.??
          當(dāng)使用構(gòu)造函數(shù)JList(Object[])創(chuàng)建一個JList的實(shí)例時(shí),系統(tǒng)將自動 創(chuàng)建一個DefaultListModel的實(shí)例來存儲JList的顯示數(shù)據(jù), 可以調(diào)用 DefaultListModel中定義的簡便方法來動態(tài)地修改JList的數(shù)據(jù),如 removeElementAt(index),addElement(Object)等. DefaultListModel 在修改數(shù)據(jù)的同時(shí),將通知JList關(guān)于數(shù)據(jù)的改變.??

          ?

          posted @ 2006-04-28 08:28 java小記 閱讀(476) | 評論 (0)編輯 收藏

          ?

          import ?java.awt. * ;
          import ?java.awt.event. * ;
          public ? class ?MyFrame? extends ?Frame {
          {
          public ?MyFrame() {
          ??setSize(
          500 , 400 );
          ??setResizable(?
          false ?);?
          ??
          this .addWindowStateListener( new ?WindowStateListener() { // 狀態(tài)監(jiān)聽器
          ???? public ? void ?windowStateChanged(WindowEvent?e) {
          ??????
          if (getState() == 1 ) { // 最小化狀態(tài)
          ????????setState( 0 ); // 切換成正常狀態(tài)
          ??????}

          ????}

          ??}
          );
          }


          public ? static ? void ?main(String[]?args) {
          ????
          new ?MyFrame().setVisible( true );
          }


          }
          posted @ 2006-04-28 08:28 java小記 閱讀(2711) | 評論 (0)編輯 收藏
          簡而言之:
          Big endian machine: It thinks the first byte it reads is the biggest.
          Little endian machine: It thinks the first byte it reads is the littlest.
          舉個例子,從內(nèi)存地址0x0000開始有以下數(shù)據(jù)
          ?0x0000?????0x12
          ?0x0001?????0x34
          ?0x0002?????0xab
          ?0x0003?????0xcd
          如果我們?nèi)プx取一個地址為0x0000的四個字節(jié)變量,若字節(jié)序?yàn)閎ig-endian,則讀出
          結(jié)果為0x1234abcd;若字節(jié)序位little-endian,則讀出結(jié)果為0xcdab3412.
          如果我們將0x1234abcd寫入到以0x0000開始的內(nèi)存中,則結(jié)果為
          ????????????????big-endian?????little-endian
          0x0000?????0x12??????????????0xcd
          0x0001?????0x23??????????????0xab
          0x0002?????0xab??????????????0x34
          0x0003?????0xcd??????????????0x12
          x86系列CPU都是little-endian的字節(jié)序.
          posted @ 2006-04-25 15:21 java小記 閱讀(330) | 評論 (0)編輯 收藏
          ?VoIP applications like Skype, GoogleTalk and Others

          Internet Voice, also known as Voice over Internet Protocol (VoIP), is a technology that allows you to make telephone calls using a broadband Internet connection instead of a regular (or analog) phone line. Some services using VoIP may only allow you to call other people using the same service, but others may allow you to call anyone who has a telephone number - including local, long distance, mobile, and international numbers. Also, while some services only work over your computer or a special VoIP phone, other services allow you to use a traditional phone through an adaptor.
          posted @ 2006-04-05 09:59 java小記 閱讀(269) | 評論 (1)編輯 收藏
          import ?java.security.MessageDigest;
          import ?java.security.NoSuchAlgorithmException;
          public ? class ?PasswordManager? {
          ????
          ????
          // ***************************************************************
          ????
          // ?Public?Interface
          ????
          // ***************************************************************

          ????
          /**
          ?????*?Creates?a?one-way?has?of?the?specified?password.??This?allows?passwords?to?be
          ?????*?safely?stored?in?the?database?without?any?way?to?retrieve?the?original?value.
          ?????*?
          ?????*?
          @param ?password?the?string?to?encrypt.
          ?????*?
          ?????*?
          @return ?the?encrypted?password,?or?null?if?encryption?failed.
          ?????
          */

          ????
          public ? static ?String?encryptPassword(?String?password?)? {
          ????????
          ????????
          try ? {
          ????????????MessageDigest?md?
          = ?MessageDigest.getInstance( " SHA " );
          ????????
          ????????????
          // Create?the?encrypted?Byte[]
          ????????????md.update(?password.getBytes()?);
          ????????????
          byte []?hash? = ?md.digest();
          ????????????
          ????????????
          // Convert?the?byte?array?into?a?String
          ????????????
          ????????????StringBuffer?hashStringBuf?
          = ? new ?StringBuffer();
          ????????????String?byteString;
          ????????????
          int ?byteLength;
          ????????????
          ????????????
          for (? int ?index? = ? 0 ;?index? < ?hash.length;?index ++ ?)? {
          ????????????????
          ????????????????byteString?
          = ?String.valueOf(?hash[index?]? + ? 128 ?);
          ????????????????
          ????????????????
          // Pad?string?to?3.??Otherwise?hash?may?not?be?unique.
          ????????????????byteLength? = ?byteString.length();
          ????????????????
          switch (?byteLength?)? {
          ????????????????
          case ? 1 :
          ????????????????????byteString?
          = ? " 00 " ? + ?byteString;
          ????????????????????
          break ;
          ????????????????
          case ? 2 :
          ????????????????????byteString?
          = ? " 0 " ? + ?byteString;
          ????????????????????
          break ;
          ????????????????}

          ????????????????hashStringBuf.append(?byteString?);
          ????????????}

          ????????????
          ????????????
          return ?hashStringBuf.toString();
          ????????}

          ????????
          catch (?NoSuchAlgorithmException?nsae?)? {
          ????????????System.out.println(?
          " Error?getting?password?hash?-? " ? + ?nsae.getMessage()?);
          ????????????
          return ? null ;
          ????????}

          ????}

          }
          posted @ 2006-03-28 15:45 java小記 閱讀(275) | 評論 (0)編輯 收藏
          偶爾eclipse3.1的web項(xiàng)目有時(shí)候不能自動編譯/WEB-INF/src,即使選擇工程的自動編譯開關(guān)也不好使,不知道是不是Bug
          我這樣解決的:
          1. project->properties->java build path->source->.../WEB-INF/src的output folder不要默認(rèn),編輯讓它指向../WEB-INF/classes
          然后重新點(diǎn)擊build工程即可自動編譯。

          2. 再就是最重要的要看工程下面是否缺少了work目錄,由于CVS控制時(shí)不把work加如版本,所以checkout后沒有這個目錄,要手工加上有的工程就能自動編譯了
          posted @ 2006-03-21 10:50 java小記 閱讀(1320) | 評論 (0)編輯 收藏
          XP系統(tǒng)一般情況下在裝完系統(tǒng)后會有一個計(jì)算機(jī)管理員權(quán)限的用戶,以后登陸時(shí)就顯示這個用戶
          進(jìn)入系統(tǒng)后在控制面板中的用戶帳號下看不到Administrator用戶,就好象丟失了一樣,如何看到呢?
          里面有另外一個問題涉及XP自動登陸                                      
          單擊"開始/運(yùn)行",輸入"rundll32 netplwiz.dll,UsersRunDll",按回車鍵后彈出“用戶帳戶”窗口,
          這和“控制面板”中打開的“用戶賬戶”窗口不同!
          然后取消選定"要使用本機(jī),用戶必須輸入用戶名和密碼"選項(xiàng),單擊確定.
          在彈出的對話框中輸入你想讓電腦每次自動登錄的賬戶(默認(rèn)Administrator)和密碼即可。
          下一次開機(jī)自動用Administrator登陸到系統(tǒng),再看控制面板就有了Administrator。
          Xp默認(rèn)把Administrator隱藏,雖然都是計(jì)算機(jī)管理員Administrator和有計(jì)算機(jī)管理員權(quán)限的用戶還是有
          細(xì)微差別的。但是一般情況下使用系統(tǒng)用計(jì)算機(jī)管理員權(quán)限的用戶就足夠了
          posted @ 2006-02-13 21:40 java小記 閱讀(5288) | 評論 (3)編輯 收藏


          安全域是Tomcat的內(nèi)置功能,主要有以下幾種安全域:
          JDBCRealm
          DataSourceRealm
          JNDIRealm
          MemoryRealm
          JAASRealm

          在conf/server.xml中配置應(yīng)用的<Context......>下面的<Realm className="org.apache.catalina.realm.MemoryRealm" />
          從一個XML文件中讀取用戶信息,默認(rèn)的就是tomcat-users.xml

          tomcat-users.xml中的角色定義
          <?xml version='1.0' encoding='utf-8'?>
          <tomcat-users> 
              <role rolename="tomcat"/> 
              <role rolename="role1"/> 
              <role rolename="guest"/>
              <user username="lee" password="lee" roles="guest"/>
              <user username="suoxin" password="suoxin" roles="tomcat,role1"/>
          </tomcat-users>

          在應(yīng)用下的web.xml中加入<security-constraint>元素
          <security-constraint>  
              <web-resource-collection>
                   <url-pattern>/*</url-pattern>   
              </web-resource-collection>   
              <auth-constraint>    
                   <role-name>admin</role-name>   
                   <role-name>guest</role-name>  
              </auth-constraint>
          </security-constraint>

          在應(yīng)用下的web.xml中加入<login-config>元素
          <login-config>     
             <auth-method>FORM</auth-method>
             <!--這里FORM是基于表單的驗(yàn)證,會跳轉(zhuǎn)到mylogin.jsp,如果出錯就到myerror.jsp,
             還有基于對話筐的是BASIC關(guān)鍵字,但是不安全在網(wǎng)絡(luò)傳輸中。摘要驗(yàn)證DIGEST會采
             用MD5(Message Digest Algorithm)加密傳輸-->
             <form-login-config>       
                <form-login-page>/mylogin.jsp</form-login-page>       
                <form-error-page>/myerror.jsp</form-error-page>     
             </form-login-config>
          </login-config>

          mylogin.jsp的action和name必須嚴(yán)格規(guī)范寫
          <form name="form1" id="form1" method="post" action="j_security_check"> 
             <input type="text" name="j_username"/> 
             <input type="text" name="j_password"/>
             <input type="submit" name="Submit" value="提交" />
          </form>

           

          posted @ 2006-02-11 09:11 java小記 閱讀(221) | 評論 (0)編輯 收藏
           
            1,下載OSCache, oscache-2.2-full.zip
            2,解壓縮oscache-2.2-full.zip后把oscache-2.2.jar拷貝到應(yīng)用的WEB-INF/lib下 ,
               并把etc目下下的oscache.properties拷貝到應(yīng)用的WEB-INF/classes下.
            3, 在應(yīng)用的web.xml中加入緩存過濾器    
              
                 <filter>
                     
          <filter-name>CacheFilter</filter-name>
                     
          <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
                     
          <init-param>
                         
          <param-name>time</param-name>
                         
          <param-value>600</param-value>
                     
          </init-param>
                     
          <init-param>
                         
          <param-name>scope</param-name>
                         
          <param-value>application</param-value>
                     
          </init-param>
                 
          </filter>
                 
                 
          <filter-mapping>
                     
          <filter-name>CacheFilter</filter-name>
                     
          <url-pattern>/servlets/UserAllProducts</url-pattern>
                 
          </filter-mapping>

            以上的/servlets/UserAllProducts訪問需要操作數(shù)據(jù)庫,并且這些內(nèi)容一段時(shí)間內(nèi)很少改變,這樣在內(nèi)存緩存這個URL很有必要
            它可以降低數(shù)據(jù)庫訪問量。
           
            經(jīng)過以上配置后,當(dāng)?shù)谝淮卧L問/servlets/UserAllProducts時(shí),從數(shù)據(jù)庫中查出所有產(chǎn)品列表并緩存到application中600秒。
            在600秒內(nèi)的任何訪問/servlets/UserAllProducts都不會真正執(zhí)行這個servlet,而直接從application中取出緩存的內(nèi)容。這樣
            就減少了數(shù)據(jù)庫的訪問量。
          posted @ 2006-02-09 18:58 java小記 閱讀(291) | 評論 (0)編輯 收藏

          今天遇到了這樣的問題,就是浮點(diǎn)運(yùn)算后數(shù)據(jù)比較出現(xiàn)錯誤,郁悶了半天,網(wǎng)上查了資料才發(fā)現(xiàn)浮點(diǎn)數(shù)直接用雙目運(yùn)算符連接會出現(xiàn)結(jié)果不準(zhǔn)確問題。解決方法如下:
          1。所有浮點(diǎn)運(yùn)算都在數(shù)據(jù)庫內(nèi)做好,也就是都用sql實(shí)現(xiàn)了
          2。用BigDecimal實(shí)現(xiàn),方法如下(僅僅是個例子):

          import java.math.BigDecimal;

          public class tt {

           
          /**
            * 
          @param args
            
          */

           
          public static void main(String[] args) {
            
          float a = 1.1f;
            
          float b = 2.2f;
            tt t 
          = new tt();
            System.out.println(t.add(a,b));
            System.out.println(t.sub(a,b));
            System.out.println(t.mul(a,b));
            System.out.println(t.div(a,b));
            System.out.println(t.round(a));

           }

           
          public float add(float v1,float v2){//加法
             BigDecimal b1 = new BigDecimal(Float.toString(v1));
             BigDecimal b2 
          = new BigDecimal(Float.toString(v2));
             
          return b1.add(b2).floatValue();
            }


            
          public float sub(float v1,float v2){//減法
             BigDecimal b1 = new BigDecimal(Float.toString(v1));
             BigDecimal b2 
          = new BigDecimal(Float.toString(v2));
             
          return b1.subtract(b2).floatValue();
            }


            
          public float mul(float v1,float v2){//乘法
             BigDecimal b1 = new BigDecimal(Float.toString(v1));
             BigDecimal b2 
          = new BigDecimal(Float.toString(v2));
             
          return b1.multiply(b2).floatValue();
            }


            
          public float div(float v1,float v2){//除法
             BigDecimal b1 = new BigDecimal(Float.toString(v1));
             BigDecimal b2 
          = new BigDecimal(Float.toString(v2));
             
          return b1.divide(b2,3,BigDecimal.ROUND_HALF_UP).floatValue();
            }


            
          public float round(float v){//截取3位
             BigDecimal b = new BigDecimal(Float.toString(v));
             BigDecimal one 
          = new BigDecimal("1");
             
          return b.divide(one,3,BigDecimal.ROUND_HALF_UP).floatValue();
            }

          }

          posted @ 2006-02-08 16:43 java小記 閱讀(277) | 評論 (0)編輯 收藏

          spring配置中bean的循環(huán)引用問題及解決方法

          問題:Spring+Hibernate的應(yīng)用中,定義了兩個業(yè)務(wù)Service,這里分別稱它們?yōu)閟erivceA,ServiceB。
          它們的關(guān)系簡單點(diǎn)來說是這樣的:
          serviceA需要引用serviceB,在serviceB中定義了一個接口列表,serverA必須在serviceB初始化時(shí)設(shè)置進(jìn)列表。
          在純bean的情況下,也就是這兩個類不需要設(shè)置其他bean的情況下,循環(huán)引用是正常的,可以通過的。例如下面配置所表示:

              <bean id="serviceA" class="A"  autowire="byName"  lazy-init="true">
               <property name="serviceB"><ref local="serviceB"/></property>
              </bean>
           <bean id="serviceB" class="B"  autowire="byName"  lazy-init="true">
               <property name="serviceA"><ref bean="serviceA"/></property>
           </bean>
          但是作為一個業(yè)務(wù)接口,它應(yīng)該是不需要關(guān)心事務(wù),回滾這些無關(guān)的東西,
          但現(xiàn)實(shí)又有這樣的需求,所以我們必須保證透明的實(shí)現(xiàn)這個功能,于是引
          入了AOP方式解決該問題,利用的是Spring自帶的org.springframework.t
          ransaction.interceptor.TransactionProxyFactoryBean.
          重新聲明文件如下:
             <bean id="baseTxProxy" lazy-init="true"
                class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                  <property name="proxyTargetClass"><value>true</value></property>
                  <property name="transactionAttributes">
                      <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
                      </props>
                  </property>
              </bean>
               
              <bean id="serviceA" parent="baseTxProxy">
               <property name="target"><ref local="serviceAImpl"/></property>
              </bean>
             
             <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
               <property name="serviceB">
                   <ref bean="serviceB"/>
               </property>
             </bean>
             
              <bean id="serviceB" parent="baseTxProxy" lazy-init="true">
               <property name="target"><ref local="serviceBImpl"/></property>
              </bean>
            
             <bean id="serviceBImpl" class="D" lazy-init="true">
               <property name="serviceA">
                   <ref bean="serviceA"/>
               </property>
             </bean>
          于是問題就出現(xiàn)了,Spring報(bào)了FactoryBeanCircularReferenceException,無法繼續(xù)完成設(shè)置工作。
          查看TransactionProxyFactoryBean源碼,其實(shí)現(xiàn)了FactoryBean和InitializingBean接口,應(yīng)該是
          做了代理之后,兩個代理Bean需要等待所有Bean設(shè)置完成后才會標(biāo)識狀態(tài)為初始化完畢,于是造成了
          沖突。

              由于兩個業(yè)務(wù)服務(wù)互相調(diào)用的路徑是不相交的,所以采用了一種變通的方法,在聲明serviceA時(shí),
          直接定義serviceB:
            <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
               <property name="serviceB">
                   <bean class="B"  autowire="byName"/>
               </property>
           </bean>
          相當(dāng)于serviceB和serviceA中使用的serviceB不是同一個實(shí)例。
           
           但是如果確實(shí)調(diào)用重合時(shí)怎么辦?
           
           解決方法是這樣的:
           
           <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
               <property name="serviceB">
                   <ref bean="serviceBImpl"/>
               </property>
           </bean>
           
            非常簡單,serviceAImpl調(diào)用時(shí),可能已經(jīng)在事務(wù)環(huán)境中了,不需再使用serviceB代理的事務(wù)支持,
            于是直接引用serviceB實(shí)例。這個方法是我寫這篇文章時(shí)想到的,-_-!!!,看來知識果真還是好好
            整理呀。

           

          posted @ 2006-02-08 16:32 java小記 閱讀(898) | 評論 (0)編輯 收藏
          關(guān)于網(wǎng)站開發(fā)中連接的可移植性總結(jié)

          網(wǎng)絡(luò)主機(jī)地址http://localhost:
          8080/

          1. 相對于根目錄的連接,形如: "/another.jsp"
           
           /DIR/目錄下的
           <a href
          ="/another.jsp">Link</a>
           <html:link href
          ="/another.jsp">Link</html:link>
           <html:link page
          ="/another.jsp">Link</html:link> 
           在默認(rèn)ROOT應(yīng)用中
          ,分別連接到地址:
           http://localhost:
          8080/another.jsp
           http://localhost:
          8080/another.jsp
           http://localhost:
          8080/another.jsp 
           在應(yīng)用test中
          ,分別連接到地址:
           http://localhost:
          8080/another.jsp
           http://localhost:
          8080/another.jsp
           http://localhost:
          8080/test/another.jsp 
           
          2. 相對于當(dāng)前目錄的連接,形如: "./another.jsp" 或 "another.jsp"
           
           /DIR/目錄下的
           <a href
          ="./another.jsp">Link</a> 
           <html:link href
          ="./another.jsp">Link</html:link>
           <html:link page
          ="./another.jsp">Link</html:link> 
           在默認(rèn)ROOT應(yīng)用中
          ,都分別連接到地址:
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080//DIR/another.jsp  
           在應(yīng)用test中
          ,分別連接到地址:
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080/test./another.jsp   錯誤連接(而且與DIR無關(guān),都連接到此地址)
            
           /DIR/目錄下的
           <a href
          ="another.jsp">Link</a> 
           <html:link href
          ="another.jsp">Link</html:link> 
           <html:link page
          ="another.jsp">Link</html:link> 
           在默認(rèn)ROOT應(yīng)用中
          ,都分別連接到地址:
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080//DIR/another.jsp   
           在應(yīng)用test中
          ,分別連接到地址:
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080//DIR/another.jsp
           http://localhost:
          8080/testanother.jsp       錯誤連接(而且與DIR無關(guān),都連接到此地址)
           
          3總結(jié)
           由于在網(wǎng)站開發(fā)時(shí)經(jīng)常不使用默認(rèn)的WEB應(yīng)用,而可能把一個模塊開發(fā)成一個WEb應(yīng)用(可能多人合作),
           但是在發(fā)布的時(shí)候要把所有模塊發(fā)布為一個WEB應(yīng)用,并通常是默認(rèn)的WEB應(yīng)用,為了使URL不依賴于Web應(yīng)用
           和是否是默認(rèn)WEB應(yīng)用,建議如下
            a.對于相對于WEB應(yīng)用根目錄的連接
          ,形如: "/another.jsp"
              使用<html:link page
          ="/..">Link </html:link>
            b.對于相對于當(dāng)前目錄的連接,形如: 
          "./another.jsp" 或 "another.jsp"
              使用<html:link href
          ="./another.jsp">Link </html:link>
                  <a href
          ="./another.jsp">Link </a>或        
                  <html:link href
          ="another.jsp">Link </html:link>
                  <a href
          ="another.jsp">Link </a>
              不要使用<html:link page
          ="./another.jsp">Link </html:link>
                      <html:link page
          ="another.jsp">Link </html:link> 此二者不可移植
            c.建議使用struts的html標(biāo)簽庫<html:link..標(biāo)簽,因?yàn)楫?dāng)用戶關(guān)閉Cookie時(shí)會自動重寫URL,所以概括
              兩句話:相對應(yīng)用根目錄用<html:link page
          ="/.."  
                      相對當(dāng)前的目錄用<html:link href
          ="./XXXXX.jsp"   或 <html:link href="XXXXX.jsp"  
           
           
          4.補(bǔ)充
            還有一個標(biāo)簽<html:link forward
          ="forwardname"> Link </html:link> 上面沒有提到,現(xiàn)做以說明。
            
            forward屬性和struts配置文件<global-forwards>中的一個<forward>元素匹配,不能和<action>中<forward>匹配。
            
            例子:<global-forwards>
                   <forward name
          ="forwardname" path="//another.jsp"/>
                 </global-forwards>
                 
                 <html:link forward
          ="forwardname"> Link </html:link>
                 相當(dāng)于<html:link page
          ="//another.jsp"> Link </html:link>
            需要注意的是:<global-forwards>中<forward>的path要使用相對于WEB應(yīng)用的根目錄路徑,包括<action>中也是。
            
            在struts1.1多應(yīng)用模塊時(shí)<html:link forwad. 有時(shí)不好使,不知道為什么????(好像是模塊切換狀態(tài)
            不對)所以最好不用。
            替代方法;
            網(wǎng)頁中用連接
              <html:link page
          ="/forwardaction.do">forward</html:link>
            在action-mapping配置如下action
               <action  path
          ="/forwardaction"  forward="/index.jsp" />
            
          posted @ 2006-02-06 20:58 java小記 閱讀(210) | 評論 (0)編輯 收藏
          package aa;

          import java.util.ArrayList;
          import java.util.Date;
          import java.util.List;

          //for test6
          import static java.lang.Math.*;

          public class Test {

              
          public static void main(String[] args) {
                  
          // 1
                  Double d = 123.45;
                  d 
          += 20.601;
                  System.out.println(d);
                  
          double dd = d + 45.123;
                  System.out.println(dd);

                  
          // 2,3
                  List<List<String>> list = new ArrayList<List<String>>();

                  List
          <String> line1 = new ArrayList<String>();
                  line1.add(
          "hello");
                  line1.add(
          ",");
                  line1.add(
          "world");
                  
          // line1.add(new Integer(123));//complie error
                  list.add(line1);

                  List
          <String> line2 = new ArrayList<String>();
                  line2.add(
          "hello2");
                  line2.add(
          ",");
                  line2.add(
          "world2");
                  list.add(line2);

                  
          for (List<String> g : list) {
                      
          for (String str : g) {
                          System.out.print(str);
                      }

                      System.out.println();
                  }


                  
          // 4
                  Color bg = Color.Red;
                  System.out.println(bg);

                  
          for (Color c : Color.values()) {
                      System.out.println(c);
                  }


                  
          // 5
                  print("hello"",""World"new Date(), 123456);
                  
                  
          //6
                  double i=2*PI;
                  print(i);

              }


              
          public static void print(Object objects) {
                  
          for (Object obj : objects) {
                      System.out.println(obj);
                  }

              }


          }


          enum Color {
              Red, Green, Blue
          }

          posted @ 2006-02-05 10:55 java小記 閱讀(233) | 評論 (0)編輯 收藏
          eclipse2不支持jdk1.5支持1.4
          eclipse3.0好象也不支持jdk1.5
          eclipse3.1支持jdk1.5

          jbuilder9不支持jdk1.5支持1.4
          jbuilder2006好象集成的就是jdk1.5,沒用過
          posted @ 2006-02-05 10:52 java小記 閱讀(238) | 評論 (0)編輯 收藏

          創(chuàng)建一個密鑰文件,
          %JAVA_HOME%/bin/keytool -genkey -alias myalias   -keyalg RSA  -validity 3650 -keystore ./mykeystorefilename

          修改conf/server.xml,打開Tomcat的HTTPS端口,
              <Connector port="8443"
                         maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
                         enableLookups="false" disableUploadTimeout="true"
                         acceptCount="100" debug="0" scheme="https" secure="true"
                         keystoreFile="mykeystorefilepath" 
                         keystorePass="mykeystorepassword" >
                <Factory clientAuth="false" protocol="TLS" />
              </Connector>
             
          在應(yīng)用中修改web.xml,增加授權(quán)區(qū)
          <security-constraint>
                  <web-resource-collection>
                          <url-pattern>/*</url-pattern>
                          <http-method>GET</http-method>
                          <http-method>POST</http-method>
                  </web-resource-collection>
                  <user-data-constraint>
                          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
                  </user-data-constraint>
          </security-constraint>

          posted @ 2006-01-21 21:32 java小記 閱讀(167) | 評論 (0)編輯 收藏


          指定網(wǎng)絡(luò)名稱不可用
          The specified network name is no longer available. : winnt_accept: Asynchronous AcceptEx failed.

          An operation was attempted on something that is not a socket.:winnt_accept: AcceptEx failed. Attempting to recover.

          出現(xiàn)這樣的問題,解決方法是:禁止使用AcceptEx,方法為在httpd.conf文件中增加Win32DisableAcceptEx標(biāo)記,例如:
                 <IfModule mpm_winnt.c>
                 ..........
                       Win32DisableAcceptEx
                 .........
                 </IfModule>
          雖然這樣會使性能降低一些.
          from apache docs2.0:
          AcceptEx() is a Microsoft WinSock v2 API that provides some performance improvements over the use of
          the BSD style accept() API in certain circumstances. Some popular Windows products, typically virus
          scanning or virtual private network packages, have bugs that interfere with the proper operation of
          AcceptEx(). If you encounter an error condition like:
          [error] (730038)An operation was attempted on something that is not a socket.: winnt_accept: AcceptEx
          failed. Attempting to recover.
          you should use this directive to disable the use of AcceptEx().

          posted @ 2006-01-21 21:07 java小記 閱讀(365) | 評論 (0)編輯 收藏

          在tomcat配置文件server.xml的<Connector ... />配置中,有和連接數(shù)相關(guān)的參數(shù):
           <Connector
          port="8080"               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
                         enableLookups="false" redirectPort="8443" acceptCount="100"
                         debug="0" connectionTimeout="20000"
                         disableUploadTimeout="true" />

          web server允許的最大連接數(shù)還受制于操作系統(tǒng)的內(nèi)核參數(shù)設(shè)置,通常Windows是2000個左右,Linux是1000個左右。

          posted @ 2006-01-05 13:29 java小記 閱讀(643) | 評論 (0)編輯 收藏
          在tomcat_home /conf/web.xml中,把listings參數(shù)設(shè)置成false即可
          <servlet>
          ...
          <init-param>
          <param-name>listings</param-name>
          <param-value>false</param-value>
          </init-param>
          ...
          </servlet>
          posted @ 2006-01-05 13:21 java小記 閱讀(165) | 評論 (0)編輯 收藏

          下面的這兩個文件,尺寸差別很大.
          %JAVA_HOME%/jre/bin/client/jvm.dll
          %JAVA_HOME%/jre/bin/server/jvm.dll
          Jvm動態(tài)庫有client和server兩個版本,分別針對桌面應(yīng)用和服務(wù)器應(yīng)用做了相應(yīng)的優(yōu)化,
          client版本加載速度較快,server版本加載速度較慢但運(yùn)行起來較快。

          讓Tomcat 使用Server版本的jvm吧,在開始菜單 tomcat5 ->tomcat config的java屬性中有一項(xiàng) jvm路徑指向server目錄下的jvm就行了。

          更改默認(rèn)java.exe調(diào)用的jvm.dll,這個由jvm.cfg決定。
          編輯%JAVA_HOME%\jre\lib\i386\jvm.cfg 
          里面第一行寫的是 -client 默認(rèn)就是client版本 ,把第二行的-server KNOWN 放到第一行, 如下面所示
          -server KNOWN
          -client KNOWN
          -hotspot ALIASED_TO -client
          -classic WARN
          -native ERROR
          -green ERROR
          改完保存,然后看看默認(rèn)版本:
          C:\java -version
          java version "1.4.2_07"
          Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_07-b05)
          Java HotSpot(TM) Server VM (build 1.4.2_07-b05, mixed mode)
          看到有 Server VM 字樣

          posted @ 2006-01-05 13:09 java小記 閱讀(245) | 評論 (0)編輯 收藏


          內(nèi)存不足 (OOM) - 由于 java 堆或本地內(nèi)存中的內(nèi)存耗盡,應(yīng)用程序顯示“內(nèi)存不足”錯誤。
          內(nèi)存泄漏 - java 堆或本地內(nèi)存的持續(xù)內(nèi)存增長,最終將導(dǎo)致內(nèi)存不足狀態(tài)。調(diào)試內(nèi)存泄漏狀態(tài)的技術(shù)與調(diào)試內(nèi)存不足狀態(tài)的技術(shù)相同。

          Java 堆 - 這是 JVM 用來分配 java 對象的內(nèi)存。java 堆內(nèi)存的最大值用 java 命令行中的 -Xmx 標(biāo)志來指定。
          如果未指定最大的堆大小,那么該極限值由 JVM 根據(jù)諸如計(jì)算機(jī)中的物理內(nèi)存量和該時(shí)刻的可用空閑內(nèi)存量這類
          因素來決定。始終建議您指定最大的 java 堆值。

          本地內(nèi)存 - 這是 JVM 用于其內(nèi)部操作的內(nèi)存。JVM 將使用的本地內(nèi)存堆數(shù)量取決于生成的代碼量、創(chuàng)建的線程、
          GC 期間用于保存 java 對象信息的內(nèi)存,以及在代碼生成、優(yōu)化等過程中使用的臨時(shí)空間。
          如果有一個第三方本地模塊,那么它也可能使用本地內(nèi)存。例如,本地 JDBC 驅(qū)動程序?qū)⒎峙浔镜貎?nèi)存。
          最大本地內(nèi)存量受到任何特定操作系統(tǒng)上的虛擬進(jìn)程大小限制的約束,也受到用 -Xmx 標(biāo)志指定用于 java 堆的內(nèi)存量的限制。
          例如,如果應(yīng)用程序能分配總計(jì)為 3 GB 的內(nèi)存量,并且最大 java 堆的大小為 1 GB,那么本地內(nèi)存量的最大值可能在 2 GB 左右。
           
          進(jìn)程大小 - 進(jìn)程大小將是 java 堆、本地內(nèi)存與加載的可執(zhí)行文件和庫所占用內(nèi)存的總和。在 32 位操作系統(tǒng)上,進(jìn)程的虛擬地址
          空間最大可達(dá)到 4 GB。從這 4 GB 內(nèi)存中,操作系統(tǒng)內(nèi)核為自己保留一部分內(nèi)存(通常為 1 - 2 GB)。剩余內(nèi)存可用于應(yīng)用程序。

          Windows缺省情況下,2 GB 可用于應(yīng)用程序,剩余 2 GB 保留供內(nèi)核使用。但是,在 Windows 的一些變化版本中,有一個 /3GB 開關(guān)
          可用于改變該分配比率,使應(yīng)用程序能夠獲得 3 GB。有關(guān) /3GB 開關(guān)的詳細(xì)信息,可以在以下網(wǎng)址中找到:
          http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ddtools/hh/ddtools/bootini_1fcj.asp
          RH Linux AS 2.1 - 3 GB 可用于應(yīng)用程序。

          進(jìn)程地址空間和物理內(nèi)存之間的差異:
          每個進(jìn)程都獲得其自有的地址空間。在 32 位操作系統(tǒng)中,此地址空間范圍為 0 到 4 GB。此范圍與計(jì)算機(jī)的可用隨機(jī)存取內(nèi)存 (RAM)
          或交換空間無關(guān)。計(jì)算機(jī)中的可用物理內(nèi)存總量是該計(jì)算機(jī)上的可用 RAM 和交換空間之和。所有運(yùn)行的進(jìn)程共享這些物理內(nèi)存。

          進(jìn)程內(nèi)的存儲地址是虛擬地址。內(nèi)核將此虛擬地址映射到物理地址上。物理地址指向物理內(nèi)存中的某個位置。在任一給定時(shí)間,計(jì)算機(jī)
          中運(yùn)行進(jìn)程所使用的全部虛擬內(nèi)存的總和不能超過該計(jì)算機(jī)上可用物理內(nèi)存的總量。


          為什么會發(fā)生 OOM 問題,JVM 在這種情況下如何處理?

          如果 JVM 不能在 java 堆中獲得更多內(nèi)存來分配更多 java 對象,將會拋出 java 內(nèi)存不足 (java OOM) 錯誤。如果 java 堆充滿了活
          動對象,并且 JVM 無法再擴(kuò)展 java 堆,那么它將不能分配更多 java 對象。
          在這種情況下,JVM 讓應(yīng)用程序決定在拋出 java.lang.OutOfMemoryError 后該執(zhí)行什么操作。例如,應(yīng)用程序可以處理此錯誤,并決定
          以安全方式自行關(guān)閉或決定忽略此錯誤。如果應(yīng)用程序不處理此錯誤,那么拋出此錯誤的線程將退出(如果您進(jìn)行 java Thread Dump,那
          么將看不到該線程)。

          在使用 Weblogic Server 的情況下,如果此錯誤是由某個執(zhí)行線程拋出的,則會處理此錯誤并將其記錄在日志中。如果連續(xù)拋出此錯誤,
          那么核心運(yùn)行狀況監(jiān)視器線程將關(guān)閉 Weblogic Server。

          如果 JVM 無法獲得更多本地內(nèi)存,它將拋出本地內(nèi)存不足(本地 OOM)錯誤。當(dāng)進(jìn)程到達(dá)操作系統(tǒng)的進(jìn)程大小限值,或者當(dāng)計(jì)算機(jī)用完
          RAM 和交換空間時(shí),通常會發(fā)生這種情況。當(dāng)發(fā)生這種情況時(shí),JVM 處理本地 OOM 狀態(tài),記錄說明它已用完本地內(nèi)存或無法獲得內(nèi)存的
          消息,然后退出。如果 JVM 或加載的任何其它模塊(如 libc 或第三方模塊)不處理這個本地 OOM 狀態(tài),那么操作系統(tǒng)將給 JVM 發(fā)送
          命令 JVM 退出的 sigabort 信號。通常情況下,JVM 收到 sigabort 信號時(shí)將會生成一個核心文件。


          排除故障的步驟:
          確定是 Java OOM 還是本地 OOM:
          如果 stdout/stderr 消息說明這是一個 java.lang.OutOfMemoryError,那么這就是 Java OOM
          如果 stdout/stderr 消息說明無法獲得內(nèi)存,那么這就是本地 OOM
          請注意,上述消息僅發(fā)送到 stdout 或 stderr 中,而不發(fā)送到應(yīng)用程序特定的日志文件(如 weblogic.log)


          對于 Java OOM,收集和分析 verbose:gc 輸出 在 java 命令行中添加“-verbose:gc”標(biāo)志。這樣將會把 GC 活動信息打印到
          stdout/stderr。將 stdout/stderr 重定向到一個文件。運(yùn)行應(yīng)用程序,直到該問題重現(xiàn)。 確保 JVM 在拋出 java OOM 之
          前完成下列任務(wù),執(zhí)行一次完整 GC 運(yùn)行,并且刪除了所有不可及對象以及虛可及、弱可及、軟可及對象,并回收了那些空間。
          有關(guān)不同級別的對象可及性的詳細(xì)信息,可以在以下網(wǎng)址中可找到:
          http://java.sun.com/developer/technicalArticles/ALT/RefObj
          您可以檢查是否在發(fā)出 OOM 消息之前執(zhí)行了完整 GC 運(yùn)行。當(dāng)完成一次完整 GC 運(yùn)行時(shí),將會打印類似如下消息(格式取決
          于 JVM - 請查看 JVM 幫助信息以了解有關(guān)格式)
          [memory ] 7.160: GC 131072K->130052K (131072K) in 1057.359 ms
          以上輸出的格式如下(備注:在此模式下將全部使用相同的格式):
          [memory ] <start>: GC <before>K-><after>K (<heap>K), <total> ms
          [memory ] <start> - start time of collection (seconds since jvm start)
          [memory ] <before> - memory used by objects before collection (KB)
          [memory ] <after> - memory used by objects after collection (KB)
          [memory ] <heap> - size of heap after collection (KB)
          [memory ] <total> - total time of collection (milliseconds)

          但是,沒有辦法斷定是否使用 verbose 消息刪除了軟/弱/虛可及的對象。如果您懷疑在拋出 OOM 時(shí)這些對象仍然存在,請
          與 JVM 供應(yīng)商聯(lián)系。

          如果垃圾回收算法是一種按代回收算法(對于 Jrockit 為 gencopy 或 gencon,對于其它 JDK 則是缺省算法),您也將看
          到類似如下的 verbose 輸出:
          [memory ] 2.414: Nursery GC 31000K->20760K (75776K), 0.469 ms
          以上是 nursery GC(即 young GC)周期,它將把活動對象從 nursery(或 young 空間)提升到 old 空間。這個周期對我
          們的分析不重要。有關(guān)按代回收算法的詳細(xì)信息,可以在 JVM 文檔中找到。
          如果在 java OOM 之前未發(fā)生 GC 周期,那么這是一個 JVM 錯誤。

          完全壓縮:
          確保 JVM 執(zhí)行了適當(dāng)?shù)膲嚎s工作,并且內(nèi)存并未成碎片(否則會阻止分配大對象并觸發(fā) java OOM 錯誤)。
          Java 對象要求內(nèi)存是連續(xù)的。如果可用空閑內(nèi)存是一些碎片,那么 JVM 將無法分配大對象,因?yàn)樗赡軣o法放入任何可用
          空閑內(nèi)存塊中。在這種情況下,JVM 將執(zhí)行一次完全壓縮,以便形成更多連續(xù)的空閑內(nèi)存來容納大對象。
          壓縮工作包括在 java 堆內(nèi)存中將對象從一個位置移動到另一個位置,以及更新對這些對象的引用以指向新位置。除非確有
          必要,否則 JVM 不會壓縮所有對象。這是為了減少 GC 周期的暫停時(shí)間。
          我們可以通過分析 verbose gc 消息來檢查 java OOM 是否由碎片引起。如果您看到類似如下的輸出(在此無論是否有可用
          的空閑 java 堆都會拋出 OOM),那么這就是由碎片引起的。

          [memory ] 8.162: GC 73043K->72989K (131072K) in 12.938 ms
          [memory ] 8.172: GC 72989K->72905K (131072K) in 12.000 ms
          [memory ] 8.182: GC 72905K->72580K (131072K) in 13.509 ms
          java.lang.OutOfMemoryError
          在上述情況中您可以看到,所指定的最大堆內(nèi)存是 128MB,并且當(dāng)實(shí)際內(nèi)存使用量僅為 72580K 時(shí),JVM 拋出 OOM。堆使用量
          僅為 55%。因此在這種情況下,碎片影響是:即使還有 45% 的空閑堆,內(nèi)存也會拋出 OOM。這是一個 JVM 錯誤或缺陷。您應(yīng)
          當(dāng)與 JVM 供應(yīng)商聯(lián)系。

          如果 JVM 一切都正常(上一步中提到的所有操作),那么此 java OOM 可能是應(yīng)用程序的問題。應(yīng)用程序可能在不斷泄漏一些
          java 內(nèi)存,而這可能導(dǎo)致出現(xiàn)上述問題。或者,應(yīng)用程序使用更多的活動對象,因此它需要更多 java 堆內(nèi)存。在應(yīng)用程序中
          可以檢查以下方面: 應(yīng)用程序中的緩存功能 - 如果應(yīng)用程序在內(nèi)存中緩存 java 對象,則應(yīng)確保此緩存并沒有不斷增大。對
          緩存中的對象數(shù)應(yīng)有一個限值。我們可以嘗試減少此限值,來觀察其是否降低 java 堆使用量。 Java 軟引用也可用于數(shù)據(jù)緩存,
          當(dāng) JVM 用完 java 堆時(shí),可以保證刪除軟可及對象。

          長期活動對象 - 如果應(yīng)用程序中有長期活動對象,則可以嘗試盡可能減少這些對象的存在期。例如,調(diào)整 HTTP 會話超時(shí)值將
          有助于更快地回收空閑會話對象。
          內(nèi)存泄漏 - 內(nèi)存泄漏的一個例子是在應(yīng)用服務(wù)器中使用數(shù)據(jù)庫連接池。當(dāng)使用連接池時(shí),必須在 finally 塊中顯式關(guān)閉 JDBC
          語句和結(jié)果集對象。這是因?yàn)?,?dāng)從池中調(diào)用連接對象上的 close() 時(shí),只是簡單地把連接返回池中以供重用,并沒有實(shí)際關(guān)閉
          連接和關(guān)聯(lián)的語句/結(jié)果集對象。

          增加 java 堆 - 如果可能的話,我們也可嘗試增加 java 堆,以觀察是否能解決問題。

          如果上述建議都不適用于該應(yīng)用程序,那么,我們需要使用一個基于 JVMPI(JVM 事件探查器接口)的事件探查器(如 Jprobe 或
          OptimizeIt)來找出哪些對象正在占用 java 堆。事件探查器還提供 java 代碼中正在創(chuàng)建這些對象的位置的詳細(xì)信息。本文檔并
          不介紹每個事件探查器的詳細(xì)信息??梢詤⒖际录讲槠魑臋n來了解如何用事件探查器設(shè)置和啟動應(yīng)用程序。一般而言,基于 JVMPI
           的事件探查器需要較高的系統(tǒng)開銷,并會大大降低應(yīng)用程序的性能。因此,在生產(chǎn)環(huán)境中使用這些事件探查器并不可取。
          http://www.borland.com/optimizeit
          http://www.quest.com/jprobe

          對于本地 OOM 問題:
          收集下列信息: .verbosegc 輸出,通過它可監(jiān)視 java 堆使用量。這樣將有助于了解此應(yīng)用程序的 java 內(nèi)存要求。
          應(yīng)當(dāng)注意,指定的最大堆內(nèi)存量(在 java 命令行中使用 Xmx 標(biāo)志)與應(yīng)用程序的實(shí)際 java 堆使用量無關(guān),其在 JVM 啟動時(shí)被保留,
          并且此保留內(nèi)存不能用于其它任何用途。

          在使用 Jrockit 時(shí),使用 -verbose 來代替 -verbosegc,因?yàn)檫@可以提供 codegen 信息以及 GC 信息。
          定期記錄進(jìn)程虛擬內(nèi)存大小,從啟動應(yīng)用程序時(shí)起直到 JVM 用完本地內(nèi)存。這樣將有助于了解此進(jìn)程是否確實(shí)達(dá)到該操作系統(tǒng)的大小限
          值。在 Windows 環(huán)境下,使用下列步驟來監(jiān)視虛擬進(jìn)程大?。?BR>在“開始” -> “運(yùn)行”對話框中,輸入“perfmon”并單擊“確定”。
          在彈出的“性能”窗口中,單擊“+”按鈕(圖表上部)。
          在顯示的對話框中選擇下列選項(xiàng):
          性能對象:進(jìn)程(不是缺省的處理器)
          從列表中選擇計(jì)數(shù)器:虛擬字節(jié)數(shù)
          從列表中選擇實(shí)例:選擇 JVM (java) 實(shí)例
          單擊“添加”,然后單擊“關(guān)閉”
          在 Unix 或 Linux 環(huán)境下,對于一個給定 PID,可以使用以下命令來查找虛擬內(nèi)存大小 - ps -p <PID> -o vsz。

          在 Linux 環(huán)境下,單個 JVM 實(shí)例內(nèi)的每個 java 線程都顯示為一個獨(dú)立的進(jìn)程。如果我們獲得根 java 進(jìn)程的 PID,那么這就足夠了。
          可以使用 ps 命令的 .forest 選項(xiàng)來找到根 java 進(jìn)程。例如,ps lU <user> --forest 將提供一個由指定用戶啟動的所有進(jìn)程的 ASCII
          樹圖。您可以從該樹圖中找到根 java。

          計(jì)算機(jī)中的內(nèi)存可用性
          如果計(jì)算機(jī)沒有足夠的 RAM 和交換空間,則操作系統(tǒng)將不能為此進(jìn)程提供更多內(nèi)存,這樣也會導(dǎo)致內(nèi)存不足。請確保 RAM 與磁盤中的交換
          空間之和足以滿足該計(jì)算機(jī)中正在運(yùn)行的所有進(jìn)程的需要。

          調(diào)整 java 堆
          如果 java 堆使用量完全在最大堆范圍內(nèi),則減小 java 最大堆將為 JVM 提供更多的本地內(nèi)存。這不是一個解決辦法,而是一個可嘗試的變
          通方法。由于操作系統(tǒng)限制進(jìn)程大小,我們需要在 java 堆和本地堆之間尋求一個平衡。
          JVM 的本地內(nèi)存使用量
          在加載了所有類并調(diào)用了方法(代碼生成結(jié)束)后,JVM 的本地內(nèi)存用量預(yù)計(jì)將會幾乎達(dá)到穩(wěn)定。對于大多數(shù)應(yīng)用程序而言,這通常發(fā)生在
          最初幾小時(shí)內(nèi)。此后,JVM 可能會因加載運(yùn)行時(shí)類型、生成優(yōu)化代碼等處理而僅使用少量本地內(nèi)存。

          為了縮小問題的范圍,可嘗試禁用運(yùn)行時(shí)優(yōu)化,并檢查這是否會產(chǎn)生任何效果。

          在使用 Jrockit 時(shí),可使用 -Xnoopt 標(biāo)志來禁用運(yùn)行時(shí)優(yōu)化。

          在使用 SUN hotspot JVM 時(shí),-Xint 標(biāo)志將強(qiáng)迫 JVM 在解釋模式中運(yùn)行(不生成代碼)。
          如果在整個運(yùn)行過程中,本地內(nèi)存使用量繼續(xù)不斷增加,那么這可能是本地代碼中的內(nèi)存泄漏。

          第三方本地模塊或應(yīng)用程序中的 JNI 代碼
          檢查您是否在使用類似數(shù)據(jù)庫驅(qū)動程序的任何第三方本地模塊。這些本地模塊也可以分配本地內(nèi)存,泄漏可能從這些模塊中發(fā)生。為了縮
          小問題的范圍,應(yīng)嘗試在沒有這些第三方模塊的情況下重現(xiàn)問題。例如,可以使用純 java 驅(qū)動程序來代替本地?cái)?shù)據(jù)庫驅(qū)動程序。

          檢查應(yīng)用程序是否使用一些 JNI 代碼。這也可能造成本地內(nèi)存泄漏,如果可能的話,您可以嘗試在沒有 JNI 代碼的情況下運(yùn)行應(yīng)用程序。

          如果在執(zhí)行上述步驟后還不能找到本地內(nèi)存泄漏的根源,那么您需要與 JVM 供應(yīng)商合作來獲得一個特殊的編譯版本,它可以跟蹤本地內(nèi)存
          分配調(diào)用,并可提供有關(guān)泄漏的更多信息。

          Jrockit 特定特性
          Jrockit 81SP1 和更高版本支持 JRA 記錄(Java 運(yùn)行時(shí)間分析器)。這對于收集 JVM 運(yùn)行時(shí)的信息很有用,將提供應(yīng)用程序的有關(guān)信息,
          例如,正在運(yùn)行的 GC 數(shù)、軟/弱/虛引用的數(shù)目、熱方法,等等。如果 JVM 出現(xiàn)性能問題或掛起問題,那么用幾分鐘進(jìn)行記錄和分析數(shù)據(jù)
          就會很有用。有關(guān)詳細(xì)信息,可以在 Jrockit 文檔中找到。
          http://e-docs.bea.com/wljrockit/docs142/userguide/jra.html


          如果您已經(jīng)理解這個模式,但仍需要其它幫助,您可以:
          http://support.bea.com 上查詢 AskBEA(例如使用“out of memory”),以查找其它已發(fā)布的解決方案。
          http://support.bea.com 上,向 BEA 的某個新聞組中提出更詳細(xì)具體的問題。
          如果這還不能解決您的問題,并且您擁有有效的技術(shù)支持合同,您可以通過登錄以下網(wǎng)站來打開支持案例:http://support.bea.com。
           

          posted @ 2005-12-21 21:48 java小記 閱讀(410) | 評論 (0)編輯 收藏

          修改 windows: mysql-root/my.ini  (mysql-4.1.14-win32.zip)
               linux:   /etc/my.cnf
          將其中的default-character-set都改成gbk
          也就是如下兩個SECTION
          [client] 
          。。。。
          default-character-set=gbk
          。。。。


          [mysqld]
          。。。。
          default-character-set=gbk
          。。。。


          Linux上:
          mysql> show variables like "%set%";
          +--------------------------+----------------------------------------------------
          ----------------------+
          | Variable_name            | Value
                                |
          +--------------------------+----------------------------------------------------
          ----------------------+
          | character_set_client     | gbk
                                |
          | character_set_connection | gbk
                                |
          | character_set_database   | gbk
                                |
          | character_set_results    | gbk
                                |
          | character_set_server     | gbk
                                |
          | character_set_system     | utf8
                                |
          | character_sets_dir       | /usr/local/mysql-standard-4.1.12-pc-linux-gnu-i686/
          share/mysql/charsets/ |
          +--------------------------+----------------------------------------------------
          ----------------------+
          7 rows in set (0.00 sec)
          此時(shí)可以查看中文的字段,應(yīng)該一切正常顯示。如果不正常顯示說明數(shù)據(jù)庫中存放的不是正確編碼。


          Windows上:
          mysql> show variables like "%set%";
          +--------------------------+--------------------------+
          | Variable_name            | Value                    |
          +--------------------------+--------------------------+
          | character_set_client     | latin1                   |
          | character_set_connection | latin1                   |
          | character_set_database   | gbk                      |
          | character_set_results    | latin1                   |
          | character_set_server     | gbk                      |
          | character_set_system     | utf8                     |
          | character_sets_dir       | D:\MySql\share\charsets/ |
          +--------------------------+--------------------------+
          7 rows in set (0.00 sec)

          不知道為什么在windows上my.ini中
          [client]
          。。。。
          default-character-set=gbk
          沒有起作用。

          Windows上登錄mysql,更改會話的編碼為gbk

          mysql> set names "gbk";
          Query OK, 0 rows affected (0.00 sec)

          mysql> show variables like "%set%";
          +--------------------------+--------------------------+
          | Variable_name            | Value                    |
          +--------------------------+--------------------------+
          | character_set_client     | gbk                      |
          | character_set_connection | gbk                      |
          | character_set_database   | gbk                      |
          | character_set_results    | gbk                      |
          | character_set_server     | gbk                      |
          | character_set_system     | utf8                     |
          | character_sets_dir       | D:\MySql\share\charsets/ |
          +--------------------------+--------------------------+
          7 rows in set (0.00 sec)

          此時(shí)可以查看中文的字段,應(yīng)該一切正常顯示。如果不正常顯示說明數(shù)據(jù)庫中存放的不是正確編碼。


          完全備份MySql
          Linux上:
            mysqldump  --user=myname --password=mypassword  mydb >mydb_backup.sql
          Windows上:
           Linux上:
            mysqldump   --default-character-set=gb2312 --user=myname --password=mypassword  mydb >mydb_backup.sql

          Windows腳本自動登陸
          D:\MySql\bin>mysql  --user=myname  --password=mypassword   --default-character-set=gbk   --host=192.168.0.17

          posted @ 2005-12-20 15:56 java小記 閱讀(551) | 評論 (0)編輯 收藏

          項(xiàng)目中需要對安全問題引起足夠的重視,比如下列tomcat的安全問題容易被忽略:
           
          server.xml默認(rèn)有下面一行:
          <Server port="8005" shutdown="SHUTDOWN">
          這樣允許任何人只要telnet到服務(wù)器的8005端口,輸入"SHUTDOWN",然后回車,服務(wù)器立即就被關(guān)掉了。
          從安全的角度上考慮,我們需要把這個shutdown指令改成一個別人不容易猜測的字符串。
          例如修改如下:
          <Server port="8006" shutdown="lizongbo">,這樣就只有在telnet到8006,并且輸入"lizongbo"才能夠關(guān)閉Tomcat.
          注意:這個修改不影響shutdown.bat的執(zhí)行。運(yùn)行shutdown.bat一樣可以關(guān)閉服務(wù)器。

           

          參考Tomcat安全文檔英文鏈接:http://jakarta.apache.org/tomcat/faq/security.html#8005
          還有兩個問題需要注意:
          1、  對于tomcat3.1中,屏蔽目錄文件自動列出的方法是什么?
          缺省情況下,如果你訪問tomcat下的一個web應(yīng)用,那么如果你輸入的是一個目錄名,而且該目錄下沒有一個可用的welcome文件,那么tomcat會將該目錄下的所有文件列出來,如果你想屏蔽這個缺省行為,那么可以修改conf/web.xml文件,將其中的:
          <servlet>
          <servlet-name>default</servlet-name>
          <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
          <init-param>
          <param-name>debug</param-name>
          <param-value>0</param-value>
          </init-param>
          <init-param>
          <param-name>listings</param-name>
          <param-value>true</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
          </servlet>
          修改為:
          <servlet>
          <servlet-name>default</servlet-name>
          <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
          <init-param>
          <param-name>debug</param-name>
          <param-value>0</param-value>
          </init-param>
          <init-param>
          <param-name>listings</param-name>
          <param-value>false</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
          </servlet>


          2、 如何讓Tomcat記錄客戶端的訪問日志 
          下面是Tomcat相關(guān)手冊中的介紹:
          以下是引用來自 的內(nèi)容:
          Valve (功能與Logger差不多,其prefix和suffix屬性解釋和Logger 中的一樣) className 指定Valve使用的類名,
          如用org.apache.catalina.valves.AccessLogValve類可以記錄應(yīng)用程序的訪問信息 directory 指定log文件存放
          的位置 pattern 有兩個值,common方式記錄遠(yuǎn)程主機(jī)名或ip地址,用戶名,日期,第一行請求的字符串,HTTP響
          應(yīng)代碼,發(fā)送的字節(jié)數(shù)。combined方式比common方式記錄的值更多 

          所以需要完成的步驟:
             1。修改Tomcat的conf/server.xml文件。
             2。加上Valve節(jié)點(diǎn)到server.xml文件中,和您目前使用的Connector的節(jié)點(diǎn)平級。
                如:<Valve className="org.apache.catalina.valves.AccessLogValve"
                directory="e:\trs\trscds\tomcat\logs" pattern="combined"/>
             3。重新啟動您的Tomcat
             4。有用戶在訪問的時(shí)候,在指定的log目錄下面會生成一個access_log文件(每天一個)。
          上述的步驟是以Tomcat4.x為例。(可能會影響性能,不推薦大家使用)。

           

          還有一個問題:需要處理好Tomcat管理臺的安全。
          Tomcat管理臺的應(yīng)用文件,默認(rèn)在{Tomcat安裝目錄}\server\webapps下,有admin和manager兩個應(yīng)用。
          其用戶密碼,在{Tomcat安裝目錄}\conf/tomcat-users.xml中定義。在{Tomcat安裝目錄}\webapps下
          admin.xml和manager.xml文件定義了可以通過訪問/admin和/manager進(jìn)入。
          默認(rèn)情況下,完全可以登錄tomcat管理臺,造成嚴(yán)重安全問題
          檢測辦法:用IE打開鏈接http://[IP]:[Port]/admin,以用戶名admin,密碼為空登錄,如果成功,
          說明存在問題。
          解決辦法:可以刪除{Tomcat安裝目錄}\webapps下admin.xml和manager.xml文件,或者去掉用戶密
          碼,也可以刪除應(yīng)用文件。


          我們一個用戶提到如果找不到網(wǎng)頁即出現(xiàn)404錯誤,會顯示服務(wù)器版本號,服務(wù)器配置也一目了然,
          為了避免這種情況,希望自定義設(shè)置錯誤頁面。
          設(shè)置如下:
          1、將附件的index.htm文件拷貝至\webapps\ROOT目錄內(nèi),刪除或改名原來的index.jsp文件。
          2、用記事本打開\conf\web.xml文件,在文件的倒數(shù)第二行(</web-app>一行之前)加入以下內(nèi)容:
                 <error-page> 
                  <error-code>404</error-code>
                  <location>/index.htm</location> 
                </error-page>


           

          posted @ 2005-12-20 15:54 java小記 閱讀(444) | 評論 (0)編輯 收藏

          默認(rèn)安裝tomcat5然后在catalina.bat最前面加入set JAVA_OPTS=-Xms128m -Xmx350m 如果用startup.bat啟動tomcat,OK設(shè)置生效.夠成功的分配200M內(nèi)存.

          但是如果不是執(zhí)行startup.bat啟動tomcat而是利用windows的系統(tǒng)服務(wù)啟動tomcat服務(wù),上面的設(shè)置就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M內(nèi)存就OOM了..

          windows服務(wù)執(zhí)行的是bin\tomcat.exe.他讀取注冊表中的值,而不是catalina.bat的設(shè)置.

          解決辦法:
          修改注冊表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions
          原值為
          -Dcatalina.home="C:\ApacheGroup\Tomcat 5.0"
          -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed"
          -Xrs

          加入 -Xms300m -Xmx350m 
          重起tomcat服務(wù),設(shè)置生效.

          posted @ 2005-12-20 11:58 java小記 閱讀(3292) | 評論 (0)編輯 收藏


           JVM(java虛擬機(jī))其實(shí)就是操作系統(tǒng)(如windows)上的一個普通程序(進(jìn)程名叫java,這個程序可以解釋執(zhí)行class文件)。
           當(dāng)java進(jìn)程啟動時(shí)會首先分配一塊堆內(nèi)存(最小內(nèi)存),以后每當(dāng)class字節(jié)碼程序要求JVM(java進(jìn)程)分配內(nèi)存時(shí),JVM
           就會在預(yù)先分配的那塊內(nèi)存上面為class字節(jié)碼程序分配內(nèi)存,當(dāng)預(yù)先分配的那塊內(nèi)存用沒時(shí),JVM會再向操作系統(tǒng)要內(nèi)存
           (物理內(nèi)存), 但是JVM不會無限制的向操作系統(tǒng)要內(nèi)存,當(dāng)它占用的實(shí)際堆內(nèi)存達(dá)到一個預(yù)定值(最大可用內(nèi)存)時(shí),
           如果class字節(jié)碼程序還向JVM要內(nèi)存,并且JVM無法通過回收當(dāng)前堆中的內(nèi)存來為class字節(jié)碼程序服務(wù)時(shí),它就會給程
           序拋出java.lang.OutOfMemoryError。其中內(nèi)存回收時(shí)機(jī)并不是再用掉內(nèi)存達(dá)到最大可用內(nèi)存時(shí)才進(jìn)行,他的運(yùn)行時(shí)機(jī)是
           不確定的,可見JVM的最大可用內(nèi)存就是你的java程序(class字節(jié)碼程序)能夠使用的最大內(nèi)存。
           例如:你把jvm最大可用內(nèi)存設(shè)為200M,而你的物理內(nèi)存1G.在這種程序下你的class程序最多能使用200M內(nèi)存,雖然你可能
           還有800M內(nèi)存可用,但是當(dāng)你的程序用掉200M后如果再要內(nèi)存,JVM不會因?yàn)槟氵€有800M內(nèi)存而為你分配內(nèi)存,他會向你拋
           出java.lang.OutOfMemoryError .
           所以JVM最大可用內(nèi)存參數(shù)比較重要。
           
           一般建議堆的最大值設(shè)置為可用內(nèi)存的最大值的80%。
           
           
           (以下為轉(zhuǎn)網(wǎng)絡(luò))
           Tomcat默認(rèn)可以使用的內(nèi)存為64MB,在較大型的應(yīng)用項(xiàng)目中,這點(diǎn)內(nèi)存是不夠的,需要調(diào)大。
           Windows下,在文件{tomcat_home}/bin/catalina.bat,Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,
           增加如下設(shè)置:
           set JAVA_OPTS=-Xms【初始化內(nèi)存大小】 -Xmx【可以使用的最大內(nèi)存】
           需要把這個兩個參數(shù)值調(diào)大。例如: set JAVA_OPTS=-Xms64m -Xmx256m
           表示初始化內(nèi)存為256MB,可以使用的最大內(nèi)存為512MB。
           
           另外需要考慮的是Java提供的垃圾回收機(jī)制。虛擬機(jī)的堆大小決定了虛擬機(jī)花費(fèi)在收集垃圾上的時(shí)間和頻度。收集垃圾可
           以接受的速度與應(yīng)用有關(guān),應(yīng)該通過分析實(shí)際的垃圾收集的時(shí)間和頻率來調(diào)整。如果堆的大小很大,那么完全垃圾收集就
           會很慢,但是頻度會降低。如果你把堆的大小和內(nèi)存的需要一致,完全收集就很快,但是會更加頻繁。調(diào)整堆大小的的目
           的是最小化垃圾收集的時(shí)間,以在特定的時(shí)間內(nèi)最大化處理客戶的請求。在基準(zhǔn)測試的時(shí)候,為保證最好的性能,要把堆
           的大小設(shè)大,保證垃圾收集不在整個基準(zhǔn)測試的過程中出現(xiàn)。
           如果系統(tǒng)花費(fèi)很多的時(shí)間收集垃圾,請減小堆大小。一次完全的垃圾收集應(yīng)該不超過 3-5 秒。如果垃圾收集成為瓶頸,那
           么需要指定代的大小,檢查垃圾收集的詳細(xì)輸出,研究 垃圾收集參數(shù)對性能的影響。一般說來,你應(yīng)該使用物理內(nèi)存
           的 80% 作為堆大小。當(dāng)增加處理器時(shí),記得增加內(nèi)存,因?yàn)榉峙淇梢圆⑿羞M(jìn)行,而垃圾收集不是并行的。


          -Xms : 應(yīng)用程序初始化內(nèi)存大寫,注意是你的某一個應(yīng)用程序,多個應(yīng)用程序?qū)⑸啥鄠€JVM實(shí)例
          -Xmx:  應(yīng)用程序占用內(nèi)存的最大值,將不能超過這個值,否則可能導(dǎo)致OutOfMemory.
          -XX:NewRatio  old generation/new generation 的比例

          推薦的-Xms -Xmx設(shè)置成一樣,,為系統(tǒng)內(nèi)存的80%.這樣,不用每次GC清理完再重新分配.
          而-XX:NewRatio為2  比如: -Xms384m -Xmx384m -XX:NewRatio=2

          posted @ 2005-12-19 18:42 java小記 閱讀(1891) | 評論 (0)編輯 收藏
           JDBC 3.0 提供了getGeneratedKeys(),可以獲取自增關(guān)鍵字的值,不需要重新再做一次select操作。

          String sql = "INSERT INTO CUSTOMERS(name,sex,age)values(?,?,?);";
                      PreparedStatement pstmt 
          = conn.prepareStatement(sql);
                      pstmt.setString(
          1, customer.getName());
                      pstmt.setString(
          2, customer.getSex());
                      pstmt.setInt(
          3, customer.getAge());
                      pstmt.execute();
                      ResultSet rs 
          = pstmt.getGeneratedKeys();
                      rs.next();
                      result 
          = new Long(rs.getLong(1));
                      pstmt.close();
          posted @ 2005-11-29 09:18 java小記 閱讀(305) | 評論 (0)編輯 收藏


          事務(wù)不應(yīng)該由dao管理,而應(yīng)該由service管理

          最重要的是如下四個類
          DataSource :數(shù)據(jù)庫的Connection連接工廠
          DataSourceUtils:
          參與同一個事務(wù)的多個dao實(shí)際上應(yīng)該是共享同一個conn的。
          DataSourceUtils.getConnection(dataSource)取得當(dāng)前ThreadLocal的conn,如果沒有從dataSource創(chuàng)建一個。
          DataSourceUtils.releaseConnection(conn, dataSource)未必真正關(guān)閉連接。
          DataSourceTransactionManager
          TransactionProxyFactoryBean;攔截具體業(yè)務(wù)對象方法調(diào)用,中間根據(jù)DataSourceTransactionManager設(shè)置進(jìn)行事務(wù)管理

          文筆不行,說不明白,舉個例子:

           dao1{
             method(){
               conn= DataSourceUtils.getConnection(dataSource);
                ...........
               DataSourceUtils.releaseConnection(conn, dataSource);
             }
           }
           
           dao2{
             method(){
               conn= DataSourceUtils.getConnection(dataSource);
                ...........
               DataSourceUtils.releaseConnection(conn, dataSource);
             }
           }
           
           service{   method();  }
           
           serviceImp{
             method(){
                dao1.method();
                dao2.method();
             }
           }
           
           
           <bean id="dataSource"
                 class="org.apache.commons.dbcp.BasicDataSource"
                 destroy-method="close">
           </bean>     
           <bean id="transactionManager"
                 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
               <property name="dataSource">
                     <ref local="dataSource" />
               </property>
            </bean> 
            <bean id="service"
                    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                 <property name="transactionManager">
                    <ref bean="transactionManager" />
                 </property>
                 <property name="target">
                    <ref local="serviceImp" />
                 </property>
                 <property name="transactionAttributes">
                    <props>
                      <prop key="*">PROPAGATION_REQUIRED</prop>
                    </props>
                 </property>
            </bean> 

          分析:
          當(dāng)調(diào)用service.method()時(shí),開始TransactionProxyFactoryBean攔截此方法指定當(dāng)前線程需要事務(wù),然后調(diào)用dao1.method(),
          調(diào)用conn= DataSourceUtils.getConnection(dataSource)
          判斷當(dāng)前線程還沒有conn則創(chuàng)建一個,因?yàn)榇藭r(shí)線程需要事務(wù)所以conn.setAutoCommit(false),執(zhí)行數(shù)據(jù)庫作,
          然后DataSourceUtils.releaseConnection(conn, dataSource),判斷當(dāng)前線程需要事務(wù)所以不真正關(guān)閉連接繼續(xù),dao1.method()返回。
          調(diào)用dao2.method(),調(diào)用conn= DataSourceUtils.getConnection(dataSource)判斷當(dāng)前線程有一個conn就返回這個conn,(此時(shí)dao1.method()和dao2.method()已經(jīng)共用了這個conn),執(zhí)行數(shù)據(jù)庫操作,然后DataSourceUtils.releaseConnection(conn, dataSource),判斷當(dāng)前線程需要事務(wù)
          所以不真正關(guān)閉連接繼續(xù),dao2.method()返回。service.method()返回,TransactionProxyFactoryBean攔截取得當(dāng)前線程連接提交事務(wù),關(guān)閉清除連接。這樣兩個dao就參與到了一個事務(wù)當(dāng)中。如果service.method()拋出異常,則TransactionProxyFactoryBean在service.method()返回時(shí)攔截取得當(dāng)前線程連接回滾事務(wù),關(guān)閉清除連接。

          不知道猜得對不對

          posted @ 2005-11-26 11:13 java小記 閱讀(1201) | 評論 (1)編輯 收藏
          結(jié)果就是兩行代碼的問題

          使用spring管理DataSource事務(wù)管理,需要采用一個特定的編碼規(guī)范。需要以一個特殊的方式獲得連接資源或者會話資源,允許相關(guān)的 PlatformTransactionManager實(shí)現(xiàn)跟蹤連接的使用,并且當(dāng)需要時(shí)應(yīng)用事務(wù)管理。
          不應(yīng)該調(diào)用一個數(shù)據(jù)源的 getConnection()方法和Connection的close()方法,而必須使用Spring的 org.springframework.jdbc.datasource.DataSourceUtils類,如下:
          Connection conn = DataSourceUtils.getConnection(dataSource);
               .......................
          DataSourceUtils.releaseConnection(conn, dataSource);

          我就是調(diào)用了Connection conn = dataSource.getConnection();
                                     ................................
                                  conn.close();
          結(jié)果郁悶了兩天,一行代碼一天

          posted @ 2005-11-25 10:36 java小記 閱讀(1564) | 評論 (2)編輯 收藏
          我們現(xiàn)在面臨的選擇實(shí)在是太多,Windows VS. Linux,.Net VS. J2EE,Struts VS. JSF,等等等等?,F(xiàn)在幾乎是每走出一步,往往都需要做出非常慎重的選擇,這個選擇很是痛苦,生怕選錯了以后,回頭路不好走。有一點(diǎn)我們不能選擇,即是自己的性別,是男是女,聽天由命,但都活得很好,很少有人為此要死要活的。這個最基本的底線我們都能接受,反而在身外之物上無法抉擇。其實(shí)我們很幸運(yùn),可以同時(shí)使用Windows及Linux,.Net及J2EE,Struts及JSF,盡管我們不能同時(shí)既當(dāng)男的又是女的。選擇多了,欲望多了,反倒更累。

          就像男女問題,選好一條路,認(rèn)真走下去,至死不悔。當(dāng)然,必要時(shí)可以做做變性手術(shù),體會一下另一半的滋味。


          作者:Sarkuya
          地址:http://www.matrix.org.cn/resource/article/43/43863_Spring_EJB3.html
          關(guān)鍵字:Spring EJB3.0 男女問題
          posted @ 2005-11-21 12:35 java小記 閱讀(248) | 評論 (0)編輯 收藏
          網(wǎng)上有人說:"用寫字板打開xml文件 重新保存一次就好了"
          照做,OK了.

          用utrlEdit編輯查看十六進(jìn)制兩者還是相同的,真莫名其妙.
          posted @ 2005-11-20 19:37 java小記 閱讀(791) | 評論 (0)編輯 收藏

          <2005年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 阿克陶县| 临朐县| 龙川县| 天门市| 双桥区| 新乡市| 江都市| 科技| 南雄市| 凌海市| 安化县| 通河县| 施秉县| 富蕴县| 汶上县| 梓潼县| 肃宁县| 闽清县| 桂东县| 藁城市| 东辽县| 清流县| 修水县| 灵川县| 龙州县| 呼伦贝尔市| 运城市| 平乐县| 开封县| 穆棱市| 乌审旗| 枣强县| 醴陵市| 丹阳市| 靖西县| 九龙城区| 吴川市| 舟曲县| 电白县| 越西县| 永吉县|