paulwong

          #

          HotSpot 的垃圾收集 - 轉

          從J2SE 5.0開始,HotSpot JVM共包含四種垃圾收集器,它們全部基于分代算法。
          一、代的劃分
          HotSpot JVM中內存被劃分為三代:年幼代(young generation)、年長代(old generation)和永久代(permanent generation)。從邏輯上講,年幼代和年長代共同構成了Java堆,而永久代則被稱為方法區(method area)。除了一些大對象可能在年長區中直接分配外,大部分對象都在年幼區中創建;而年長區除了那些直接創建的大對象外,大部分對象都是在年幼區中歷經幾次垃圾收集而幸免于難后被提升過來的。永久代中則保存著已載入類型的相關信息,包含了類、方法和其他一些內部使用的元數據,所有這些信息同樣以對象的形式來組織和表示,雖然這些對象并不是Java對象,但是它們卻象Java對象一樣可以被同樣的垃圾收集器所收集;另外,java.lang.String類所管理的內在化的字符串緩存池也在該代中分配;雖然名字叫做“永久”代,但其中的對象并不是永久的,只是沿用了歷史名稱而已。
          年幼代由一個伊甸區(Eden Space)和兩個更小的生還區(Survivor Space)組成,如下圖所示(該圖為縮略圖,請點擊察看原圖)。大部分對象在伊甸區中創建,少數大對象可能在年長代中直接創建。生還區中保存的對象是歷經一次或多次對年幼代的垃圾收集而未死的幸存者,并且在被認為已足夠成熟而提升到年長代之前,它們仍有在稍后的某次垃圾收集過程中犧牲的可能。除非處在垃圾收集過程當中,兩個生還區中只有一個用來容納這些幸存者,另一個則保持為空。
          JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s5.sinaimg.cn/bmiddle/51501580g8169fb66ab44&690">

          二、垃圾收集類型
          年幼代填滿后,一次只針對該代的收集被執行,這樣的收集也被稱作“次收集(minor collection)”。當年長代或永久代被填滿后,一次針對所有代的完整收集被執行,這樣的收集也被稱作“主收集(major collection)”。通常來說,在一次主收集過程中,年幼代首先被收集,收集算法采用當前收集器的年幼代收集算法,該算法往往是針對年幼對象的行為特征而專門設計的;然后是對年長代和永久代的收集,收集算法都采用當前收集器的年長代收集算法。對于給定收集器所具體使用的年幼代和年長代收集算法,請參考下文。另外,主收集過程中如果存在壓縮,則每代獨自進行。
          不過,首先收集年幼代的策略在年長代空閑空間太小時會失效,因為年長代已無足夠的空間來接納所有的可能從年幼代提升過來的對象;在這種情況下,除CMS外的所有收集器都會放棄原有的年幼代收集算法,轉而統一采用年長代收集算法對所有代進行收集。(CMS收集器之所以例外是因為它的年長代算法不能用來收集年幼代。)

          三、快速分配
          從下文對垃圾收集器的描述中可以看出,在許多情況下,內存中都有大塊的連續空閑空間用以滿足對象的分配請求。這種情形下的分配操作使用簡單的“bump-the-pointer”技術,效率很高。按照這種技術,JVM內部維護一個指針(allocatedTail),它始終指向先前已分配對象的尾部,當新的對象分配請求到來時,只需檢查代中剩余空間(從allocatedTail到代尾geneTail)是否足以容納該對象,并在“是”的情況下更新allocatedTail指針并初始化對象。下面的偽代碼具體展示了從連續內存塊中分配對象時分配操作的簡潔性和高效性:
          void * malloc(int n){
          if( geneTail - allocatedTail < n )
          doGarbageCollection();
          void * wasAllocatedTail = allocatedTail;
          allocatedTail += n;
          return wasAllocatedTail;
          }
          對于多線程應用,分配操作必須是線程安全的。如果使用全局鎖為此提供保證,則分配操作必定成為一個性能瓶頸。基于此,HotSport JVM采用了一種被稱為“線程局部分配緩沖區”(Thread-Local Allocation Buffers,TLAB)的技術。該項技術為每個線程提供一個獨立的分配緩沖區(伊甸區的一小部分),借此來提高分配操作的吞吐量。因為針對每個TLAB,只有一個線程從中分配對象,故而分配操作可以使用“bump-the-pointer”技術快速完成,而不必使用任何鎖機制;只有當線程將其已有TLAB填滿并且需要獲取一個新的TLAB時,同步才是必須的。同時,為了減少TLAB所帶來的空間消耗,還使用了一些其他技術,例如,分配器能夠把TLAB的平均大小限制在伊甸區的1%以下。
          “bump-the-pointer”和TLAB技術的組合保證了分配操作的高效性,類似new Object()這樣的操作在大部分時間內只需要大約10條機器指令即可完成。

          四、收集方式
          1)串行(serial)和并行(parallel)
          串行和并行是從收集任務本身如何被完成的角度來描述收集過程的。采用串行方式收集時,同一時間只有一件事情會發生。例如,即使有多個CPU可用,還是只有一個被用來執行收集任務。當采用并行方式收集時,垃圾收集任務被分成許多子任務,并且那些子任務在不同的CPU上被同時執行。同時操作使收集任務得以更快地完成,代價是增加了任務的復雜性并可能產生內存碎片。2)STW(stop-the-world)和并發(concurrent)
          STW和并發是從收集任務是否影響應用程序執行的角度來描述收集過程的。當垃圾收集使用STW方式進行時,在收集期間應用程序將被完全掛起。作為另一種選擇,收集任務可以采取并發方式,與應用程序一起同時執行。比較典型的情況是,并發收集器采取并發方式完成大部分工作,但也可能偶爾地不得不切換到STW方式,以完成一些需要應用程序短暫停頓的工作。STW收集比并發收集更為簡單,因為在收集期間堆被凍結、對象不會改變;它的缺點是對某些應用程序來說,被暫停過久是不符合要求的。相對地,采用并發方式進行垃圾收集時,停頓時間會更短,但這也要求收集器必須更加小心,因為它正在操作可能被應用程序同時更新的對象。對并發收集器來說,這會增加額外開銷從而影響性能,也會對堆空間產生更大的需求。

          五、串行收集器(serial collector)
          使用串行收集器時,對年幼代和年長代的收集都采用串行、STW方式進行。也就是說收集任務同時只使用一個CPU,而且在收集任務執行期間,應用程序的執行被中止。
          1)串行收集器如何收集年幼代?
          下圖展示了使用串行收集器對年幼代進行收集時的操作細節。伊甸區中的活動對象被拷貝到初始為空的生還區2中;已占用的生還區1中的活動對象如果仍顯年輕,則同樣被拷貝到生還區2中,否則被直接拷貝到年長代;需要注意的是,生還區2一旦被填滿,則所有尚未被拷貝的活動對象,不論其來自伊甸區還是生還區1,也不論其曾經幸免于多少次次收集,統統被拷貝到年長代。按照定義,在活動對象被拷貝之后,伊甸區和生還區1中的對象就全部成為垃圾對象,無須再被檢查。(垃圾對象在圖中以“X”標記,雖然實際上收集器并不檢查和標記這些對象。) JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s4.sinaimg.cn/middle/51501580g81cfe5708d93&690"> 收集完成后,伊甸區和生還區1變為空閑空間,活動對象保存在生還區2中。此時,兩個生還區的角色已經發生了互換。如下圖:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s4.sinaimg.cn/middle/51501580g81d362167ce3&690"> 2)串行收集器如何收集年長代?
          串行收集器采用標記-清理-壓縮算法收集年長代和永久代。在標記階段,收集器遍歷引用樹,找出所有活動對象并打上標記;在清理階段,順序掃描代空間中所有對象(不論死活),計算出每個活動對象在代空間中的新位置;在壓縮階段,指向活動對象的所有引用被先期更新后,所有活動對象也被逐個滑動到其新的位置。由于所有活動對象都是按照次序朝代空間頭部移動的,因此就在代空間尾部自然形成了一個單一而連續的空閑空間。如下圖:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s3.sinaimg.cn/middle/51501580g81fd1aa883d2&690">壓縮過程使基于年長代或永久代的分配操作可以使用快速的“bump-the-pointer”技術。
          3)何時使用串行收集器?
          對于運行在客戶端級硬件上并且對停頓時間沒有特別要求的大多數應用而言,串行收集器都是首選。按照目前的硬件水平,串行收集器可以高效地管理使用64MB堆空間、最長停頓時間不能超過半秒的很多重要應用。
          4)串行收集器的選用
          在J2SE 5.0版本中,對于非服務器級硬件而言,串行收集器作為缺省的垃圾收集器被自動選用;對于其他硬件平臺,則可以通過命令行選項“-XX:+UseSerialGC”進行顯示的選用。

          六、并行收集器(parallel collector)
          目前,許多Java應用的運行平臺大都包含很多物理內存和多個CPU。并行收集器,也被稱作吞吐量收集器,被開發出來的主要目的就是為了充分利用CPU資源,而不是只讓一個CPU去做垃圾收集而其他CPU卻被閑置。
          1)并行收集器如何收集年幼代?
          和串行收集器相比,并行收集器采用了大致相同的年幼代收集算法,只是執行的是其并行版本而已。對年幼代的收集雖然仍基于拷貝技術、采用STW方式進行,但收集工作是并行展開的,使用了多個CPU,這就降低了垃圾收集開銷,從而提高了應用程序的吞吐量。下圖展示了并行收集器和串行收集器在執行年幼代收集時到底有何不同:
          JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s7.sinaimg.cn/middle/51501580g81e435e495a6&690">
          2)并行收集器如何收集年長代?
          和串行收集器一樣,并行收集器對年長代的收集同樣基于標記-清理-壓縮算法,同樣采用串行、STW方式進行。
          3)何時使用并行收集器?
          能夠得益于并行收集器的應用程序,必定運行在多CPU機器上,并且對停頓時間不能有特別的約束。因為可能持續時間很長的年長代收集雖然稀少,但還是會發生的。適于采用并行收集器的典型應用包括批處理、記帳、工資單和科學計算等等。你可能更傾向于選擇并行壓縮收集器(見下文)而不是并行收集器,因為前者對所有代(而不只是年幼代)的收集都采用并行方式進行。
          4)并行收集器的選用
          在J2SE 5.0版本中,對于服務器級硬件而言,并行收集器作為缺省的垃圾收集器被自動選用;對于其他硬件平臺,則可以通過命令行選項“-XX:+UseParallelGC”進行顯示的選用。

          七、并行壓縮收集器(parallel compacting collector)
          并行壓縮收集器在J2SE 5.0 U6中引入,它和并行收集器的區別在于,對年長代的收集它使用了全新的算法。注意:并行壓縮收集器終將取代并行收集器。
          1)并行壓縮收集器如何收集年幼代?
          同并行收集器,不再贅述。
          2)并行壓縮收集器如何收集年長代?
          使用并行壓縮收集器時,對年長代和永久代的收集都采用帶滑動壓縮的準并行、STW方式進行。為了滿足并行處理的要求,每一個代空間均被邏輯劃分為諸多定長區域(fixed-sized region),每個區域的相關信息保存在收集器維護的內部數據結構中。收集過程被分為標記、匯總和壓縮三個階段進行。在標記階段,根引用集被劃分給多個垃圾收集線程,它們同時運行,以并行的方式對活動對象進行追蹤和標記;在活動對象被標記的同時,該對象的起始區域的數據也將被同步更新以反映該活動對象的大小和位置信息。
          在匯總階段(summary phase),操作不再基于對象,而是區域。考慮到先前收集過程中的壓縮累積效應,每一個代空間中位于左側的某一部分通常是密集的,主要包含了活動對象。從這樣的密集區塊中可能回收的空間數量使得它們并不值得被壓縮。所以匯總階段的首要任務就是檢查區域的密集度,從最左邊一個區域開始,直到找到這樣的一個區域,使得在該區域及其右側所有區域中可被回收的空間數量抵得上對它們進行壓縮的成本。該區域左側的所有區域就被稱為密集前置區塊,沒有對象會被移入其中。該區域及其右側所有區域會被壓縮,以消除所有死區。匯總階段的下一個任務就是計算并保存每個被壓縮區域中活動數據的首字節在壓縮后的新位置。需要注意的是:匯總階段在目前被實現為一個串行階段,這也是“準”并行方式的由來;并行實現也是可能的,只是與標記和壓縮階段的并行化相比,它對性能的影響不大。
          在壓縮階段,垃圾收集線程使用匯總數據確定需要被填充的區域,然后它們就可以獨立地把對象拷貝到這些區域中而不再需要額外的同步。這就產生了一個堆,堆空間的一端塞滿了活動對象,而另一端則是一個單一而連續的空閑內存塊。
          3)何時使用并行壓縮收集器?
          和并行收集器一樣,并行壓縮收集器同樣有益于在多CPU機器上運行的應用程序。除此之外,年長代收集的并行化操作方式還減少了停頓時間,使得并行壓縮收集器比并行收集器更為適合那些有停頓時間限制的應用。不過,對于運行在大型共享主機(如SunRays)上的應用來說,并行壓縮收集器也許并不太合適,因為任何單一應用都不應長時間獨占幾個CPU。在這樣的機器上,要么考慮通過命令行選項“-XX:ParallelGCThreads=n”減少垃圾收集線程的數目,要么考慮選擇一種不同的收集器。
          4)并行壓縮收集器的選用
          并行壓縮收集器只能通過命令行選項“-XX:+UseParallelOldGC”進行顯示的選用。

          八、并發的標記-清理收集器(Concurrent Mark-Sweep(CMS) Collector)
          對于許多應用來說,端到端的吞吐量并不象響應時間那么重要。通常來講,對年幼代的收集并不會引起太長時間的停頓。但是對年長代的收集,雖然不常發生,卻可能導致停頓時間過長的狀況,在堆空間很大時尤其明顯。為了解決這個問題,HotSpot JVM包含了一個名叫“并發的標記-清理(CMS)收集器”的收集器,它也被稱為低延遲收集器。
          1)CMS收集器如何收集年幼代?
          同并行收集器,不再贅述。
          2)CMS收集器如何收集年長代?
          采用CMS收集器收集年長代時,大部分收集任務與應用程序并發執行。
          CMS收集器的收集周期始于初始標記,它采用串行、STW方式進行,用于確定根引用集。隨后進入并發標記階段,完成對所有活動對象的追蹤和標記,在JDK6中該階段已開始采用并行、并發方式進行。由于在并發標記過程中應用程序正在執行并可能更新了一些對象的引用域,因此并發標記過程結束時并非所有活動對象都已確保被標記出來。為了處理這種情況,應用程序再次暫停,收集過程進入再標記階段;它采用并行、STW方式進行,通過對并發標記過程中被修改對象的再次訪問最終完成整個標記過程。因為再標記階段的停頓時間往往是最長的(超過初始標記停頓甚至次收集停頓),因此再標記過程會盡量采用并行方式進行。
          再標記階段完成后,所有活動對象都已確保被標記,隨后進入并發清理階段,它采用串行、并發方式進行,就地回收所有垃圾對象。下圖展示了串行的標記-清理-壓縮收集器和CMS收集器在收集年長代時的區別: JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s13.sinaimg.cn/middle/51501580g82676852d74c&690"> 因為一些任務(例如再標記過程中對被修改對象的再次訪問)增加了收集器的工作量,CMS收集器的總體開銷自然會增大。對于大多數試圖減少停頓時間的收集器來說,這是一種典型的折衷。
          CMS收集器是唯一一個不使用壓縮技術的收集器。也就是說,在垃圾對象所占用的空間被釋放以后,收集器并不把活動對象全部推擠到代空間的某一端去。見下圖:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s3.sinaimg.cn/middle/51501580g82716466bed2&690">這種方式節省了回收時間,但卻因為空閑空間不再連續,收集器也就不再可能只使用一個簡單指針即可指示出可分配給新對象的下一個空閑空間的位置,相反,它現在需要使用空閑空間列表。也就是說,收集器創建并通過一組列表把內存中尚未分配的區域連接起來,每當有對象需要分配空間時,適當的列表(基于所需內存數量)被搜索,以找到一塊足以放下該對象的空閑區域。作為結果,與使用“bump-the-pointer”技術時相比,年長代中的分配操作變得更加昂貴。同時這也給年幼代收集帶來了額外的開銷,因為在其收集過程中每提升一個對象都會觸發一次年長代中的分配操作。
          CMS收集器的另一個缺點是和其他收集器相比它需要更大的堆空間。一方面,由于在標記階段應用程序被允許運行,它就可能繼續分配內存,從而可能使年長代空間不斷地增長;另一方面,雖然標記階段完成后所有活動對象都已確保被標記,但是在標記過程中一些對象卻可能變為垃圾對象,而且直到下次年長代收集之前它們不會被回收。這樣的對象也被稱為游浮垃圾。
          CMS收集器的最后一個缺點是由于缺乏壓縮它可能引發碎片化問題。為了對付碎片化,CMS收集器跟蹤對象的流行尺寸,預估未來需求,并為滿足需求還可能分割或合并空閑內存塊。
          不象其他收集器,CMS收集器并不是等到年長代填滿后才啟動對年長代的收集,而是嘗試盡早啟動年長代收集,以便在年長代被填滿之前收集過程可以完成。否則的話,CMS收集器將重新采用在串行和并行收集器中使用的標記-清理-壓縮算法,盡管該算法工作于STW方式,也更加耗時。為避免這種情況的發生,CMS收集器對先前收集所耗時間和代空間充滿所耗時間進行統計,并據此確定收集啟動時間。另外,當年長代的空間占用率超過啟動占用率(initiating occupancy)時,CMS收集器也將啟動一次收集。啟動占用率的值可以通過命令行選項“-XX:CMSInitiatingOccupancyFraction=n”進行設定,其中 n 表示年長代空間大小的百分比。缺省值為68。
          總的來說,與并行收集器相比,CMS收集器(有時甚至顯著地)減少了年長代收集的停頓時間,而代價是略有增加的年幼代收集的停頓時間、吞吐量方面的一些損失和額外的堆空間需求。
          3)增量模式
          CMS收集器可以采用讓并發階段增量完成的模式運行。這種模式通過對并發階段的周期性暫停把處理能力交還給應用程序,以減少并發階段持續時間過長所帶來的不利影響。收集工作被分成許多小的時間塊,它們在年幼代收集的間歇期被調度。當應用程序既需要CMS收集器提供的低停頓時間,又只能在很少的CPU(比如說1到2個)上運行時,這個特性就相當有用。
          4)何時使用CMS收集器?
          如果應用程序需要更短的垃圾收集停頓時間并且能夠承擔在運行時和垃圾收集器共享處理器資源,那么就可以使用CMS收集器。(由于其并發性,在垃圾收集過程中CMS收集器將和應用程序搶奪CPU周期。)通常來說,具有較大的長壽數據集并且運行在2個或多個CPU上的應用程序,更容易受益于CMS收集器的使用。一個典型的例子就是Web服務器。對于任何需要低停頓時間的應用程序來說,CMS收集器都值得考慮。對于年長代尺寸適中并且運行在單一處理器上的交互式應用程序來說,使用CMS收集器同樣可能取得不錯的效果。
          5)CMS收集器的選用
          CMS收集器只能通過命令行選項“-XX:+UseConcMarkSweepGC”進行顯示的選用。如果希望CMS收集器在增量模式下運行,還需要通過命令行選項“-XX:+CMSIncrementalMode”啟用該模式。

          九、收集器、堆尺寸和虛擬機的自動選擇
          在J2SE 5.0中,根據應用程序所運行的硬件平臺和操作系統,垃圾收集器、堆尺寸和HotSpot虛擬機(客戶機或服務器)的缺省值被自動選定。這些自動的選擇不僅減少了對命令行選項的使用,而且還更好的滿足了不同類型應用程序的需要。
          1)服務器級硬件(server-class machine,不使用“機器”這個詞是因為讀起來太拗口)的定義:
          服務器級硬件必須同時滿足以下兩個條件:
          ①擁有2個或以上的物理處理器
          ②擁有2GB或以上的物理內存
          該定義適用于所有平臺,32位Windows平臺除外。
          2)服務器級硬件與非服務器級硬件下各項缺省值的比較:
          機器類型 虛擬機 垃圾收集器 堆尺寸初始值-Xms 堆尺寸最大值-Xmx
          服務器級硬件 服務器版 并行收集器 物理內存的1/64,不超過1GB 物理內存的1/4,不超過1GB
          非服務器級硬件 客戶機版 串行收集器 4MB 64MB
          注意:本節所涉及的堆尺寸指的是Java堆的大小,包括年幼代和年長代,但不包括永久代。  

          posted @ 2011-10-30 20:47 paulwong 閱讀(349) | 評論 (0)編輯 收藏

          架構設計的一些關鍵點

          eBay 架構經驗
          1. Partition Everything 切分萬物
          2. Asynchrony Everywhere 處處異步
          3. Automate Everything 全部自動
          4. Remember Everything Fails 記錄失敗
          5. Embrace Inconsistency 親不同是謂大同
          6. Expect (R)evolution 預言演變
          7. Dependencies Matter 重視依賴
          8. Be Authoritative 獨斷專行
          9. Never Enough Data

          淘寶架構經驗
          1. Partition Everything 切分萬物
          2. 適當放棄一致性
          3. 備份和隔離解決穩定性問題
          4. 分割和異步解決性能問題(類似 eBay 的 Asynchrony Everywhere)
          5. 自動化降低人力成本(類似 eBay 的 Automate Everything)
          6. 產品化管理

          Flickr架構經驗
          1. 使得機器自動構建 (Teach machines to build themselves)
          2. 使得機器自監控(Teach machines to watch themselves)
          3. 使得機器自修復(Teach machines to fix themselves)
          4. 通過流程減少 MTTR (Reduce MTTR by streamlining)

          架構的關注點是系統。其全名本來也是系統架構。它是系統級的主題。它當然也屬于系統設計過程的一個部分。只是與面向對象聚焦于業務領域不同,它聚焦于解決所有系統共同的問題,或者說與業務邏輯無關的問題。
          上面所列出的技術,其實可以全部歸結為對以下技術的采用:
          1. 自動化
          2. 錯誤記錄
          3. 異步
          4. 接受不一致性即適當地放棄正確性
          5. 對系統進行適當的抽象定義(橫向與豎向。模塊與方面。數據分割。。。模塊,方面,分割的數據都是一種抽象。定義是為了管理。沒有定義就沒有管理。定義是管理的前提。要不然,“管理”什么?)
          6. 可進化性
          7. 面向用戶(即產品化。產品化指的是從產品的角度對產品進行包裝,,包括產品服務,錯誤,交互,UI等等)
          8. 隔離(管理依賴--剔除不必要的依賴,管理必要的依賴)
          9. 使得機器自監控(Teach machines to watch themselves)

          posted @ 2011-10-30 20:29 paulwong 閱讀(284) | 評論 (0)編輯 收藏

          在LINUX下配置JBOSS

          1. bin/run.sh
            export LANG=zh_CN.GB18030 //使用中文
            JBOSSCONF
            ="default" //SERVER中使用default
          2. bin/run.conf
            配置JAVA_OPTS
            if [ "x$JAVA_OPTS" = "x" ]; then
               JAVA_OPTS
            ="-Xms512m -Xmx2048m -XX:MaxPermSize=256m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dsun.lang.ClassLoader.allowArraySyntax=true -Djava.awt.headless=true "
               JAVA_OPTS
            ="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
            #   JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Djboss.platform.mbeanserver -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
               JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=10.0.122.132"
            fi
          3. /opt/jboss4.3/jboss-as/server/default/deploy/jboss-web.deployer
            改端口和綁定監聽所有的IP
                <Connector port="80" address="0.0.0.0"    
                     maxThreads
            ="250" maxHttpHeaderSize="8192"
                     emptySessionPath
            ="true" protocol="HTTP/1.1"
                     enableLookups
            ="false" redirectPort="8443" acceptCount="100"
                     connectionTimeout
            ="20000" disableUploadTimeout="true"
                compressableMimeType
            ="text/html,text/xml,text/plain,text/css,text/javascript,application/xhtml+xml,application/x-javascript,application/javascript,text/xhtml" />
          4. /opt/jboss4.3/jboss-as/server/default/conf/
            配置LOG4J
               <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
                  
            <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
                  
            <param name="File" value="${jboss.server.log.dir}/server.log"/>
                  
            <param name="Append" value="true"/>
                  
            <param name="Threshold" value="ERROR"/>

                  
            <!-- Rollover at midnight each day -->
                  
            <param name="DatePattern" value="'.'yyyy-MM-dd"/>

                  
            <!-- Rollover at the top of each hour
                  <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
                  
            -->

                  
            <layout class="org.apache.log4j.PatternLayout">
                     
            <!-- The default pattern: Date Priority [Category] Message\n -->
                     
            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>

                     
            <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n 
                     <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
                
            -->
                  
            </layout>
               
            </appender>
          5. /etc/profile
            配置JAVA_HOME等,改完后source /etc/profile,使配置生效
            JAVA_HOME=/usr/java/jdk1.6.0_29
            JRE_HOME
            =/usr/java/jdk1.6.0_29/jre
            PATH
            =$JAVA_HOME/bin:JRE_HOME/bin:$PATH 
            CLASSPATH
            =.:$JAVA_HOME/lib/jt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib 
            export JAVA_HOME JRE_HOME PATH CLASSPATH 
          6. 相關LINUX命令
            # cd /usr/local/jboss-4.2.3.GA/bin 
            #./run.sh //jboss的啟動
            #tail -f nohup.out //查看啟動信息
            #./shutdown.sh -S //jboss的停止
            #ps -ef |grep java //查看jboss的運行狀態
            #kill -9 后加PID //殺進程
            #netstat -ntpl //查看端口
            #iptables -F //清除所有防火墻限制

          posted @ 2011-10-28 10:18 paulwong 閱讀(1492) | 評論 (0)編輯 收藏

          開放 linux 防火墻 端口

          想搭個服務器,但外面訪問不到,是防火墻的原因,把端口設置一下就行。

          1.在/etc/sysconfig/iptables里添加
          -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -ACCEPT

          2.重啟iptables
          [root@localhost ~]# /etc/init.d/iptables restart

          3.看下狀態
          [root@localhost ~]# /etc/init.d/iptables status

          posted @ 2011-10-27 10:15 paulwong 閱讀(170) | 評論 (0)編輯 收藏

          JDK線程查看工具

          JDK和LINUX提供的查看當前運行的線程的工具: 
          1. KILL
            kill -3 [pid]:線程相關信息會列在Console上
          2. JSTACK
            jstack [pid]:查看線程運行狀況,如等鎖,運行等
          3. JCONSOLE
            jconsole -pluginpath [JTop.jar]:增加一個JTOP的標簽,可查看所有線程
            TthreadXMBean:在JCONSOLE中訪問此BEAN即可

          posted @ 2011-10-27 00:04 paulwong 閱讀(1359) | 評論 (0)編輯 收藏

          JDK內存管理工具比較

          JDK自帶了不少查看和管理內存的工具:
          1. JMAP
            jmap -heap [pid] : 文字形式查看JVM中堆內存,非堆內存等大小情況
            jmap -histo [pid] : 文字形式查看各種類占內存大小情況,但粒度只去到[C這種
            jmap -dump:format=b,file=文件名 [pid] : DUMP出內存快照,給其他工具分析內存提供依據
          2. JHAT
            jhat -J-Xms1024M 文件名:分析DUMP文件,并將結果以http://ip:7000向外提供,可具體到哪些對象
          3. MAT
            由于jhat分析大文件時速度慢,因此引入Eclipse Memory Analyzer,速度和功能強很多
          4. JSTAT
            jstat -gcutil [pid]:查看FULL GC的次數和消耗時間,統計
          5. JCONSOLE
            以圖形方式查看內存、線程、類、MBEAN等信息
          6. JVISUALVM
            是JCONSOLE的升級版,可查看內存、線程、各對象占內存的大小,JMAP/JHAT能做的都可以做到

          能用圖形查看的就用圖形方式查看,不能的就用文字形式代替。

          posted @ 2011-10-26 23:51 paulwong 閱讀(921) | 評論 (0)編輯 收藏

          配置遠程JCONSOLE

          JDK自帶工具JCONSOLE,可以以圖形界面遠程監控JVM的情況,也可作相應的一些操作。
          1、修改Tomcat的啟動語句,將bin/catalina.sh文件vi編輯:
          將原
          JAVA_OPTS="-Xmx1024M -Xms512M -Xss3M"
          export JAVA_OPTS
          調整為
          JAVA_OPTS="-Xmx1024M -Xms512M -Xss3M -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true"
          export JAVA_OPTS
          如果是JBOSS,還需加這一行
          JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=10.0.122.132",如果不加就連不上

          檢查LINUX環境:
          運行:hostname -i,如果返回127.0.0.1,則要改/etc/sysconfig/network里的HOSTNAME為NEWHOST,再在/etc/hosts里增加一行本機IP對應NEWHOST的值。
          清除防火墻的所有東西:iptables -F!!
          參考:http://dikar.iteye.com/blog/534109

          2、修改jmx配置文件
          目錄切換至JAVA_HOME所在目錄
          /jre/lib/management下,
          a、將jmxremote.access、jmxremote.password.template權限調整為讀寫;
          chmod 600 jmxremote.password.template
          chmod 600 jmxremote.access
          b、jmxremote.password.template文件重命名
          mv jmxremote.password.template jmxremote.password
          c、vi jmxremote.password
          去掉
          # monitorRole QED
          # controlRole R&D
          的#號(Solaris下可編輯模式下,可以使用x刪除光標標記處字符)
          :wq 保存操作
          3、啟動Tomcat
          ./catalina.sh run

          4、查看JMX啟動情況
          netstat -a | grep -i 9999 查看端口占有情況
          如機器9999端口被其他程序占用,可調整端口-Dcom.sun.management.jmxremote.port=????

          5、客戶端機器可通過jconsole或visualvm對其進行監控
          使用JMX方式,輸入url 用戶名(controlRole)、密碼(R&D)即可訪問
          url:遠程主機IP:9999
          用戶名及密碼(參考jmxremote.password文件) monitorRole只能讀,controlRole能讀寫

          配置中的安全原因出錯,由于密碼是以明文的方式保存在:jmxremote.password中,所以對此文件只能有所有者都讀取,其他人都不能讀取。WINDOWS下的設置情況見:http://1985wanggang.blog.163.com/blog/static/77638332010731101726156/

          JCONSOLE使用手冊:
          1.5:http://blog.sina.com.cn/s/blog_5dc29fcc0100xiex.html
          1.6:http://hornetblog.sinaapp.com/?p=5

          posted @ 2011-10-26 22:31 paulwong 閱讀(2223) | 評論 (0)編輯 收藏

          JVM參數調優

          JVM中用來放NEW出來的對象的內存叫堆內存,用來放CLASS等靜態的對象的內存叫非堆內存,如果不加指定,默認情況下就幾十兆。當遇上一些飯量大的家伙,如POI,導出上萬條數據時,就會報內存溢出。所以在生產環境要指定這些內存的大小。

          -server
          一定要作為第一個參數,會使JVM啟動速度變慢,但會顯著提升JVM性能

          -Xms<size>
          設置初始化時堆內存大小,有多大就設多大。設置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內存。

          -Xmx<size>
          設置堆內存最大值,有多大就設多大

          -XX:PermSize=300M
          設置初始化時非堆內存大小,一般為總內存的1/8

          -XX:MaxPermSize=300M 
          設置非堆內存最大值,一般為總內存的1/4

          -Xmn2g:設置年輕代大小為2G.整個堆大小=年輕代大小 + 年老代大小 + 持久代大小.持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小.此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8.

          -Xss128k: 設置每個線程的堆棧大小.JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K.更具應用的線程所需內存大小進行 調整.在相同物理內存下,減小這個值能生成更多的線程.但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右.

          -XX:NewRatio=4:設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代).設置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5

          -XX:SurvivorRatio=4:設置年輕代中Eden區與Survivor區的大小比值.設置為4,則兩個Survivor區與一個Eden區的比值為2:4,一個Survivor區占整個年輕代的1/6

          -XX:MaxTenuringThreshold=0: 設置垃圾最大年齡.如果設置為0的話,則年輕代對象不經過Survivor區,直接進入年老代. 對于年老代比較多的應用,可以提高效率.如果將此值設置為一個較大值,則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活 時間,增加在年輕代即被回收的概論.

          回收器選擇
          JVM給了三種選擇:串行收集器,并行收集器,并發收集器,但是串行收集器只適用于小數據 量的情況,所以這里的選擇主要針對并行收集器和并發收集器.默認 情況下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在啟動時加入相應參數.JDK5.0以后,JVM會根據當前系統配置進行判斷.
          吞吐量優先的并行收集器
          如上文所述,并行收集器主要以到達一定的吞吐量為目標,適用于科學技術和后臺處理等.
          典型配置:

          -XX:+UseParallelGC
          選擇垃圾收集器為并行收集器.此配置僅對年輕代有效.即上述配置下,年輕代使用并發收集,而年老代仍舊使用串行收集.

          -XX:ParallelGCThreads=20
          配置并行收集器的線程數,即:同時多少個線程一起進行垃圾回收.此值最好配置與處理器數目相等.

          -XX:+UseParallelOldGC
          配置年老代垃圾收集方式為并行收集.JDK6.0支持對年老代并行收集.

          -XX:MaxGCPauseMillis=100
          設置每次年輕代垃圾回收的最長時間,如果無法滿足此時間,JVM會自動調整年輕代大小,以滿足此值.

          -XX:+UseAdaptiveSizePolicy
          設置此選項后,并行收集器會自動選擇年輕代區大小和相應的Survivor區比例,以達到目標系統規定的最低相應時間或者收集頻率等,此值建議使用并行收集器時,一直打開.

          參考資料


          Tomcat – Java.Lang.OutOfMemoryError: PermGen Space
          http://www.mkyong.com/tomcat/tomcat-javalangoutofmemoryerror-permgen-space/


          實例講解JVM參數調優的八條經驗
          http://developer.51cto.com/art/200907/134761.htm

          posted @ 2011-10-25 20:43 paulwong 閱讀(391) | 評論 (0)編輯 收藏

          對象池

               摘要: 如果一個B/S的應用,并發量在2000以上時,新建的對象累積會占用大量內存,當超過一定數量的時候,會報內存不夠,使用享元模式就可以解決這一問題,也就是建立對象池。現在的方案可以使用Apache Commons Pool。一、基本String對象測試 Code highlighting produced by Actipro CodeHighlighter (freeware) htt...  閱讀全文

          posted @ 2011-10-23 17:02 paulwong 閱讀(354) | 評論 (0)編輯 收藏

          T60升級內存的問題

          最近T60使用ECLIPSE時老報內存不夠,機器原本用的是2G的內存,因此打算升級內存,看了網上的各種文章,決定采用直接換成2根2G,組成4G的內存使用,由于之前說法,32位的操作系統只能認3G的內存,有1G是沒用上的,結果也是這樣,但說裝上RAMDISK后,可以將那1G內存轉成內存硬盤,給虛擬內存用,因此也不會浪費,結果試了N多次,虛擬硬盤用的內存不是額外的那1G,最后查資料,結論如下:如果要他顯示4G要滿足如下條件:

          1. 要在PC中使用超過4GB的內存,需要同時滿足以下若干條件
          (1)主板配置有支持至少8GB內存尋址的芯片組(例如Intel P965/P975)
          (2)CPU支持X64指令集(例如Intel Core2處理器)
          (3)BIOS支持memory remapping
          (4)使用64bit的操作系統(或支持物理內存擴展技術的32bit操作系統)

          2. Intel 945芯片組或更早期的芯片組,受到32bit的限制,最大只能尋址到4GB,也就是說只能訪問4GB以內的地址。但是這4GB地址并不是完全留給內存使用的,與此同時,各種接口、IO設備都還需要分配大量的尋址空間(例如顯卡通常就要占用數百MB),所以最后留給系統物理內存這一硬件的尋址空間,就只剩下3GB多一些。而操作系統也只能識別到這么多的物理內存。因此,如果PC系統的硬件達不到以上第一點中的(1)(2)(3)條時,即使在系統中安裝超過4GB的內存,能夠被識別的物理內存也只有4GB,而留給操作系統使用的只有3GB多一些。

          3. 操作系統對識別的內存數也有影響。32bit的操作系統只具備4GB的尋址能力,即使硬件滿足上述使用4GB內存的條件,限于操作系統的尋址空間限制,必須要保留數百MB的尋址空間給各種接口和IO設備,因此操作系統仍然最多只可以用到3GB多一些的物理內存。而64bit的操作系統下,因為把各種接口和IO設備所占用的地址空間移到更靠后的地址段,因此4GB物理內存可以完全尋址,也就是完全識別使用。再延伸一下,同理可以推斷,假設某64bit操作系統的最大尋址能力是8GB,而系統安裝了8GB的物理內存,那么操作系統可以識別并使用的內存也就是7GB多一些。

          芯片組的問題,浪費了1G內存。

          posted @ 2011-10-15 23:49 paulwong 閱讀(2813) | 評論 (0)編輯 收藏

          僅列出標題
          共115頁: First 上一頁 95 96 97 98 99 100 101 102 103 下一頁 Last 
          主站蜘蛛池模板: 宁德市| 遵义县| 长兴县| 金沙县| 秦安县| 湟中县| 郑州市| 巨鹿县| 石家庄市| 丹巴县| 策勒县| 沙湾县| 裕民县| 青海省| 龙江县| 扶余县| 盖州市| 鞍山市| 朔州市| 香港| 灵川县| 昭通市| 福州市| 杭锦后旗| 精河县| 株洲市| 磐石市| 元氏县| 湘乡市| 门源| 隆回县| 锡林郭勒盟| 突泉县| 横峰县| 隆子县| 峨山| 灵寿县| 莱西市| 汝州市| 乐至县| 安康市|