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

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

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

    posts - 23,  comments - 3,  trackbacks - 0
     
    http://blog.csdn.net/watchnight/archive/2010/01/26/5258532.aspx

    沒有一個平臺獨立的方法能夠在所有的JVM上實現。一個最簡單、最接近取得PID的辦法是使用:

    ManagementFactory.getRuntimeMXBean().getName() 。

    取得到的字符竄的格式為[PROCESS_ID]@[MACHINE_NAME],通過解析這個字符串就可以得到java進程的PID。

    在以下平臺上測試通過:

    1、Windows、Linux上的Sun JDK1.5、JDK6

    2、HP-UX上的JDK1.5、JDK6

    3、Linux上的JRockit  R27.6



    posted @ 2010-07-01 16:06 temper 閱讀(1014) | 評論 (0)編輯 收藏
    將jvm.dll拷貝到JavaService.exe所在目錄(也可以通過設置path實現)
    參照:http://forge.ow2.org/forum/forum.php?thread_id=2330&forum_id=625

    ps:推薦通過設置path來實現,畢竟這樣對用戶和空間需求改動最小。
    參照:http://www.tmro.net/2008/05/jboss-service-on-windows-server-2003/
    posted @ 2010-06-25 14:28 temper 閱讀(383) | 評論 (0)編輯 收藏

    原文:http://roylone.blog.163.com/blog/static/378674132008816104325127/


    一、相關概念


    基本回收算法

    1. 引用計數(Reference Counting)
      比較古老的回收算法。原理是此對象有一個引用,即 增加一個計數,刪除一個引用則減少一個計數。垃圾回收時,只用收集計數為0的對象。此算法最致命的是無法處理循環引用的問題。
    2. 標記-清除(Mark-Sweep)
      此算法執行分兩階段。第一階段從引用根節點開始標記所 有被引用的對象,第二階段遍歷整個堆,把未標記的對象清除。此算法需要暫停整個應用,同時,會產生內存碎片。
    3. 復制(Copying)
      此算法把內存空間劃為兩個相等的區域,每次只使用其中一個區域。垃 圾回收時,遍歷當前使用區域,把正在使用中的對象復制到另外一個區域中。次算法每次只處理正在使用中的對象,因此復制成本比較小,同時復制過去以后還能進 行相應的內存整理,不過出現“碎片”問題。當然,此算法的缺點也是很明顯的,就是需要兩倍內存空間。
    4. 標記-整理(Mark-Compact)
      此算法結合了“標記-清除”和“復制”兩個算法的 優點。也是分兩階段,第一階段從根節點開始標記所有被引用對象,第二階段遍歷整個堆,把清除未標記對象并且把存活對象“壓縮”到堆的其中一塊,按順序排 放。此算法避免了“標記-清除”的碎片問題,同時也避免了“復制”算法的空間問題。
    5. 增量收集(Incremental Collecting)
      實施垃圾回收算法,即:在應用 進行的同時進行垃圾回收。不知道什么原因JDK5.0中的收集器沒有使用這種算法的。
    6. 分代(Generational Collecting)
      基于對對象生命周期分析后得出的 垃圾回收算法。把對象分為年青代、年老代、持久代,對不同生命周期的對象使用不同的算法(上述方式中的一個)進行回收。現在的垃圾回收器(從 J2SE1.2開始)都是使用此算法的。

    分代垃圾回收詳述


    如上圖所示,為Java堆中的各代分布。

    1. Young(年輕代)
      年輕代分三個區。一個Eden區,兩個Survivor區。大部分對象在 Eden區中生成。當Eden區滿時,還存活的對象將被復制到Survivor區(兩個中的一個),當這個Survivor區滿時,此區的存活對象將被復 制到另外一個Survivor區,當這個Survivor去也滿了的時候,從第一個Survivor區復制過來的并且此時還存活的對象,將被復制“年老區 (Tenured)”。需要注意,Survivor的兩個區是對稱的,沒先后關系,所以同一個區中可能同時存在從Eden復制過來 對象,和從前一個Survivor復制過來的對象,而復制到年老區的只有從第一個Survivor去過來的對象。而且,Survivor區總有一個是空 的。
    2. Tenured(年老代)
      年老代存放從年輕代存活的對象。一般來說年老代存放的都是生命期 較長的對象。
    3. Perm(持久代)
      用于存放靜態文件,如今Java類、方法等。持久代對垃圾回收沒有顯著 影響,但是有些應用可能動態生成或者調用一些class,例如Hibernate等,在這種時候需要設置一個比較大的持久代空間來存放這些運行過程中新增 的類。持久代大小通過-XX:MaxPermSize=<N>進行設置。

    GC類型
    GC有兩種類型:Scavenge GC和Full GC
    1. Scavenge GC
      一般情況下,當新對象生成,并且在Eden申請空間失敗時,就好觸發Scavenge GC,堆Eden區域進行GC,清除非存活對象,并且把尚且存活的對象移動到Survivor區。然后整理Survivor的兩個區。
    2. Full GC
      對整個堆進行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此應該盡可能減少Full GC。有如下原因可能導致Full GC:
      • Tenured被寫滿
      • Perm域被寫滿
      • System.gc()被顯示調用
      • 上一次GC之后Heap的各域分配策略動態變化


    分代垃圾回收過程演示




    二、垃圾回收器


    目前的收集器主要有三種:串行 收集器、并行收集器、并發收集器

    1. 串行收集器

      使用單線程處理所有垃圾回收工作,因為無需多線程交互,所以效率比較高。但是,也 無法使用多處理器的優勢,所以此收集器適合單處理器機器。當然,此收集器也可以用在小數據量(100M左右)情況下的 多處理器機器上。可以使用-XX:+UseSerialGC打開。
    2. 并行收集器
       
      1. 對年輕代進行并行垃圾回收,因此可以減少垃圾回收時間。一般在多線程多處理器機器上使用。使用-XX:+UseParallelGC. 打開。并行收集器在J2SE5.0第六6更新上引入,在Java SE6.0中進行了增強--可以堆年老代進行并行收集。如果年老代不使 用并發收集的話,是使用單線程進行垃圾回收,因此會制約擴展能力。使用-XX:+UseParallelOldGC打 開。
      2. 使用-XX:ParallelGCThreads=<N>設置并行垃圾回收的線程數。此 值可以設置與機器處理器數量相等
      3. 此收集器可以進行如下配置:
        • 最大垃圾回收暫停:指定垃圾回收時的最長暫停時間,通過-XX:MaxGCPauseMillis=<N>指 定。<N>為毫秒.如果指定了此值的話,堆大小和垃圾回收相關參數會進行調整以達到指定值。設定此值可能 會減少應用的吞吐量。
        • 吞吐量:吞吐量為垃圾回收時間與非垃圾回收時間的比值,通過-XX:GCTimeRatio=<N>來 設定,公式為1/(1+N)。例如,-XX:GCTimeRatio=19時,表示5%的時間用于垃圾回收。默認情況 為99,即1%的時間用于垃圾回收。
    3. 并發收集器
      可以保證大部分工作都并發進行(應用不停止),垃圾回收只暫停很少的時間,此收 集器適合對響應時間要求比較高的中、大規模應用。使用-XX:+UseConcMarkSweepGC打開。
       
      1. 并發收集器主要減少年老代的暫停時間,他在應用不停止的情況下使用獨立的垃圾回收線程,跟蹤可達對象。在每個年老代垃圾回收周期中,在收集初期并 發收集器會對整個應用進行簡短的暫停,在收集中還會再暫停一次。第二次暫停會比第一次稍長,在此過程中多個線程同時進行垃圾回收工作。
      2. 并發收集器使用處理器換來短暫的停頓時間。在一個N個處理器的系統上,并發收集部分使用K/N個 可用處理器進行回收,一般情況下1<=K<=N/4
      3. 在只有一個處理器的主機上使用并發收集器,設置為incremental mode模式也可獲得較短的停頓時間。
      4. 浮動垃圾:由于在應用運行的同時進行垃圾回收,所以有些垃圾可能在垃圾回收進行完成時產生,這樣就 造成了“Floating Garbage”,這些垃圾需要在下次垃圾回收周期時才能回收掉。所以,并發收集器一般需要20%的 預留空間用于這些浮動垃圾。
      5. Concurrent Mode Failure:并發收集器在應用運行時進行收集,所以需要保證 堆在垃圾回收的這段時間有足夠的空間供程序使用,否則,垃圾回收還未完成,堆空間先滿了。這種情況下將會發生“并發模式失敗”,此時整個應用將會暫停,進 行垃圾回收。
      6. 啟動并發收集器:因為并發收集在應用運行時進行收集,所以必須保證收集完成之前有足夠的內存空間供 程序使用,否則會出現“Concurrent Mode Failure”。通過設置-XX:CMSInitiatingOccupancyFraction=<N>指 定還有多少剩余堆時開始執行并發收集
    4. 小結
      • 串行處理器:
         --適用情況:數據量比較小(100M左右);單處理器下并且對響應時間無要求的應 用。
         --缺點:只能用于小型應用
      • 并行處理器:
         --適用情況:“對吞吐量有高要求”,多CPU、對應用響應時間無要求的 中、大型應用。舉例:后臺處理、科學計算。
         --缺點:應用響應時間可能較長
      • 并發處理器:
         --適用情況:“對響應時間有高要求”,多CPU、對應用響應時間有較高要 求的中、大型應用。舉例:Web服務器/應用服務器、電信交換、集成開發環境。

    三、常見配置舉例
    1. 堆大小設置
      JVM 中最大堆大小有三方面限制:相關操作系統的數據模型(32-bt還是64-bit)限制;系統的可用虛擬內存限制;系統的可用物理內存限制。32位系統 下,一般限制在1.5G~2G;64為操作系統對內存無限制。我在Windows Server 2003 系統,3.5G物理內存,JDK5.0下測試,最大可設置為1478m。
      典型設置:
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
        -Xmx3550m: 設置JVM最大可用內存為3550M。
        -Xms3550m: 設置JVM促使內存為3550m。此值可以設置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內存。
        -Xmn2g:設置年輕代大小為2G。整個堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為 64m,所以增大年輕代后,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8。
        -Xss128k: 設置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應用的線程所需內存大小進行調整。在相同物理內 存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。
      • java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
        -XX:NewRatio=4: 設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的 1/5
        -XX:SurvivorRatio=4:設置年輕代中 Eden區與Survivor區的大小比值。設置為4,則兩個Survivor區與一個Eden區的比值為2:4,一個Survivor區占整個年輕代的 1/6
        -XX:MaxPermSize=16m:設置持久代大小為16m。
        -XX:MaxTenuringThreshold=0: 設置垃圾最大年齡。如果設置為0的話,則年輕代對象不經過Survivor區,直接進入年 老代。對于年老代比較多的應用,可以提高效率。如果將此 值設置為一個較大值,則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活時間,增加在年 輕代即被回收的概論。
    2. 回收器選擇
      JVM給了三種選擇:串行收集器、并行收集器、并發收集器, 但是串行收集器只適用于小數據量的情況,所以這里的選擇主要針對并行收集器和并發收集器。默認情況下,JDK5.0以前都是使用串行收集器,如果想使用其 他收集器需要在啟動時加入相應參數。JDK5.0以后,JVM會根據當前系統配置進行判斷。
      1. 吞吐量優先的并行收集器
        如上文所述,并行收集器主要以到達一定的吞吐量為目標,適用于科學技術和后臺 處理等。
        典型配置
        • java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
          -XX:+UseParallelGC: 選擇垃圾收集器為并行收集器。此配置僅對年輕代有效。即上述配置下,年輕代使用并發收集, 而年老代仍舊使用串行收集。
          -XX:ParallelGCThreads=20: 配置并行收集器的線程數,即:同時多少個線程一起進行垃圾回收。此值最好配置與處理器數目相等。
        • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
          -XX:+UseParallelOldGC: 配置年老代垃圾收集方式為并行收集。JDK6.0支持對年老代并行收集。
        • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100
          -XX:MaxGCPauseMillis=100:設 置每次年輕代垃圾回收的最長時間,如果無法滿足此時間,JVM會自動調整年輕代大小,以滿足此值。
        • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
          -XX:+UseAdaptiveSizePolicy
          : 設置此選項后,并行收集器會自動選擇年輕代區大小和相應的Survivor區比例,以達到目標系統規定的最低相應時間或者收集頻率等,此值建議使用并行收 集器時,一直打開。
      2. 響應時間優先的并發收集器
        如上文所述,并發收集器主要是保證系統的響應時間,減少垃圾收集 時的停頓時間。適用于應用服務器、電信領域等。
        典型配置
        • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
          -XX:+UseConcMarkSweepGC: 設置年老代為并發收集。測試中配置這個以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此時年輕代大小最好 用-Xmn設置。
          -XX:+UseParNewGC:設 置年輕代為并行收集。可與CMS收集同時使用。JDK5.0以上,JVM會根據系統配置自行設置,所以無需再設置此值。
        • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
          -XX:CMSFullGCsBeforeCompaction: 由于并發收集器不對內存空間進行壓縮、整理,所以運行一段時間以后會產生“碎片”,使得運行效率降低。此值設置運行多少次GC以后對內存空間進行壓縮、整 理。
          -XX:+UseCMSCompactAtFullCollection:打開對年 老代的壓縮。可能會影響性能,但是可以消除碎片
    3. 輔助信息
      JVM提供了大量命令行參數,打印信息,供調試使用。主要有以下一些:
      • -XX:+PrintGC
        輸出形式:[GC 118250K->113543K(130112K), 0.0094143 secs]

                        [Full GC 121376K->10414K(130112K), 0.0650971 secs]

      • -XX:+PrintGCDetails
        輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]

                        [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

      • -XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可與上面兩個混合使用
        輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
      • -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收 前,程序未中斷的執行時間。可與上面混合使用
        輸出形式:Application time: 0.5291524 seconds
      • -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期間程序暫 停的時間。可與上面混合使用
        輸出形式:Total time for which application threads were stopped: 0.0468229 seconds
      • -XX:PrintHeapAtGC:打印GC前后的詳細堆棧信息
        輸出形式:
        34.702: [GC {Heap before gc invocations=7:
         def new generation   total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
        eden space 49152K,  99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
        from space 6144K,  55% used [0x221d0000, 0x22527e10, 0x227d0000)
          to   space 6144K,   0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
         tenured generation   total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
        the space 69632K,   3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
         compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
           the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
            ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
            rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
        34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
         def new generation   total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
        eden space 49152K,   0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
          from space 6144K,  55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
          to   space 6144K,   0% used [0x221d0000, 0x221d0000, 0x227d0000)
         tenured generation   total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
        the space 69632K,   4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
         compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
           the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
            ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
            rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
        }
        , 0.0757599 secs]
      • -Xloggc:filename:與上面幾個配合使用,把相關日志信息記錄到文件以便分析。
    4. 常見配置匯總
      1. 堆設置
        • -Xms:初始堆大小
        • -Xmx:最大堆大小
        • -XX:NewSize=n:設置年輕代大小
        • -XX:NewRatio=n:設置年輕代和年老代的比值。如:為3,表示年輕代與年老代比值為 1:3,年輕代占整個年輕代年老代和的1/4
        • -XX:SurvivorRatio=n:年輕代中Eden區與兩個Survivor區的比值。注 意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區占整個年輕代的1/5
        • -XX:MaxPermSize=n:設置持久代大小
      2. 收集器設置
        • -XX:+UseSerialGC:設置串行收集器
        • -XX:+UseParallelGC:設置并行收集器
        • -XX:+UseParalledlOldGC:設置并行年老代收集器
        • -XX:+UseConcMarkSweepGC:設置并發收集器
      3. 垃圾回收統計信息
        • -XX:+PrintGC
        • -XX:+PrintGCDetails
        • -XX:+PrintGCTimeStamps
        • -Xloggc:filename
      4. 并行收集器設置
        • -XX:ParallelGCThreads=n:設置并行收集器收集時使用的CPU數。并行收集線程數。
        • -XX:MaxGCPauseMillis=n:設置并行收集最大暫停時間
        • -XX:GCTimeRatio=n:設置垃圾回收時間占程序運行時間的百分比。公式為 1/(1+n)
      5. 并發收集器設置
        • -XX:+CMSIncrementalMode:設置為增量模式。適用于單CPU情況。
        • -XX:ParallelGCThreads=n:設置并發收集器年輕代收集方式為并行收集時,使 用的CPU數。并行收集線程數。

    四、 調優總結
    1. 年輕代大小選擇
      • 響應時間優先的應用盡可能設大,直到接近系 統的最低響應時間限制(根據實際情況選擇)。在此種情況下,年輕代收集發生的頻率也是最小的。同時,減少到達年老代的對 象。
      • 吞吐量優先的應用:盡可能的設置大,可能到達Gbit的程度。因為對響應時間沒有要求,垃圾收集可 以并行進行,一般適合8CPU以上的應用。
    2. 年老代大小選擇
      • 響應時間優先的應用:年老代使用并發收集器,所以其大小需要小心設置,一般要考慮并發會話率會 話持續時間等一些參數。如果堆設置小了,可以會造成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式;如果堆大了,則需要較 長的收集時間。最優化的方案,一般需要參考以下數據獲得:
        • 并發垃圾收集信息
        • 持久代并發收集次數
        • 傳統GC信息
        • 花在年輕代和年老代回收上的時間比例
        減少年輕代和年老代花費的時間,一般會提高應用的效率
      • 吞吐量優先的應用:一般吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代。原因是,這樣可 以盡可能回收掉大部分短期對象,減少中期的對象,而年老代盡存放長期存活對象。
    3. 較小堆引起的碎片問題
      因為年老代的并發收集器使用標記、清除算法,所以不會對堆進行壓縮。 當收集器回收時,他會把相鄰的空間進行合并,這樣可以分配給較大的對象。但是,當堆空間較小時,運行一段時間以后,就會出現“碎片”,如果并發收集器找不 到足夠的空間,那么并發收集器將會停止,然后使用傳統的標記、清除方式進行回收。如果出現“碎片”,可能需要進行如下配置:
      • -XX:+UseCMSCompactAtFullCollection:使用并發收集器時,開啟對年老代的壓縮。
      • -XX:CMSFullGCsBeforeCompaction=0:上面配置開啟的情況下,這里設置多少次Full GC后,對年老代進行壓縮
    posted @ 2010-06-25 14:21 temper 閱讀(164) | 評論 (0)編輯 收藏
    http://blog.csdn.net/ai_33/archive/2008/06/10/2529096.aspx

    關于中文文件下載的問題,網上的咨詢和答疑已經很多,我原來處理下載的代碼如下:
        
        response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
     下載的程序里有了這句,一般在IE6的下載提示框上將正確顯示文件的名字,無論是簡體中文,還是日文。不過當時確實沒有仔細測試文件名很長的中文文件名。先如今經過仔細測試,發現文字只要超過17個字,就不能下載了。經過好一番google和反復測試,總算對這個問題有了系統的認識,分列如下:

        . 通過我原來的方式,也就是先用URLEncoder編碼,當中文文字超過17個時,IE6 無法下載文件。這是IE的bug,參見微軟的知識庫文章 KB816868 。原因可能是因為ie在處理 Response Header 的時候,對header的長度限制在150字節左右。而一個漢字編碼成UTF-8是9個字節,那么17個字便是153個字節,所以便會報錯。微軟提供了一個補丁,可以從 這里 下載。這個補丁需要先安裝ie6 sp1。因為我平時勤打補丁,我的IE6版本號是 6.0.2800.1106.xpsp2_xxxxx。所以我可能已經安裝過了補丁,從而可以下載,但仍然出現文件名被截斷的現象。微軟讓我們等待IE下一個service pack的發布。我今天也上網看到了好消息,迫于firefox的壓力,IE7可能在年中發布。另外,Firefox 不支持這樣的方式,將把編碼后的%xx%xx直接作為文件名顯示。


        . 我嘗試使用 javamail 的MimeUtility.encode()方法來編碼文件名,也就是編碼成 =?gb2312?B?xxxxxxxx?= 這樣的形式,并從 RFC1522 中找到對應的標準支持。不過很遺憾,IE6并不支持這一個標準。我試了一下,Firefox是支持的。

        . 按網上很多人提供的解決方案:將文件名編碼成ISO8859-1似乎是有效的解決方案,代碼如下:
        
        response.setHeader( "Content-Disposition", "attachment;filename="  + new String( fileName.getBytes("gb2312"), "ISO8859-1" ) );
        
        在確保附件文件名都是簡體中文字的情況下,那么這個辦法確實是最有效的,不用讓客戶逐個的升級IE。如果臺灣同胞用,把gb2312改成big5就行。但現在的系統通常都加入了國際化的支持,普遍使用UTF-8。如果文件名中又有簡體中文字,又有繁體中文,還有日文。那么亂碼便產生了。另外,在我的電腦上Firefox(v1.0-en)下載也是亂碼。

        折中考慮,我結合了一、三的方式,代碼片斷如下:

            String fileName = URLEncoder.encode(atta.getFileName(), "UTF-8");
            /*
             * see http://support.microsoft.com/default.aspx?kbid=816868
             */
            if (fileName.length() > 150) {
                String guessCharset = xxxx /*根據request的locale 得出可能的編碼,中文操作系統通常是gb2312*/
                fileName = new String(atta.getFileName().getBytes(guessCharset), "ISO8859-1");
            }
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            
        暫且不考慮 Firefox 是因為它目前似乎還沒有有力侵食到IE的企業用戶市場。影響客戶買單的常常是進度,而不是兼容度。
    posted @ 2009-05-08 17:30 temper 閱讀(1359) | 評論 (0)編輯 收藏
    曾經在系統中使用了一個從網上弄來的可編輯select,根據需要做了一些修改,在ie6下面運行正常。昨晚突然收到領導郵件說不好用。了解完才知道是在ie8下面出問題,每次把鼠標放到那個黃色的按鈕上面,都會出現一個action.do的提示。
    此button對應的js是:
    esHTML='<div id='+this.divname+'>'
             
    +'<table id='+this.tablename+' cellpadding=0 cellspacing=0 class=select><tr><td bgcolor=#FFFFFF>'
             
    +'<input type=text class=selecttext size="'+size+'" name='+name+' value="'+defaulttext+'" '+readonly+'><td><button class=selectbutton id='+this.buttonname+'>6</td></tr></table>'
             
    +'</div>'
    ps:俺們以前一直只支持ie6,這就是不做網站的好處。
    趕緊下載一個ie8裝上,確認此問題,然后滿世界的找資料。說實話,也沒找到。
    后來一氣之下試驗了一下另外一種寫法,居然好用了,希望牛人給點解釋。
    esHTML='<div id='+this.divname+'>'
             
    +'<table id='+this.tablename+' cellpadding=0 cellspacing=0 class=select><tr><td bgcolor=#FFFFFF>'
             
    +'<input type=text class=selecttext size="'+size+'" name='+name+' value="'+defaulttext+'" '+readonly+'><td><input type="button" class="selectbutton" id='+this.buttonname+' value="6"/></td></tr></table>'
             
    +'</div>'
    看來要趕緊學習了,不然ie9出來我就得去要飯了。
    posted @ 2009-04-03 15:23 temper 閱讀(114) | 評論 (0)編輯 收藏
    Hi   TOM,  
      I   have   a   problem   with   ref   cursors.I'll   try   to   explain   it(sorry   if   my   english   is    
      not   very   good).  
      I   have   2   databases   and   i   want   to   return   values   from   one   DBto   the   other.  
      In   the   DB   that   i   want   to   recieve   the   data   i   have   the   call(with   a   procedure)   and      
      i   create   a   variable    
      wich   the   type   is   REF   CURSOR   from   the   second   DB.   In   example:  
      --the   variable    
      vResultCursor   user_DB2.pk_k1.vSqlCursorD@DB2;    
      --where   pk1   is   a   package   in   which   i   declare   the   REF   CURSOR   variable  
      ..  
      --The   call  
      user_DB2.pk_k1.P_1@DB2(vResultCursor);  
      --where   P1   is   the   procedure   in   wich   i   open   the   cursor   and    
      after   that   i   want   to   work   with   this   cursor  
       
      loop            
      --vx   is   varchar2              
                      FETCH   vResultCursor   INTO   vx;  
                            EXIT   WHEN   vResultCursor%NOTFOUND;  
                            insert   into   tbl_probe   values   (sysdate,'vx',vx);              
                          commit;                          
                 
      end   loop;  
      close     vResultCursor;  
       
      In   the   first   DB   i   have   in   PK_K1   the   declaration   of   the   ref   cursor,   and   the    
      procedure   wich   open   the   dinamic  
        cursor:  
      CREATE     OR   REPLACE   PACKAGE   PK_K1   IS    
      TYPE   vSqlCursorD   IS   REF   CURSOR;  
      PROCEDURE   P_RESOLVECURSOR   (vSQLCURSOR   OUT   vSqlCursorD);  
      END   PK_K1;  
       
      CREATE   OR   REPLACE   PACKAGE   BODY   PK_K1   IS  
       
      PROCEDURE   P_RESOLVECURSOR   (vSQLCURSOR   OUT   vSqlCursorD)   IS  
      vSqlCursortxt   VARCHAR2(4096);  
      BEGIN  
      vSqlCursortxt:=   'SELECT   *   FROM   DUAL';  
      OPEN   vSQLCURSOR   FOR   vSqlCursortxt;  
      EXCEPTION  
                        WHEN   OTHERS   THEN  
                                    IF   (vSQLCURSOR%ISOPEN)   THEN  
                                            CLOSE   vSQLCURSOR;  
                                  END   IF;  
      END;    
      END   PK_K1;  
      The   problem   that   i   have   is,   that   if   i   make   a   procedure   in   the   package   PK_K1   and    
      i   call   the   procedure   P_RESOLVECURSOR  
      it   works,   but   when   i   call   from   the   other   DB   it   doesnt   work.   The   error   is   ERROR    
      ORA-01001   when   whe   make   the   FETCH  
      I   gave   the   EXECUTE   grant   from   one   DB   to   the   OTHER  
      GRANT   EXECUTE   ON   PK_K1   TO   USERDB1;  
      could   u   help   me?  
      Thanks    
         
       
       
      Followup:  
       
      ref   cursors   cannot   be   used   over   a   dblink   like   that.  
       
       
      http://download-east.oracle.com/docs/cd/B19306_01/appdev.102/b14261/sqloperations.htm#sthref1448  
       
      ....  
      Note:  
       
              *     Using   a   REF   CURSOR   variable   in   a   server-to-server   RPC   results   in   an    
      error.   However,   a   REF   CURSOR   variable   is   permitted   in   a   server-to-server   RPC   if    
      the   remote   database   is   a   non-Oracle   database   accessed   through   a   Procedural    
      Gateway.  
              *     LOB   parameters   are   not   permitted   in   a   server-to-server   RPC.  
       
      .....    
       
      Passing   a   cursor   from   one   DB   to   the   other     March   23,   2006  
      Reviewer:     Jorge     from   Spain  
       
      Thank   for   the   explanation,   we   solve   the   problem   opening   and   closing   the   cursor    
      in   one   DB   and   passig   the   data   to   the   other   server   in   an   TABLE   Object   by   means   of    
      a   function.  
      Thanks   a   lot     

      ==========================================================
    看來這幾天的努力白費了,氣憤啊
    posted @ 2009-03-30 16:58 temper 閱讀(146) | 評論 (0)編輯 收藏
    創建另一個數據庫的連接
    CREATE [PUBLIC] DATABASE LINK dblink
        [CONNECT TO user IDENTIFIED BY password]
        [USING 'connect_string']



    部署新版本
    java.util.zip.ZipException: invalid entry CRC (expected 0x0 but got 0xab633fa2)
     at java.util.zip.ZipInputStream.read(ZipInputStream.java:164)
     at java.util.jar.JarInputStream.read(JarInputStream.java:171)
     at java.io.BufferedInputStream.read1(BufferedInputStream.java:254)
     at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
     at java.util.jar.JarInputStream.getBytes(JarInputStream.java:88)
     at java.util.jar.JarInputStream.<init>(JarInputStream.java:65)
     at java.util.jar.JarInputStream.<init>(JarInputStream.java:43)
    原因:jdk版本不對
    posted @ 2009-03-27 13:22 temper 閱讀(179) | 評論 (0)編輯 收藏

    怎樣查看oracle當前的連接數呢?只需要用下面的SQL語句查詢一下就可以了。
    select * from v$session where username is not null

    select username,count(username) from v$session where username is not null group by username #查看不同用戶的連接數

    select count(*) from v$session   #連接數

    Select count(*) from v$session where status='ACTIVE' #并發連接數

    show parameter processes   #最大連接

    alter system set processes = value scope = spfile;重啟數據庫   #修改連接

    /home/oracle9i/app/oracle9i/dbs/init.ora

    /home/oracle9i/app/oracle9i/dbs/spfilexxx.ora ## open_cursor

    posted @ 2009-03-24 11:10 temper 閱讀(14941) | 評論 (0)編輯 收藏
    具體參見:http://wrapper.tanukisoftware.org
    網上的介紹基本上是自己寫個測試類,然后用warpper做成系統進程的。但是我們目前是一個比較大的java項目,經過一個多小時摸索,終于試驗成功。
    大概需要注意的地方如下:
    系統的配置文件放入bin目錄,系統打成包,放入lib,系統需要的其它第三方包也放入lib,配置wrapper.conf文件,將這些包都配入wrapper.java.classpath.[n].在wrapper.app.parameter.1中配入main方法所在的類。運行一下App.bat,看看是否成功。:)
    ps:詳細的配置請自己去網絡搜索,這只是對其中沒有提及的進行了補充。另外這次配置的項目不是web項目。
    posted @ 2008-12-11 14:08 temper 閱讀(351) | 評論 (0)編輯 收藏

     

    db2獲得剛插入的自增字段的值:
    values(identity_val_local())


    Select Top在不同數據庫中的使用用法:


    1. Oracle數據庫

    <CENTER><CCID_NOBR> SELECT * FROM TABLE1 WHERE ROWNUM<=N



    2. Infomix數據庫


    SELECT FIRST N * FROM TABLE1


    3. DB2數據庫


    SELECT * ROW_NUMBER() OVER(ORDER BY COL1 DESC) AS ROWNUM WHERE ROWNUM<=N


    或者


    SELECT COLUMN FROM TABLE FETCH FIRST N ROWS ONLY



    4. SQL Server數據庫


    SELECT TOP N * FROM TABLE1


    5. Sybase數據庫


    SET ROWCOUNT N
    GO
    SELECT * FROM TABLE1



    6. MySQL數據庫


    SELECT * FROM TABLE1 LIMIT N



    7. FoxPro數據庫


    SELECT * TOP N FROM TABLE ORDER BY COLUMN

    轉載自http://tech.techweb.com.cn/archiver/tid-243262.html
    posted @ 2008-11-03 10:32 temper 閱讀(148) | 評論 (0)編輯 收藏
    僅列出標題
    共3頁: 上一頁 1 2 3 下一頁 
    主站蜘蛛池模板: 亚洲∧v久久久无码精品| 国产亚洲人成无码网在线观看 | caoporm碰最新免费公开视频| 成年女性特黄午夜视频免费看| 亚洲一区在线免费观看| 国产91免费在线观看| 亚洲一区二区三区免费视频| 精品免费人成视频app| 亚洲av永久无码精品三区在线4 | 青青草无码免费一二三区| 亚洲av日韩av高潮潮喷无码| 无码精品国产一区二区三区免费| 亚洲AV区无码字幕中文色| 最新黄色免费网站| 亚洲综合av一区二区三区不卡 | 国产免费AV片在线播放唯爱网 | 午夜两性色视频免费网站| 亚洲成a人片在线不卡一二三区| 日本不卡视频免费| 国产精品无码永久免费888| 亚洲AV无码久久寂寞少妇| 在线日本高清免费不卡| 精品亚洲456在线播放| 免费大学生国产在线观看p| 国产日韩久久免费影院| 亚洲国产第一页www| 成年免费大片黄在线观看岛国 | 亚洲人成在线影院| 成人免费午夜在线观看| 春暖花开亚洲性无区一区二区 | 亚洲色偷偷av男人的天堂| 插B内射18免费视频| 日韩精品免费一线在线观看| 亚洲AV无码一区二区二三区软件 | 亚洲夂夂婷婷色拍WW47| 2048亚洲精品国产| 18禁美女裸体免费网站| 国产亚洲一卡2卡3卡4卡新区| 精品亚洲视频在线观看| 国产91免费视频| 日韩少妇内射免费播放|