<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Be alaways javaing...

    Loving Java
    posts - 43, comments - 5, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    2008年12月16日


    posted @ 2008-12-16 09:37 追風舞者 閱讀(158) | 評論 (0)編輯 收藏

    2008年12月11日

    轉載自:www.tkk7.com/zhaobin
    來自BlueDavy的博客

      1. 為什么學習OSGi
      2. OSGi成為JSR291以及OSGi對Spring產生的影響
      3. OSGi應用于企業應用Step by step之持久篇
      4. SCA:企業應用開發的利器
      5. OSGi和SCA
      6. 基于OSGi實現可擴展的模塊的設計
      7. OSGi in action online演講的資料【推薦】
      8. 基于OSGi搭建動態化的系統
      9. OSGi Extender Model啟示錄
      10. Play OSGi
      11. Bnd - Bundle Tool中文使用手冊
      12. 基于Eclipse Equinox的插件框架:TPF
      13. TPF插件管理框架功能、實現以及下載【推薦】
      14. 發布《OSGi實戰》正式版【特別推薦】
      15. 發布《OSGi進階》正式版【特別推薦】
      16. OSGi PPT For Newer【推薦】

    來自 勤勞的蜜蜂的博客

      1. OSGi介紹(一)什么是OSGi
      2. OSGi介紹(二)一個假想的實例
      3. OSGi介紹(三)OSGi service platform的體系結構
      4. OSGi介紹(四)第一個bundle
      5. OSGi介紹(五)兩個bundle
      6. OSGi介紹(六)OSGi的service
      7. OSGi介紹(七)bundle和service(續)

    來自Phrancol的博客

      1. 構建模塊化的動態Web應用(演示版)
      2. 開發基于Equinox/OSGI 的 Web Application (一) [譯]
      3. 開發基于Equinox/OSGI 的 Web Application (二) [譯]
      4. Spring-OSGI 1.0 M3 中文手冊(Spring Dynamic Modules Reference Guide for OSGi(tm) Service Platforms)
      5. Developing Equinox/Spring-osgi/Spring Framework Web Application Part 1 - 顯示首頁【推薦】
      6. Developing Equinox/Spring-osgi/Spring Framework Web Application Part 2 - 使用Spring-OSGI
      7. Developing Equinox/Spring-osgi/Spring Framework Web Application Part 3 - 找到我的Bean

    來自八進制的博客

      1. Equinox OSGi服務器應用程序的配置步驟
      2. 利用OSGi DS實現可配置Web應用程序初探

    來自羅明的博客

      1. 讓OSGi支持JSF Web開發
      2. [OSGi]為什么我們需要Bnd?

    來自yangbutao的博客

      1. OSGI 服務層探究
      2. OSGI Module & lifecycle

    來自erylee的博客

      1. OpenCore: OSGi上部署Hibernate的四種方式
      2. OpenCore:OSGi上部署Apache Common Log
      3. OpenCore:基于OSGi開發純插件體系結構的WEB應用程序

    來自

      1. Equinox OSGi系列之一 Equinox入門
      2. Equinox OSGi系列之二 搭建Equinox OSGi核心環境
      3. Equinox OSGi系列之三 Equinox配置參數詳解
      4. Equinox OSGi系列之四 創建自己的OSGi應用項目 

    來自IBM 的developerworks

      1. 利用 Eclipse 開發基于 OSGi 的 Bundle 應用(2006 年 7 月 17 日)
      2. 基于 OSGi 的面向服務的組件編程(2007 年 8 月 31 日)

    來自其他的博客或帖子:

      1. SOA應用系統總體框架及相關概念
      2. SCA與OSGi真的具有可比性嗎?【推薦】
      3. Eclipse(3.1) Plugin Framework(基于OSGI的Plugin Architecture)
      4. 談談osgi中的事件機制
      5. 基于Web的OSGi框架構想
      6. From JavaWorld  "Hello, OSGi, Part 1: Bundles for beginners" "Hello, OSGi, Part 3: Take it to the server side - JavaWorld"

    posted @ 2008-12-11 14:40 追風舞者 閱讀(223) | 評論 (0)編輯 收藏

    2008年12月3日

    剛剛找到的面試題目。自己做了一下,反正挺慘不人睹的。貼出來就想幫幫有需要的人
    并且問問為什么是這個結果呢?有的題的答案真的想不到啊~想不到~

    一、判斷題(30分)
    1.Java程序里,創建新的類對象用關鍵字new,回收無用的類對象使用關鍵字free。
    2.對象可以賦值,只要使用賦值號(等號)即可,相當于生成了一個各屬性與賦值對象相同的新對象。
    3.有的類定義時可以不定義構造函數,所以構造函數不是必需的。
    4.類及其屬性、方法可以同時有一個以上的修飾符來修飾。
    5.Java的屏幕坐標是以像素為單位,容器的左下角被確定為坐標的起點
    6.抽象方法必須在抽象類中,所以抽象類中的方法都必須是抽象方法。
    7.Final類中的屬性和方法都必須被final修飾符修飾。
    8.最終類不能派生子類,最終方法不能被覆蓋。
    9.子類要調用父類的方法,必須使用super關鍵字。
    10.一個Java類可以有多個父類。
    11.如果p是父類Parent的對象,而c是子類Child的對象,則語句c = p是正確的。
    12.在java集合中,Vector和HashMap是線程安全的。
    13.當一個方法在運行過程中產生一個異常,則這個方法會終止,但是整個程序不一定終止運行。
    14.接口是特殊的類,所以接口也可以繼承,子接口將繼承父接口的所有常量和抽象方法。
    15.用“+”可以實現字符串的拼接,用- 可以從一個字符串中去除一個字符子串。

    二、選擇題(30分)
    1、關于垃圾收集的哪些敘述是正確的(   ):
    A.程序開發者必須自己創建一個線程進行內存釋放的工作
    B.垃圾收集允許程序開發者明確指定并立即釋放該內存
    C.垃圾收集將檢查并釋放不再使用的內存
    D.垃圾收集能夠在期望的時間釋放被java對象使用的內存
    2、下面的哪些賦值語句是不正確的(   ):
    A.float f=11.1;
    B.double d=5.3E12;
    C.double d=3.14159;
    D.double d=3.14D;
    3、下面關于變量及其范圍的陳述哪些是不正確的(   ):
    A.實例變量是類的成員變量
    B.實例變量用關鍵字static聲明
    C.在方法中定義的局部變量在該方法被執行時創建
    D.局部變量在使用前必須被初始化
    4、下列關于修飾符混用的說法,錯誤的是(  ):
    A.abstract不能與final并列修飾同一個類
    B.abstract類中不可以有private的成員
    C.abstract方法必須在abstract類中
    D.static方法中能處理非static的屬性
    5、容器Panel和Applet缺省使用的布局編輯策略是(    ):
    A、BorderLayout  B、FlowLayout      C、GridLayout      D、CardLayout
    6、以下標識符中哪項是不合法的(    ):
    A、 BigMeaninglessName                     B、$int
    C、1 st                                    D、$1
    7、main方法是Java  Application程序執行的入口點,關于main方法的方法頭以下哪項是合法的(    ):
    A、    public  static  void  main()   
    B、    public  static  void   main(String[ ]  args)
    C、    public  static int  main(String[ ]  arg)
    D、    public  void  main(String  arg[ ])
    8、執行完以下代碼int [ ]  x = new  int[25];后,以下哪項說明是正確的(    ):
    A、    x[24]為0
    B、    x[24]未定義
    C、    x[25]為0
    D、    x[0]為空
    9、以下代碼段執行后的輸出結果為(     ):
           int  x=3; int  y=10;
           System.out.println(y%x);
    A、0
    B、1
    C、2
    D、3
    10、以下哪個表達式是不合法的(    ):
    A、String  x=”Hello”;   int  y=9;   x+=y;
    B、String  x=”Hello”;   int  y=9;  if(x= =y)  { }
    C、String  x=”Hello”;  int  y=9;  x=x+y;
    D、String  x=null;  int  y=(x!=null)&&(x.length()>0) ? x.length : 0
    11、編譯運行以下程序后,關于輸出結果的說明正確的是 (    ):
           public  class   Conditional{
                  public  static  void  main(String  args[  ]){
                         int  x=4;
                         System.out.println(“value  is  “+ ((x>4) ? 99.9 :9));
    }
    }
    A、    輸出結果為:value  is  99.99
    B、    輸出結果為:value  is  9
    C、    輸出結果為:value  is  9.0
    D、    編譯錯誤
    12、以下聲明合法的是(     ):
    A、    default  String  s;
    B、    public  final  static  native  int  w( )
    C、    abstract  double  d;
    D、    abstract  final  double  hyperbolicCosine( )
    13、關于以下application的說明,正確的是(    ):
    1.  class   StaticStuff
    2. {
    3.                  static  int  x=10;
    4.                  static  { x+=5;}
    5.                  public  static  void  main(String  args[ ])
    6.                  {
    7.                       System.out.println(“x=” + x);
    8.                  }
    9.                  static  { x/=3;}
    10.   }
    A、 4行與9行不能通過編譯,因為缺少方法名和返回類型 
    B、 9行不能通過編譯,因為只能有一個靜態初始化器
    C、 編譯通過,執行結果為:x=5
    D、編譯通過,執行結果為:x=3
    14、關于以下程序代碼的說明正確的是(   ):
    1.class  HasStatic{
    2.    private  static  int  x=100;
    3.    public  static  void  main(String  args[  ]){
    4.        HasStatic  hs1=new  HasStatic(  );
    5.        hs1.x++;
    6.        HasStatic  hs2=new  HasStatic(  );
    7.        hs2.x++;
    8.        hs1=new  HasStatic( );
    9.        hs1.x++;
    10.       HasStatic.x- -;
    11.       System.out.println(“x=”+x);
    12.   }
    13.}
    A、5行不能通過編譯,因為引用了私有靜態變量
    B、10行不能通過編譯,因為x是私有靜態變量
    C、程序通過編譯,輸出結果為:x=103
    D、程序通過編譯,輸出結果為:x=102
    15、以下選項中循環結構合法的是(    ):
    A、while (int  i<7){
         i++;
         System.out.println(“i is “+i);
    }
    B、int  j=3;
    while(j){
       System.out.println(“ j  is “+j);
    }
    C、int  j=0;
    for(int  k=0; j + k !=10; j++,k++){
        System.out.println(“ j  is “+ j + “k  is”+ k);
    }
    D、int  j=0;
    do{
            System.out.println( “j  is “+j++);
            if (j = = 3) {continue  loop;}
    }while  (j<10);

    三、簡答題(40分)
    1.    寫出下列程序的運行結果
    public class Cat
    {  
      void mi( ) throws NullPointerException
      {
        System.out.println( “Cat mi mi .. “ );
      }
    }
    public class SmallCat extends Cat
    {int i=8;
      void mi( ) throws Exception
      {
        System.out.println( “SmallCat mi mi .. “ );
      }
      public static void main( String[] a ) throws Exception
      {
        Cat cat = new SmallCat();
        cat.mi();
      }
    }


    寫出下列程序的運行結果
    interface Playable {
        void play();
    }
    interface Bounceable {
        void play();
    }
    interface Rollable extends Playable, Bounceable {
        Ball ball = new Ball("PingPang");
    }
    class Ball implements Rollable {
        private String name;
        public String getName() {
            return name;
        }
        public Ball(String name) {
            this.name = name;       
        }
       public void play() {
            ball = new Ball("Football");
            System.out.println(ball.getName());
        }
    }

    寫出下列程序的運行結果
    class Value{
    public int i = 15;
    }
    public class Test{
    public static void main(String argv[]){
           Test t = new Test();
        t.first();
       }
    public void first(){
           int i = 5;
           Value v = new Value();
          v.i = 25;
          second(v, i);
          System.out.println(v.i);
       }
    public void second(Value v, int i){
          i = 0;
           v.i = 20;
         Value val = new Value();
            v = val;
            System.out.println(v.i + " " + i);
          }
    }


    寫出下列程序的運行結果
    class MyThread extends Thread{
    public void run(){
    System.out.println("MyThread: run()");
    }
    public void start(){
    System.out.println("MyThread: start()");
        }
    }
    class MyRunnable implements Runnable{
    public void run(){
    System.out.println("MyRunnable: run()");
        }
    public void start(){
    System.out.println("MyRunnable: start()");
       }
    }
    public class MyTest {
    public static void main(String args[]){
    MyThread myThread  =  new MyThread();
    MyRunnable myRunnable = new MyRunnable();
    Thread thread  =  new Thread(myRunnable);
    myThread.start();
    thread.start();
    }
    }

    posted @ 2008-12-03 09:57 追風舞者 閱讀(397) | 評論 (0)編輯 收藏

    一、參考資料:

    1. Tuning Garbage Collection with the 5.0 Java Virtual Machine 官方指南。
    2. Hotspot memory management whitepaper 官方白皮書。
    3. Java Tuning White Paper 官方文檔。
    4. FAQ about Garbage Collection in the Hotspot  官方FAQ,JVM1.4.2。
    5. Java HotSpot 虛擬機中的垃圾收集 JavaOne2004上的中文ppt
    6. A Collection of JVM Options JVM選項的超完整收集。

    二、基本概念

    1、堆(Heap)

    JVM管理的內存叫堆。在32Bit操作系統上有1.5G-2G的限制,而64Bit的就沒有。

    JVM初始分配的內存由-Xms指定,默認是物理內存的1/64但小于1G。

    JVM最大分配的內存由-Xmx指定,默認是物理內存的1/4但小于1G。

    默認空余堆內存小于40%時,JVM就會增大堆直到-Xmx的最大限制,可以由-XX:MinHeapFreeRatio=指定。
    默認空余堆內存大于70%時,JVM會減少堆直到-Xms的最小限制,可以由-XX:MaxHeapFreeRatio=指定。

    服務器一般設置-Xms、-Xmx相等以避免在每次GC 后調整堆的大小,所以上面的兩個參數沒啥用。 

    2.基本收集算法

    1. 復制:將堆內分成兩個相同空間,從根(ThreadLocal的對象,靜態對象)開始訪問每一個關聯的活躍對象,將空間A的活躍對象全部復制到空間B,然后一次性回收整個空間A。
      因為只訪問活躍對象,將所有活動對象復制走之后就清空整個空間,不用去訪問死對象,所以遍歷空間的成本較小,但需要巨大的復制成本和較多的內存。
    2. 標記清除(mark-sweep):收集器先從根開始訪問所有活躍對象,標記為活躍對象。然后再遍歷一次整個內存區域,把所有沒有標記活躍的對象進行回收處理。該算法遍歷整個空間的成本較大暫停時間隨空間大小線性增大,而且整理后堆里的碎片很多。
    3. 標記整理(mark-sweep-compact):綜合了上述兩者的做法和優點,先標記活躍對象,然后將其合并成較大的內存塊。

        可見,沒有免費的午餐,無論采用復制還是標記清除算法,自動的東西都要付出很大的性能代價。

    3.分代

        分代是Java垃圾收集的一大亮點,根據對象的生命周期長短,把堆分為3個代:Young,Old和Permanent,根據不同代的特點采用不同的收集算法,揚長避短也。

    Young(Nursery),年輕代。研究表明大部分對象都是朝生暮死,隨生隨滅的。因此所有收集器都為年輕代選擇了復制算法。
        復制算法優點是只訪問活躍對象,缺點是復制成本高。因為年輕代只有少量的對象能熬到垃圾收集,因此只需少量的復制成本。而且復制收集器只訪問活躍對象,對那些占了最大比率的死對象視而不見,充分發揮了它遍歷空間成本低的優點。

        Young的默認值為4M,隨堆內存增大,約為1/15,JVM會根據情況動態管理其大小變化。
        -XX:NewRatio= 參數可以設置Young與Old的大小比例,-server時默認為1:2,但實際上young啟動時遠低于這個比率?如果信不過JVM,也可以用-Xmn硬性規定其大小,有文檔推薦設為Heap總大小的1/4。

        Young的大小非常非常重要,見“后面暫停時間優先收集器”的論述。

        Young里面又分為3個區域,一個Eden,所有新建對象都會存在于該區,兩個Survivor區,用來實施復制算法。每次復制就是將Eden和第一塊Survior的活對象復制到第2塊,然后清空Eden與第一塊Survior。Eden與Survivor的比例由-XX:SurvivorRatio=設置,默認為32。Survivio大了會浪費,小了的話,會使一些年輕對象潛逃到老人區,引起老人區的不安,但這個參數對性能并不重要。 

    Old(Tenured),年老代。年輕代的對象如果能夠挺過數次收集,就會進入老人區。老人區使用標記整理算法。因為老人區的對象都沒那么容易死的,采用復制算法就要反復的復制對象,很不合算,只好采用標記清理算法,但標記清理算法其實也不輕松,每次都要遍歷區域內所有對象,所以還是沒有免費的午餐啊。

    -XX:MaxTenuringThreshold=設置熬過年輕代多少次收集后移入老人區,CMS中默認為0,熬過第一次GC就轉入,可以用-XX:+PrintTenuringDistribution查看。

    Permanent,持久代。裝載Class信息等基礎數據,默認64M,如果是類很多很多的服務程序,需要加大其設置-XX:MaxPermSize=,否則它滿了之后會引起fullgc()或Out of Memory。 注意Spring,Hibernate這類喜歡AOP動態生成類的框架需要更多的持久代內存。

    4.minor/major collection

        每個代滿了之后都會促發collection,(另外Concurrent Low Pause Collector默認在老人區68%的時候促發)。GC用較高的頻率對young進行掃描和回收,這種叫做minor collection
    而因為成本關系對Old的檢查回收頻率要低很多,同時對Young和Old的收集稱為major collection。
        System.gc()會引發major collection,使用-XX:+DisableExplicitGC禁止它,或設為CMS并發-XX:+ExplicitGCInvokesConcurrent。

    5.小結

    Young -- minor collection -- 復制算法

    Old(Tenured) -- major colletion -- 標記清除/標記整理算法

    三、收集器

    1.古老的串行收集器(Serial Collector)

        使用 -XX:+UseSerialGC,策略為年輕代串行復制,年老代串行標記整理。

    2.吞吐量優先的并行收集器(Throughput Collector)

        使用 -XX:+UseParallelGC ,也是JDK5 -server的默認值。策略為:
        1.年輕代暫停應用程序,多個垃圾收集線程并行的復制收集,線程數默認為CPU個數,CPU很多時,可用–XX:ParallelGCThreads=減少線程數。
        2.年老代暫停應用程序,與串行收集器一樣,單垃圾收集線程標記整理。

        所以需要2+的CPU時才會優于串行收集器,適用于后臺處理,科學計算。

        可以使用-XX:MaxGCPauseMillis= 和 -XX:GCTimeRatio 來調整GC的時間。

    3.暫停時間優先的并發收集器(Concurrent Low Pause Collector-CMS)

        前面說了這么多,都是為了這節做鋪墊......

        使用-XX:+UseConcMarkSweepGC,策略為:
        1.年輕代同樣是暫停應用程序,多個垃圾收集線程并行的復制收集。
        2.年老代則只有兩次短暫停,其他時間應用程序與收集線程并發的清除。

    3.1 年老代詳述

        并行(Parallel)與并發(Concurrent)僅一字之差,并行指多條垃圾收集線程并行,并發指用戶線程與垃圾收集線程并發,程序在繼續運行,而垃圾收集程序運行于另一個個CPU上。

        并發收集一開始會很短暫的停止一次所有線程來開始初始標記根對象,然后標記線程與應用線程一起并發運行,最后又很短的暫停一次,多線程并行的重新標記之前可能因為并發而漏掉的對象,然后就開始與應用程序并發的清除過程。可見,最長的兩個遍歷過程都是與應用程序并發執行的,比以前的串行算法改進太多太多了!!!

        串行標記清除是等年老代滿了再開始收集的,而并發收集因為要與應用程序一起運行,如果滿了才收集,應用程序就無內存可用,所以系統默認68%滿的時候就開始收集。內存已設得較大,吃內存又沒有這么快的時候,可以用-XX:CMSInitiatingOccupancyFraction=恰當增大該比率。

    3.2 年輕代詳述

       可惜對年輕代的復制收集,依然必須停止所有應用程序線程,原理如此,只能靠多CPU,多收集線程并發來提高收集速度,但除非你的Server獨占整臺服務器,否則如果服務器上本身還有很多其他線程時,切換起來速度就..... 所以,搞到最后,暫停時間的瓶頸就落在了年輕代的復制算法上。

        因此Young的大小設置挺重要的,大點就不用頻繁GC,而且增大GC的間隔后,可以讓多點對象自己死掉而不用復制了。但Young增大時,GC造成的停頓時間攀升得非常恐怖,比如在我的機器上,默認8M的Young,只需要幾毫秒的時間,64M就升到90毫秒,而升到256M時,就要到300毫秒了,峰值還會攀到恐怖的800ms。誰叫復制算法,要等Young滿了才開始收集,開始收集就要停止所有線程呢。

    3.3 持久代

    可設置-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled,使CMS收集持久代的類,而不是fullgc,netbeans5.5 performance文檔的推薦。

    4.增量(train算法)收集器(Incremental Collector)

    已停止維護,–Xincgc選項默認轉為并發收集器。

    四、暫停時間顯示

     加入下列參數 (請將PrintGC和Details中間的空格去掉,CSDN很怪的認為是禁止字句) 

    -verbose:gc -XX:+PrintGC Details  -XX:+PrintGCTimeStamps

    會程序運行過程中將顯示如下輸出

     9.211: [GC 9.211: [ParNew: 7994K->0K(8128K), 0.0123935 secs] 427172K->419977K(524224K), 0.0125728 secs]

     顯示在程序運行的9.211秒發生了Minor的垃圾收集,前一段數據針對新生區,從7994k整理為0k,新生區總大小為8128k,程序暫停了12ms,而后一段數據針對整個堆。

    對于年老代的收集,暫停發生在下面兩個階段,CMS-remark的中斷是17毫秒:

    [GC [1 CMS-initial-mark: 80168K(196608K)] 81144K(261184K), 0.0059036 secs] 

    [1 CMS-remark: 80168K(196608K)] 82493K(261184K),0.0168943 secs]

    再加兩個參數 -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime對暫停時間看得更清晰。

    五、真正不停的BEA JRockit 與Sun RTS2.0

       Bea的JRockit 5.0 R27 的特色之一是動態決定的垃圾收集策略,用戶可以決定自己關心的是吞吐量,暫停時間還是確定的暫停時間,再由JVM在運行時動態決定、改變改變垃圾收集策略。
       
       它的Deterministic GC的選項是-Xgcprio: deterministic,號稱可以把暫停可以控制在10-30毫秒,非常的牛,一句Deterministic道盡了RealTime的真諦。 不過細看一下文檔,30ms的測試環境是1 GB heap 和 平均  30% 的活躍對象(也就是300M)活動對象,2 個 Xeon 3.6 GHz  4G內存 ,或者是4 個Xeon 2.0 GHz,8G內存。

      最可惜JRockt的license很奇怪,雖然平時使用免費,但這個30ms的選項就需要購買整個Weblogic Real Time Server的license。 

      其他免費選項,有:

    • -Xgcprio:pausetime -Xpausetarget=210ms 
        因為免費,所以最低只能設置到200ms pause target。 200ms是Sun認為Real-Time的分界線。
    • -Xgc:gencon
      普通的并發做法,效率也不錯。

      JavaOne2007上有Sun的 Java Real-Time System 2.0 的介紹,RTS2.0基于JDK1.5,在Real-Time  Garbage Collctor上又有改進,但還在beta版狀態,只供給OEM,更怪。

    六、JDK 6.0的改進

    因為JDK5.0在Young較大時的表現還是不夠讓人滿意,又繼續看JDK6.0的改進,結果稍稍失望,不涉及我最頭痛的年輕代復制收集改良。

    1.年老代的標識-清除收集,并行執行標識
      JDK5.0只開了一條收集進程與應用線程并發標識,而6.0可以開多條收集線程來做標識,縮短標識老人區所有活動對象的時間。

    2.加大了Young區的默認大小
    默認大小從4M加到16M,從堆內存的1/15增加到1/7

    3.System.gc()可以與應用程序并發執行
    使用-XX:+ExplicitGCInvokesConcurrent 設置

    七、小結

    1. JDK5.0/6.0

    對于服務器應用,我們使用Concurrent Low Pause Collector,對年輕代,暫停時多線程并行復制收集;對年老代,收集器與應用程序并行標記--整理收集,以達到盡量短的垃圾收集時間。

    本著沒有深刻測試前不要胡亂優化的宗旨,命令行屬性只需簡單寫為:

    -server -Xms<heapsize>M -Xmx<heapsize>M -XX:+UseConcMarkSweepGC  -XX:+PrintGC Details  -XX:+PrintGCTimeStamps

    然后要根據應用的情況,在測試軟件輔助可以下看看有沒有JVM的默認值和自動管理做的不夠的地方可以調整,如-xmn 設Young的大小,-XX:MaxPermSize設持久代大小等。

    2. JRockit 6.0 R27.2

    但因為JDK5的測試結果實在不能滿意,后來又嘗試了JRockit,總體效果要好些。
     JRockit的特點是動態垃圾收集器是根據用戶關心的特征動態決定收集算法的,參數如下

     -Xms<heapsize>M -Xmx<heapsize>M -Xgcprio:pausetime -Xpausetarget=200ms -XgcReport -XgcPause -Xverbose:memory

    posted @ 2008-12-03 09:51 追風舞者 閱讀(218) | 評論 (0)編輯 收藏

    1.垃圾收集算法的核心思想

      Java語言建立了垃圾收集機制,用以跟蹤正在使用的對象和發現并回收不再使用(引用)的對象。該機制可以有效防范動態內存分配中可能發生的兩個危險:因內存垃圾過多而引發的內存耗盡,以及不恰當的內存釋放所造成的內存非法引用。

      垃圾收集算法的核心思想是:對虛擬機可用內存空間,即堆空間中的對象進行識別,如果對象正在被引用,那么稱其為存活對象,反之,如果對象不再被引用,則為垃圾對象,可以回收其占據的空間,用于再分配。垃圾收集算法的選擇和垃圾收集系統參數的合理調節直接影響著系統性能,因此需要開發人員做比較深入的了解。

    2.觸發主GC(Garbage Collector)的條件

      JVM進行次GC的頻率很高,但因為這種GC占用時間極短,所以對系統產生的影響不大。更值得關注的是主GC的觸發條件,因為它對系統影響很明顯。總的來說,有兩個條件會觸發主GC:
     

      ①當應用程序空閑時,即沒有應用線程在運行時,GC會被調用。因為GC在優先級最低的線程中進行,所以當應用忙時,GC線程就不會被調用,但以下條件除外。

      ②Java堆內存不足時,GC會被調用。當應用線程在運行,并在運行過程中創建新對象,若這時內存空間不足,JVM就會強制地調用GC線程,以便回收內存用于新的分配。若GC一次之后仍不能滿足內存分配的要求,JVM會再進行兩次GC作進一步的嘗試,若仍無法滿足要求,則 JVM將報“out of memory”的錯誤,Java應用將停止。

      由于是否進行主GC由JVM根據系統環境決定,而系統環境在不斷的變化當中,所以主GC的運行具有不確定性,無法預計它何時必然出現,但可以確定的是對一個長期運行的應用來說,其主GC是反復進行的。

    3.減少GC開銷的措施

      根據上述GC的機制,程序的運行會直接影響系統環境的變化,從而影響GC的觸發。若不針對GC的特點進行設計和編碼,就會出現內存駐留等一系列負面影響。為了避免這些影響,基本的原則就是盡可能地減少垃圾和減少GC過程中的開銷。具體措施包括以下幾個方面:

      (1)不要顯式調用System.gc()

      此函數建議JVM進行主GC,雖然只是建議而非一定,但很多情況下它會觸發主GC,從而增加主GC的頻率,也即增加了間歇性停頓的次數。

      (2)盡量減少臨時對象的使用

      臨時對象在跳出函數調用后,會成為垃圾,少用臨時變量就相當于減少了垃圾的產生,從而延長了出現上述第二個觸發條件出現的時間,減少了主GC的機會。

      (3)對象不用時最好顯式置為Null

      一般而言,為Null的對象都會被作為垃圾處理,所以將不用的對象顯式地設為Null,有利于GC收集器判定垃圾,從而提高了GC的效率。

      (4)盡量使用StringBuffer,而不用String來累加字符串(詳見blog另一篇文章JAVA中String與StringBuffer)

      由于String是固定長的字符串對象,累加String對象時,并非在一個String對象中擴增,而是重新創建新的String對象,如Str5=Str1+Str2+Str3+Str4,這條語句執行過程中會產生多個垃圾對象,因為對次作“+”操作時都必須創建新的String對象,但這些過渡對象對系統來說是沒有實際意義的,只會增加更多的垃圾。避免這種情況可以改用StringBuffer來累加字符串,因StringBuffer是可變長的,它在原有基礎上進行擴增,不會產生中間對象。

      (5)能用基本類型如Int,Long,就不用Integer,Long對象

      基本類型變量占用的內存資源比相應對象占用的少得多,如果沒有必要,最好使用基本變量。

      (6)盡量少用靜態對象變量

      靜態變量屬于全局變量,不會被GC回收,它們會一直占用內存。

      (7)分散對象創建或刪除的時間

      集中在短時間內大量創建新對象,特別是大對象,會導致突然需要大量內存,JVM在面臨這種情況時,只能進行主GC,以回收內存或整合內存碎片,從而增加主GC的頻率。集中刪除對象,道理也是一樣的。它使得突然出現了大量的垃圾對象,空閑空間必然減少,從而大大增加了下一次創建新對象時強制主GC的機會。

    4.gc與finalize方法

      ⑴gc方法請求垃圾回收

      使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請求Java的垃圾回收。需要注意的是,調用System.gc()也僅僅是一個請求。JVM接受這個消息后,并不是立即做垃圾回收,而只是對幾個垃圾回收算法做了加權,使垃圾回收操作容易發生,或提早發生,或回收較多而已。

      ⑵finalize方法透視垃圾收集器的運行

      在JVM垃圾收集器收集一個對象之前 ,一般要求程序調用適當的方法釋放資源,但在沒有明確釋放資源的情況下,Java提供了缺省機制來終止化該對象釋放資源,這個方法就是finalize()。它的原型為:

      protected void finalize() throws Throwable

      在finalize()方法返回之后,對象消失,垃圾收集開始執行。原型中的throws Throwable表示它可以拋出任何類型的異常。

      因此,當對象即將被銷毀時,有時需要做一些善后工作。可以把這些操作寫在finalize()方法里。

     

    java 代碼
    1. protected void finalize()    
    2.    {    
    3.    // finalization code here    
    4.    }  

     

    ⑶代碼示例

    java 代碼
    1. class Garbage{    
    2.    int index;    
    3.    static int count;    
    4.   
    5.    Garbage() {    
    6.    count++;    
    7.    System.out.println("object "+count+" construct");    
    8.    setID(count);    
    9.    }    
    10.   
    11.    void setID(int id) {    
    12.    index=id;    
    13.    }    
    14.   
    15.    protected void finalize() //重寫finalize方法    
    16.    {    
    17.    System.out.println("object "+index+" is reclaimed");    
    18.    }    
    19.   
    20.    public static void main(String[] args)    
    21.    {    
    22.    new Garbage();    
    23.    new Garbage();    
    24.    new Garbage();    
    25.    new Garbage();    
    26.    System.gc(); //請求運行垃圾收集器    
    27.    }    
    28.   
    29.  }  

    5.Java 內存泄漏
      由于采用了垃圾回收機制,任何不可達對象(對象不再被引用)都可以由垃圾收集線程回收。因此通常說的Java 內存泄漏其實是指無意識的、非故意的對象引用,或者無意識的對象保持。無意識的對象引用是指代碼的開發人員本來已經對對象使用完畢,卻因為編碼的錯誤而意外地保存了對該對象的引用(這個引用的存在并不是編碼人員的主觀意愿),從而使得該對象一直無法被垃圾回收器回收掉,這種本來以為可以釋放掉的卻最終未能被釋放的空間可以認為是被“泄漏了”。

      考慮下面的程序,在ObjStack類中,使用push和pop方法來管理堆棧中的對象。兩個方法中的索引(index)用于指示堆棧中下一個可用位置。push方法存儲對新對象的引用并增加索引值,而pop方法減小索引值并返回堆棧最上面的元素。在main方法中,創建了容量為64的棧,并64次調用push方法向它添加對象,此時index的值為64,隨后又32次調用pop方法,則index的值變為32,出棧意味著在堆棧中的空間應該被收集。但事實上,pop方法只是減小了索引值,堆棧仍然保持著對那些對象的引用。故32個無用對象不會被GC回收,造成了內存滲漏。

     

    java 代碼
    public class ObjStack {    
    1.    private Object[] stack;    
    2.    private int index;    
    3.    ObjStack(int indexcount) {    
    4.    stack = new Object[indexcount];    
    5.    index = 0;    
    6.    }    
    7.    public void push(Object obj) {    
    8.    stack[index] = obj;    
    9.    index++;    
    10.    }    
    11.    public Object pop() {    
    12.    index--;    
    13.    return stack[index];    
    14.    }    
    15.    }    
    16.    public class Pushpop {    
    17.    public static void main(String[] args) {    
    18.    int i = 0;    
    19.    Object tempobj;    
    20.   
    21. //new一個ObjStack對象,并調用有參構造函數。分配stack Obj數組的空間大小為64,可以存64個對象,從0開始存儲   
    22.    ObjStack stack1 = new ObjStack(64);   
    23.   
    24.    while (i < 64)    
    25.    {    
    26.    tempobj = new Object();//循環new Obj對象,把每次循環的對象一一存放在stack Obj數組中。    
    27.    stack1.push(tempobj);    
    28.    i++;    
    29.    System.out.println("第" + i + "次進棧" + "\t");    
    30.    }    
    31.   
    32.    while (i > 32)    
    33.    {    
    34.    tempobj = stack1.pop();//這里造成了空間的浪費。    
    35.    //正確的pop方法可改成如下所指示,當引用被返回后,堆棧刪除對他們的引用,因此垃圾收集器在以后可以回收他們。    
    36.    /*   
    37.    * public Object pop() {index - -;Object temp = stack [index];stack [index]=null;return temp;}   
    38.    */    
    39.    i--;    
    40.    System.out.println("第" + (64 - i) + "次出棧" + "\t");    
    41.    }    
    42.    }    
    43.    }  

     

    6.如何消除內存泄漏

      雖然Java虛擬機(JVM)及其垃圾收集器(garbage collector,GC)負責管理大多數的內存任務,Java軟件程序中還是有可能出現內存泄漏。實際上,這在大型項目中是一個常見的問題。避免內存泄漏的第一步是要弄清楚它是如何發生的。本文介紹了編寫Java代碼的一些常見的內存泄漏陷阱,以及編寫不泄漏代碼的一些最佳實踐。一旦發生了內存泄漏,要指出造成泄漏的代碼是非常困難的。因此本文還介紹了一種新工具,用來診斷泄漏并指出根本原因。該工具的開銷非常小,因此可以使用它來尋找處于生產中的系統的內存泄漏。

      垃圾收集器的作用

      雖然垃圾收集器處理了大多數內存管理問題,從而使編程人員的生活變得更輕松了,但是編程人員還是可能犯錯而導致出現內存問題。簡單地說,GC循環地跟蹤所有來自“根”對象(堆棧對象、靜態對象、JNI句柄指向的對象,諸如此類)的引用,并將所有它所能到達的對象標記為活動的。程序只可以操縱這些對象;其他的對象都被刪除了。因為GC使程序不可能到達已被刪除的對象,這么做就是安全的。

      雖然內存管理可以說是自動化的,但是這并不能使編程人員免受思考內存管理問題之苦。例如,分配(以及釋放)內存總會有開銷,雖然這種開銷對編程人員來說是不可見的。創建了太多對象的程序將會比完成同樣的功能而創建的對象卻比較少的程序更慢一些(在其他條件相同的情況下)。

      而且,與本文更為密切相關的是,如果忘記“釋放”先前分配的內存,就可能造成內存泄漏。如果程序保留對永遠不再使用的對象的引用,這些對象將會占用并耗盡內存,這是因為自動化的垃圾收集器無法證明這些對象將不再使用。正如我們先前所說的,如果存在一個對對象的引用,對象就被定義為活動的,因此不能刪除。為了確保能回收對象占用的內存,編程人員必須確保該對象不能到達。這通常是通過將對象字段設置為null或者從集合(collection)中移除對象而完成的。但是,注意,當局部變量不再使用時,沒有必要將其顯式地設置為null。對這些變量的引用將隨著方法的退出而自動清除。

      概括地說,這就是內存托管語言中的內存泄漏產生的主要原因:保留下來卻永遠不再使用的對象引用。

      典型泄漏

      既然我們知道了在Java中確實有可能發生內存泄漏,就讓我們來看一些典型的內存泄漏及其原因。

      全局集合

      在大的應用程序中有某種全局的數據儲存庫是很常見的,例如一個JNDI樹或一個會話表。在這些情況下,必須注意管理儲存庫的大小。必須有某種機制從儲存庫中移除不再需要的數據。

      這可能有多種方法,但是最常見的一種是周期性運行的某種清除任務。該任務將驗證儲存庫中的數據,并移除任何不再需要的數據。

      另一種管理儲存庫的方法是使用反向鏈接(referrer)計數。然后集合負責統計集合中每個入口的反向鏈接的數目。這要求反向鏈接告訴集合何時會退出入口。當反向鏈接數目為零時,該元素就可以從集合中移除了。

      緩存

      緩存是一種數據結構,用于快速查找已經執行的操作的結果。因此,如果一個操作執行起來很慢,對于常用的輸入數據,就可以將操作的結果緩存,并在下次調用該操作時使用緩存的數據。

      緩存通常都是以動態方式實現的,其中新的結果是在執行時添加到緩存中的。典型的算法是:

      檢查結果是否在緩存中,如果在,就返回結果。

      如果結果不在緩存中,就進行計算。

      將計算出來的結果添加到緩存中,以便以后對該操作的調用可以使用。

      該算法的問題(或者說是潛在的內存泄漏)出在最后一步。如果調用該操作時有相當多的不同輸入,就將有相當多的結果存儲在緩存中。很明顯這不是正確的方法。

      為了預防這種具有潛在破壞性的設計,程序必須確保對于緩存所使用的內存容量有一個上限。因此,更好的算法是:

      檢查結果是否在緩存中,如果在,就返回結果。

      如果結果不在緩存中,就進行計算。

      如果緩存所占的空間過大,就移除緩存最久的結果。

      將計算出來的結果添加到緩存中,以便以后對該操作的調用可以使用。

      通過始終移除緩存最久的結果,我們實際上進行了這樣的假設:在將來,比起緩存最久的數據,最近輸入的數據更有可能用到。這通常是一個不錯的假設。

      新算法將確保緩存的容量處于預定義的內存范圍之內。確切的范圍可能很難計算,因為緩存中的對象在不斷變化,而且它們的引用包羅萬象。為緩存設置正確的大小是一項非常復雜的任務,需要將所使用的內存容量與檢索數據的速度加以平衡。

      解決這個問題的另一種方法是使用java.lang.ref.SoftReference類跟蹤緩存中的對象。這種方法保證這些引用能夠被移除,如果虛擬機的內存用盡而需要更多堆的話。

      ClassLoader

      Java ClassLoader結構的使用為內存泄漏提供了許多可乘之機。正是該結構本身的復雜性使ClassLoader在內存泄漏方面存在如此多的問題。ClassLoader的特別之處在于它不僅涉及“常規”的對象引用,還涉及元對象引用,比如:字段、方法和類。這意味著只要有對字段、方法、類或ClassLoader的對象的引用,ClassLoader就會駐留在JVM中。因為ClassLoader本身可以關聯許多類及其靜態字段,所以就有許多內存被泄漏了。

      確定泄漏的位置

      通常發生內存泄漏的第一個跡象是:在應用程序中出現了OutOfMemoryError。這通常發生在您最不愿意它發生的生產環境中,此時幾乎不能進行調試。有可能是因為測試環境運行應用程序的方式與生產系統不完全相同,因而導致泄漏只出現在生產中。在這種情況下,需要使用一些開銷較低的工具來監控和查找內存泄漏。還需要能夠無需重啟系統或修改代碼就可以將這些工具連接到正在運行的系統上。可能最重要的是,當進行分析時,需要能夠斷開工具而保持系統不受干擾。

      雖然OutOfMemoryError通常都是內存泄漏的信號,但是也有可能應用程序確實正在使用這么多的內存;對于后者,或者必須增加JVM可用的堆的數量,或者對應用程序進行某種更改,使它使用較少的內存。但是,在許多情況下,OutOfMemoryError都是內存泄漏的信號。一種查明方法是不間斷地監控GC的活動,確定內存使用量是否隨著時間增加。如果確實如此,就可能發生了內存泄漏。

    posted @ 2008-12-03 09:41 追風舞者 閱讀(1305) | 評論 (1)編輯 收藏

    2008年10月10日

    public class Search {

        
    /**
         * 前提條件array數組已排序
         
    */
        
    public static boolean binarySearch(int[] array, int target) {
            
    boolean result = false;
            
    int bottom = 0;
            
    int top = array.length-1;
            
    while (bottom <= top) {
                
    int mid = (top + bottom) / 2;
                
    if (target == array[mid]) {
                    result 
    = true;
                    
    break;
                } 
    else if (target < array[mid]) {
                    top 
    = mid - 1;
                } 
    else if (target > array[mid]) {
                    bottom 
    = mid + 1;
                }
            }

            
    return result;
        }

        
    public static void main(String[] args) {
            
    int [] array = {1,3,5,7,9,10};
            
    boolean result = binarySearch(array, 10);
            System.out.println(result);
        }
    }

    posted @ 2008-10-10 16:19 追風舞者 閱讀(214) | 評論 (0)編輯 收藏

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;

    public class Hanoi {
        
    public static void main(String[] args) throws NumberFormatException,
                IOException {
            System.out.print(
    "請輸入盤數:");
            BufferedReader br 
    = new BufferedReader(new InputStreamReader(System.in));
            
    int n = Integer.parseInt(br.readLine());
            move(n, 
    'A''B''C');
        }

        
    /**
         * 將n個盤子借助b,從 a 移到 c
         
    */
        
    public static void move(int n, char a, char b, char c) {
            
    if (n == 1)
                System.out.println(
    "盤 " + n + " 由 " + a + " 移至 " + c);
            
    else {
                move(n 
    - 1, a, c, b);
                System.out.println(
    "盤 " + n + " 由 " + a + " 移至 " + c);
                move(n 
    - 1, b, a, c);
            }
        }
    }

    posted @ 2008-10-10 15:56 追風舞者 閱讀(201) | 評論 (0)編輯 收藏

    public class Sort {

        
    public static void quickSort(int[] array) {
            quickSort(array, 
    0, array.length - 1);
        }

        
    private static void quickSort(int[] array, int low, int high) {
            
    if (low < high) {
                
    int p = partition(array, low, high);
                quickSort(array, low, p 
    - 1);
                quickSort(array, p 
    + 1, high);
            }

        }

        
    private static int partition(int[] array, int low, int high) {
            
    int s = array[high];
            
    int i = low - 1;
            
    for (int j = low; j < high; j++) {
                
    if (array[j] < s) {
                    i
    ++;
                    swap(array, i, j);
                }
            }
            swap(array, 
    ++i, high);
            
    return i;
        }

        
    private static void swap(int[] array, int i, int j) {
            
    int temp;
            temp 
    = array[i];
            array[i] 
    = array[j];
            array[j] 
    = temp;
        }
        
        
    public static void main(String[] args) {
            
    int [] array = {2,5,3,7,4};
            quickSort(array);
            
    for(int i = 0;i<array.length;i++){
                System.out.println(array[i]);
            }
        }

    }

    posted @ 2008-10-10 15:39 追風舞者 閱讀(2054) | 評論 (4)編輯 收藏

    2008年9月19日

    在Ubuntu 8.04中查看顯卡是否裝好
    運行glxinfo | grep rendering
    如果顯示”direct rendering: Yes”,則已安裝

    1、下載驅動

    我下載的就是NVIDIA-Linux-x86_64-173.14.12-pkg2.run這個文件,下載后放到home目錄下吧。

     

    2、刪除原驅動包
    sudo apt-get -–purge remove nvidia-glx nvidia-glx-new
    然后刪除 /lib/linux-restricted-modules/2.6.22-14-generic/文件夾下面帶有nvidia字樣的內容,注意里面有一個隱藏文件.nvidia-new-installer也要刪掉

    這里是內核自帶的驅動

    再檢查一下這兩個文件是否存在,/etc/init.d/nvidia-glx /etc/init.d/nvidia-kernel 如果存在,刪除掉。

    3、安裝要用到的軟件
    sudo apt-get install build-essential pkg-config xserver-xorg-dev linux-headers-`uname -r`

    安裝編譯包。

    我在安裝的時候提示說沒有lib,驅動安裝時候要安裝Kernel Interface,如果采用自己編譯的方式則要求系統中有libc的源碼。我想一般人都是沒有的,呵呵。這個時候我們可以在安裝驅動之前先自己把這個源碼給安裝好,問題就解決了。如何安裝?呵呵,更簡單,強大的 apt install阿, 運行:
    sudo apt-get install libc6-dev
    一行命令搞定。

    4、備份
    備份文件是一個好習慣。
    sudo cp /etc/default/linux-restricted-modules-common ~/linux-restricted-modules-common.backup
    sudo cp /etc/X11/xorg.conf ~/xorg.conf.backup

    5、禁止系統使用默認的驅動
    sudo gedit /etc/default/linux-restricted-modules-common
    在最后的雙引號中添加nv nvidia_new,即把文件中的“”,改成“nv nvidia_new”
    如果前面第二步刪除完整了其實也可以不用執行這一步。

    6、將后面的操作記錄在紙上,因為后面會完全在終端字符界面下操作。

    7、停止GDM進程
    sudo /etc/init.d/gdm stop
    按Ctrl+Alt+F1,登錄后進入第7步。

    8、安裝驅動
    進入下好的驅動所在目錄
    執行:sudo sh ./NVIDIA-Linux-x86_64-173.14.12-pkg2.run

    安裝過程中

    如果提示有舊驅動,詢問是否刪除舊驅動,選Yes;
    如果提示缺少某某模塊(modules),詢問是否上網下載,選no;
    如果提示編譯模塊,詢問是否進行編譯,選ok;
    如果提示將要修改Xorg.conf,詢問是否允許,選Yes;

    接下來就是等待安裝完成。

    9、安裝完成就回到終端,重啟GDM
    sudo /etc/init.d/gdm restart

    如果失敗,就重啟機子:sudo shutdown -r now

    好了,當看到NV的logo后,才表示安裝成功。

    如果不想看NVIDIA的LOGO,可以修改 /etc/X11/xorg.conf
    在Section “Device”中添加Option “NoLogo” “True”

    如:
    Section “Device”
    Identifier “通用顯示卡”
    Driver “nvidia”
    Option “NoLogo” “True”
    EndSection

    10.顯示高級設置
    如果想進行顯示方面的高級設置,在終端下輸入:nvidia-settings命令。

    左邊第二項是設置分辨率(server display configuration),從右邊的resolution中選擇分辨率,再點擊apply,

    預覽一下,不好取消就行了。

    至此,安裝完畢。

    如果御載的話就用這個命令

    sh NVIDIA-Linux-x86_64-173.14.12-pkg2.run –uninstall

    安裝成功,就這么簡單,一般nvidia 會自動配置好所有~`

    重新配置x server:
    sudo apt-get install pkg-config xserver-xorg-dev3
    sudo dpkg-reconfigure xserver-xorg



    posted @ 2008-09-19 13:23 追風舞者 閱讀(510) | 評論 (0)編輯 收藏

    2008年9月18日

    安裝MySQL

    sudo apt-get install mysql-server

    這個應該很簡單了,而且我覺得大家在安裝方面也沒什么太大問題,所以也就不多說了,下面我們來講講配置。

    配置MySQL

    注意,在Ubuntu下MySQL缺省是只允許本地訪問的,如果你要其他機器也能夠訪問的話,那么需要改變/etc/mysql/my.cnf配置文件了!下面我們一步步地來:

    默認的MySQL安裝之后根用戶是沒有密碼的,所以首先用根用戶進入:

    $mysql -u root

    在這里之所以用-u root是因為我現在是一般用戶(firehare),如果不加-u root的話,mysql會以為是firehare在登錄。注意,我在這里沒有進入根用戶模式,因為沒必要。一般來說,對mysql中的數據庫進行操作, 根本沒必要進入根用戶模式,只有在設置時才有這種可能。

    進入mysql之后,最要緊的就是要設置Mysql中的root用戶密碼了,否則,Mysql服務無安全可言了。

    mysql> GRANT ALL PRIVILEGES ON *.* TO root@localhost IDENTIFIED BY "123456";

    注意,我這兒用的是123456做為root用戶的密碼,但是該密碼是不安全的,請大家最好使用大小寫字母與數字混合的密碼,且不少于8位。

    這樣的話,就設置好了MySQL中的root用戶密碼了,然后就用root用戶建立你所需要的數據庫。我這里就以xoops為例:

    mysql>CREATE DATABASE xoops;

    mysql>GRANT ALL PRIVILEGES ON xoops.* TO xoops_root@localhost IDENTIFIED BY "654321";

    這樣就建立了一個xoops_roots的用戶,它對數據庫xoops有著全部權限。以后就用xoops_root來對xoops數據庫進行管理,而無需要再用root用戶了,而該用戶的權限也只被限定在xoops數據庫中。

    如果你想進行遠程訪問或控制,那么你要做兩件事:

    其一:

    mysql>GRANT ALL PRIVILEGES ON xoops.* TO xoops_root@"%" IDENTIFIED BY "654321";

    允許xoops_root用戶可以從任意機器上登入MySQL。

    其二:

    $sudo gedit /etc/mysql/my.cnf

    老的版本中

    >skip-networking => # skip-networking

    新的版本中

    >bind-address=127.0.0.1 => bind-address= 你機器的IP

    這樣就可以允許其他機器訪問MySQL了。

    posted @ 2008-09-18 17:53 追風舞者 閱讀(180) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 亚洲一区二区影院| 天天综合亚洲色在线精品| 成人免费一级毛片在线播放视频 | 国产精品另类激情久久久免费| 曰批免费视频播放免费| 亚洲AV成人一区二区三区AV| 亚洲第一成年免费网站| caoporn国产精品免费| 亚洲妓女综合网99| 亚洲人AV永久一区二区三区久久| 久久亚洲免费视频| 美国免费高清一级毛片| 97亚洲熟妇自偷自拍另类图片| 日韩免费视频观看| 91视频免费网址| 成人a毛片视频免费看| 亚洲精品**中文毛片| 亚洲精品A在线观看| 国产一卡2卡3卡4卡2021免费观看| 一级女性全黄生活片免费看| 亚洲一区二区三区久久| 国内精品久久久久久久亚洲| 午夜爱爱免费视频| 97在线视频免费公开观看| 午夜成人无码福利免费视频| 亚洲一区二区免费视频| 国产成A人亚洲精V品无码| 国产zzjjzzjj视频全免费| 亚洲免费福利在线视频| 色播在线永久免费视频网站| 国产精品观看在线亚洲人成网| 亚洲熟妇色自偷自拍另类| 亚洲国产精品无码av| 四虎成人精品在永久免费| 韩国免费一级成人毛片| 国产永久免费高清在线| 一本大道一卡二大卡三卡免费| 亚洲AV一区二区三区四区| 久久久久精品国产亚洲AV无码| 久久国产亚洲电影天堂| 国产AV无码专区亚洲AWWW|