原文地址:http://apmblog.compuware.com/2011/05/11/how-garbage-collection-differs-in-the-three-big-jvms/
========================================================================================
Hotspot JVM使用和 IBM Websphere及 OracleWeblogic不同的垃圾回收機制,但是垃圾回收的概念和算法是相通的。
HotSpotJVM
1)HotSpotJVM使用內存分區(如永久perm區和分代Generation Heap區),分代區(Generation Heap區)又包括新生Yong區和老生Old/Tenured區,Yong區中又分為Eden區和 Survior區(2塊);
2)Yong區 GC:對象先在Yong區的Eden中得到分配,任何時候Eden區滿了就會觸發Yong區GC (Minor GC?),會把Yong區Eden中仍存活的Live對象拷貝到空的那個Survior區,除此之外,另外一個Survior區中的對象也會被檢查和拷貝(在2個Survior區之間拷貝對象的頻率是可配置的),其結果就是對象僅存在于一個Survior區中,而Eden區和另一塊Survior區是空的。這種形式的GC叫“拷貝收集(Copy Collection)”。Yong區中多次GC后仍存活的對象會被提升/拷貝到Old區。
3) Old區 GC:標記和打掃(Mark & Sweep)算法是老生區(OldHeap)使用的GC算法,與新生代Yong區算法不同的地方在于它不拷貝對象。對象越多GC消耗時間越長,因此老生區GC代價很高并盡量避免,因此我們需要保證對象僅僅從Yong區拷貝到Old區并保證Old區不被填滿,因此,代區的大小是Hotspot JVM中單一的一個最重要的優化參數。如果我們不能阻止對象從Yong區拷貝到Old區,我們可以使用“并發標記和打掃算法”(CMS -Concurrent Mark and Sweep),此算法可以并行的進行收集操作。(停頓時間:串行(Serial) <平行(Parallel) <并發(Concurrent))。
Old區GC還有其他問題,比如“碎片問題”會導致“慢分配”,更長的打掃時間并最終會導致OOM(當分配大對象而遇到的全是小空間時).
碎片問題可通過被稱為“壓縮”的方法來解決。“串行和平行算法(Serialand Parallel)”會在每次Old區進行GC時進行壓縮,它不對整個Old區壓縮而只對Old區中碎片程度達到一定Level的區域區進行。相比之下,“并發標記和打掃算法CMS”根本就不會進行壓縮。當對象不能再被分配時,一個串行的“主要MajorGC”會被觸發。
因此,HotSpot 的第二個調整參數是選擇正確的GC策略,GC策略的選擇會影響應用的性能,HotSpot中的大部分GC策略調整選項參數是是關于分片和壓縮的, HotspotJVM沒有提供太多調整參數,因此,唯一的方法是優化代碼減少申請對象的次數。
4) Permanent Generation 永久區:保存屬于類的(靜態的)屬性和字符串常量等,永久區的GC只會發生在“主要Major GC”時(Major GC很少發生),因此很多人認為Hotspot JVM在永久區根本不會GC。
Major GC - “Stops the world” and“cost much time”, e.g. Full GC.
OracleJRockit
1) Oracle WebLogic使用的JVM,將來會和Hotspot合并
2) Heap策略 -也使用“分代Heap”,而且支持一個所謂的“連續Heap”。分代Heap分為:老生區(Old/Tenured)和苗圃/新生區(Nursery),當對象被申請時,他們被放在一個新生區中稱為Keep Area的地方,在GC時,Keep Area不會被考慮而其它仍然存活的對象會被馬上移到老生區。因此,新生區的大小是JRockit很重要的參數。JRockit在第二次新生代GC時就會拷貝那些對象到Old區。
JRockit的“連續Heap”不區分“新”和“老”的對象,常常在特定的情況下比如以大吞吐量下的批量任務會產生很好的性能,它是JRockit Server JVM模式下的默認設置,而且往往不是正確的選擇,因為典型的Web應用不是面向吞吐量而是面向響應時間,因此人們往往會選擇低停頓時間模式和分代GC策略。
3) CMS -
大部分的CMS標記階段可分為4個部分
1. 初始標記 -標記生成Live對象的Root集合 - Java Thread會被paused
2 并發標記 -根據root集合中的對象查找并標記其引用的Live對象 -- Java Thread正常運行
3 預清理 -找出“并發標記”發現的需要修改的地方并發現和標記其它額外的Live對象-- Java Thread正常運行
4 最終標記-找出在預清理階段發現的需要改變的地方并發現和標記其它額外的Live對象 -- Java Thread會被Paused
CMS 打掃階段也和 Application并發執行, 但和Hotspot JVM的分2個階段相比,JRockit會先清掃Heap的第一半部分,在此階段,線程會被允許在Heap的第二半部分進行對象申請。在一個短暫的同步停頓后,會打掃第二半部分然后會有一個短暫的最后的停頓期。
因此,JRockit的算法比HotSpot的算法停頓更多,但是標記階段會短一些。而且它不像HotSpot JVM那樣可以通過調整未用內存的百分比來觸發GC。
4) 壓縮
JRockit 在所有的Old老生區GC進行壓縮,包括CMS。它通過一種按Heap中分區增量的模式進行的,這些各類參數可以調整,比如按堆百分比壓縮,或最大多少對象會被壓縮,而且你可以完全把壓縮關掉或者在GC時進行“完全壓縮”。因此可配置性比HotSpot更強。
5) 線程本地分配TLA(Thread Local Allocation)
JRockit默認使用線程本地分配TLA,這允許線程不需要同步即可分配對象,這將有利于分配速度,TLA的大小而且可以配置,大的TLA可以優化使用大量線程本地分配對象的應用,另一方面,太大的TLA會導致更多的碎片,因為TLA是被線程以排斥的方式獨有的,因此受限于線程數并依賴于應用的架構。
6) 大對象和小對象
JRockit在分配大對象和小對象時區別對待,大小的定義在JVM的版本不同而不同,常常2-128Kb之間,大對象在線程本地意外的Old區分配,而新生Yong區使用“拷貝收集-Copy Collection (見Hotspot Yong區GC)”,在某些點,拷貝一個對象變得比它被GC更消耗。
7) 沒有永久區 -- JRockit JVM沒有永久區, 所有類的屬性和字符串常量放在通常的Heap區域,因此如果它不再被使用,會被馬上回收。
IBM JVM
IBM JVM 被IBMWebsphere使用,它和JRockit有很多相同地方,它默認的使用一個“連續的Heap”,特別是在Websphere安裝過程中,這往往是導致最初的低性能的原因。它和JRockit一樣區分大小對象,并默認使用線程本地分配TLA,它也沒有“永久區”,但是IBM JVM也支持分代模型并且看起來更像HotSpot JVM,比如它的分代模型包括“新生區”和“老生區”,新生區又分為“分配區(Allocate)”和“Survior區”,新對象在Allocate區分配并在GC時拷貝到Survior區,這意味著一個對象在被移動到Old區時會被在2個區之間多次拷貝.和JRockit一樣,IBM JVM有多個選項可以配置“壓縮”階段,可以配置為“關閉”或“每次GC都進行壓縮”,和JRockit相比,默認的觸發條件是由于一系列的觸發而不是導致“完全”壓縮,而且這個可以被配置選項更改。
Java 7會宣稱“G1” - Production Ready,而且G1是不同的。
事務的原子性、一致性、獨立性及持久性
事務的原子性是指一個事務要么全部執行,要么不執行.也就是說一個事務不可能只執行了一半就停止了.比如你從取款機取錢,這個事務可以分成兩個步驟:1劃卡,2出錢.不可能劃了卡,而錢卻沒出來.這兩步必須同時完成.要么就不完成.
事務的一致性是指事務的運行并不改變數據庫中數據的一致性.例如,完整性約束了a+b=10,一個事務改變了a,那么b也應該隨之改變.
事務的獨立性是指兩個以上的事務不會出現交錯執行的狀態.因為這樣可能會導致數據不一致.
事務的持久性是指事務運行成功以后,就系統的更新是永久的.不會無緣無故的回滾.
$("#id").show()表示display:block,
$("#id").hide()表示display:none;
$("#id").toggle()切換元素的可見狀態。如果元素是可見的,切換為隱藏的;如果元素是隱藏的,切換為可見的。
【基本實現】在自己的電腦上搭建ftp,實現同一網段匿名登錄,并能上傳下載文件。
【涉及技術】vsftpd,iptables
【方法】
1. 先查看自己的機子上是否已安裝vsftpd (very secure FTP Daemon),這是linux上常用的ftpd技術,配置方法比較類似配置Apache。命令行輸入:
#rpm -qa | grep vsftp
若出現內容,則表示已安裝;若無,則手動抓包下載:
# sudo yum install vsftpd
2 .啟動vsftpd服務。很多教程寫的是/etc/init.d/vsftpd start,但是我試了下后發現不行,應該如下輸入:
# sudo service vsftpd start
相應的,start 可換成stop,restart等,從字面意思就知道其意思。
查看是否有啟動vsftpd:
# pstree | grep vsftpd
若有則表示啟動成功。至此,可通過#ftp 主機名/localhost/127.0.0.1 來測試ftp是否正常工作。
3. 配置 相關文件。vsftpd.conf 全局配置文件放在/etc/vsftpd/下。為了防止配置錯了,先拷貝一份副本,之后進入文檔進行編輯。完成后重啟ftp即可。
#cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd1.conf
#sudo vim /etc/vsftpd/vsftpd.conf
為了允許匿名登錄,則anonymous_enable必須等于YES,其他相應的配置屬性簡單列表如下:
anonymous_enable=YES 允許匿名登錄
Local_enable=YES 允許本地用戶登錄
write_enable=YES 開放本地用戶的寫權限
dirmessage_enable=YES 當切換到目錄時,顯示該目錄下的.message隱含文件的內容
xferlog_enab1e =YES 激活上傳和下載日志
connect_from_port_20 = YES 啟用FTP數據端口的連接請求
xferlog_std_format =YES 使用標準的ftpd xferlog日志格式
pam_service_name=vsftpd 設置認證服務的配置文件名稱,該文件存放在/etc/pam.d/
userlist_enable=YES 激活vsftpd檢查userlist_file指定用戶是否可以訪問vsftpd服務器
4. 本機進行測試。在瀏覽器上輸入ftp://localhost或者ftp://127.0.0.1,若搭建成功,則會有相應的文件夾,而這文件夾是默認在/var/ftp/下,當然以后你還可以進行修改。另一個方法是可以直接在命令行輸入:
#ftp 127.0.0.1
因為匿名登錄,跳過輸入用戶名和密碼后輸入:
ftp>user anonymous
再次跳過輸入密碼,此時會顯示登錄成功的字樣。
5. 關閉防火墻。此時去同一網段的主機訪問ftp,會發現一直鏈接不上。暫時了解到的是現在的linux系統為了更好地控制 IP 信息包過濾和防火墻配置,使用了iptables的東西。首先得關閉SElinux,該配置文件在/etc/selinux/下:
#vim /etc/selinux/config
找到相應語句,將其改成:SELINUX=disabled
重啟之后,如果發現還不行,則暫時的辦法可以關閉整個防火墻(不推薦):
#sudo service iptables stop
到了此步則肯定能從別的主機訪問自己搭建的ftp的,只是可能還需要涉及文件夾權限問題,修改之后就能實現文件上傳下載了。
完畢。
【補充】
若出現vsftpd: refusing to run with writable anonymous root的錯誤,大概是ftp目錄權限問題,修正方法:
# chown root:root /var/ftp
# chmod 755 /var/ftp