qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          Java 亂碼解決

           1、jsp頁面的編碼方式有兩個地方需要設(shè)置:

          <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
          <%@ page contentType="text/html;charset=utf-8"%>

            其中:pageEncoding 指的是jsp文件本身在本地保存時的編碼方式。contentType的charset是指服務(wù)器發(fā)送網(wǎng)頁內(nèi)容給客戶端時所使用的編碼。

            從第一次訪問一個jsp頁面開始,到這個頁面被發(fā)送到客戶端,這個Jsp頁面要經(jīng)過三次編碼轉(zhuǎn)換:

            第一階段是jsp編譯成.java,它會根據(jù)pageEncoding的設(shè)定讀取jsp,結(jié)果是由指定的編碼方案翻譯成統(tǒng)一的UTF-8 JAVA源碼(即.java),如果pageEncoding設(shè)定錯了,或沒有設(shè)定,出來的就是中文亂碼。

            第二階段是由JAVAC的JAVA源碼至java byteCode的編譯,不論JSP編寫時候用的是什么編碼方案,經(jīng)過這個階段的結(jié)果全部是UTF-8的encoding的java源碼。

            JAVAC用UTF-8的encoding讀取java源碼,編譯成UTF-8 encoding的二進制碼(即.class),這是JVM對常數(shù)字串在二進制碼(java encoding)內(nèi)表達的規(guī)范。

            第三階段是Tomcat(或其的application container)載入和執(zhí)行階段二的來的JAVA二進制碼,輸出的結(jié)果,也就是在客戶端見到的,這時隱藏在階段一和階段二的參數(shù)contentType就發(fā)揮了功效

            所以最終的解決方法為:

            在jsp頁面設(shè)置pageEncoding或者contentType的其中一個為支持中文的編碼格式(如utf-8,gbk,gb2312)。因為設(shè)置一個的話,另一個默認會和它一樣。

            如果兩個都設(shè)置的話,必須保證兩個都是支持中文編碼(不一定要一樣)。

            最佳建議設(shè)置如下:

          <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
          <%@ page contentType="text/html;charset=utf-8"%>

            2、post方式傳值亂碼:

            由于post方式傳值是通過request存儲的,在另一個頁面也是通過request.getParameter(String name)來提取信息,所以這種情況下的亂碼主要是因為request存儲信息的編碼設(shè)置導(dǎo)致的。post提交時,如果沒有設(shè)置提交的編碼格式,則會以iso8859-1方式進行提交,接受的jsp卻以utf-8的方式接受。所以使用如下語句即可得到單個正確的中文字符串:String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") ;

            解決方法:

            在接收頁面設(shè)置request.setCharacterEncoding("UTF-8")。最好通過過濾器實現(xiàn)每個頁面都設(shè)置為request.setCharacterEncoding("UTF-8")。

            3、get方式傳值亂碼:

            get方式傳值有兩種,一種是表單get傳值,另一種是url地址傳值(實質(zhì)上這兩種方式都是通過url參數(shù)的方式傳值)。

            表單方式get傳值:

            表單方式get傳值的編碼過程為,首先瀏覽器根據(jù)頁面的charset編碼方式對傳值進行編碼,然后提交至服務(wù)器交給tomcat,tomcat對這些信息進行解碼時,采用的解碼方式是由server.xml文件中的URIEncoding設(shè)置決定的,也就是說,當我們使用命令request.getParameter("")獲取表單參數(shù)值時,得到的字符串,經(jīng)過了charset的編碼和URIEncoding的解碼。

           由上所知,只要charset的編碼和URIEncoding的解碼一致,并且支持中文,就能保證沒有亂碼。

            設(shè)置URIEncoding的方法如下:

            方法一:

            修改$TOMCAT/conf/server.xml文件,在HTTP Connector或者AJP Connector的配置加上URIEncoding="gbk"

          <...   maxThreads="150" minSpareThreads="25" maxSpareThreads="75" 
                enableLookups="false" redirectPort="8443" acceptCount="100" 
            connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="gbk" />

            方法二:

            使用useBodyEncodingForURI="true". 這個方法適合你的TOMCAT實例下需要跑多個不同Encoding的程序時。

          <...  maxThreads="150" minSpareThreads="25" maxSpareThreads="75" 
                 enableLookups="false" redirectPort="8443" acceptCount="100" 
                connectionTimeout="20000" disableUploadTimeout="true" useBodyEncodingForURI="true" />

               enableLookups="false" redirectPort="8443" protocol="AJP/1.3" useBodyEncodingForURI="true" />

            在Tomcat配置中,連接器(HTTP Connector)屬性中有一個URIEncoding和

            useBodyEncodingForURI屬性,這兩個屬性設(shè)置對URL后的附加參數(shù)進行URL解碼時該如何選擇 字符集編碼。URIEncoding用于制定URL后的附加參數(shù)的字符集編碼,useBodyEncodingForURI 則說明是否采用實體內(nèi)容的字符集編碼設(shè)置來替代URIEncoding的設(shè)置,也就是說當 useBodyEncodingForURI屬性設(shè)置為true時ServletRequest.setCharacterEncoding方法設(shè)置的字符集編碼也影響getParameter等方法對URL地址后的參數(shù)進行URL解碼的結(jié)果。(在/%TomCat_Home%/ conf\server.xml文件中找到 <Connector>標記,然后在后面加上useBodyEncodingForURI=true)

            url方式get傳值亂碼:

            于這種方式,瀏覽器不會采用頁面的charset方式對URL中的中文進行編碼后提交至服務(wù)器(IE,F(xiàn)ireFox都一樣),而是采用系統(tǒng)的GBK轉(zhuǎn)碼為ISO-8859-1之后提交至服務(wù)器tomcat,所以這個過程為:

            首先,url地址中的中文被從gbk轉(zhuǎn)換成ISO-8859-1,交給tomcat后,又被tomcat根據(jù)URLEcoding解碼,這種情況,只有把URLEcoding設(shè)置為gbk才能在request.getParameter("")時不出現(xiàn)亂碼。但是這樣就會影響到上面的配置,所以一個好的解決方法是,使用java.net.URLEcoder和URLDecoder對地址中的中文進行手動編碼和解碼。

            所以一個萬全的解決方法為:

            1)所有頁面的charset設(shè)置為UTF-8。

            2)Tomcat的URIEncoding默認是ISO-8859-1,而我設(shè)置為UTF-8,主要是想解決中文命名的文件以及請求以get方式提交有可能出現(xiàn)的亂碼問題。

            3)添加過濾器,調(diào)用request.setCharacterEncoding("utf-8")方法將request的字符集設(shè)定為utf-8,解決請求以post方式提交的亂碼問題。

            4)url地址中存在中文參數(shù)時,首先對中文參數(shù)使用URLEcoder編碼為utf-8,然后在request.getParameter("")接收到參數(shù)后再使用URLDecoder還原。例如:

            From.jsp頁面:

          <%String username = "張某某" ; 
               username = URLEncoder.encode(username,"utf-8"); 
               %> 
               <a href="to.jsp?param=<%=username %>">轉(zhuǎn)入</a>

            To.jsp頁面

           <%=URLDecoder.decode(request.getParameter("param"),"utf-8")%>

            總之 ,亂碼的解決方案如下:

            post傳值亂碼時,在接收端設(shè)置request.setCharacterEncoding("UTF-8")

            get傳值或者url亂碼時,手動設(shè)置接收的參數(shù)String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") ;

            由上可見get,post傳值在tomcat5中是不一樣的

          posted @ 2011-12-19 16:48 順其自然EVO 閱讀(1908) | 評論 (0)編輯 收藏

          測試人員需要為產(chǎn)品質(zhì)量負責嗎?

           測試人員需要為產(chǎn)品質(zhì)量負責嗎?

            這句話其實可以這樣問

            醫(yī)生需要為病人的病情負責嗎?

            答案是肯定的。

            一個產(chǎn)品從測試人員手中走過,測試人員需要對它進行有目的的有效的測試,確保盡早的發(fā)現(xiàn)產(chǎn)品內(nèi)在的缺陷,從而在最短的時間內(nèi)促使開發(fā)人員完成對產(chǎn)品的修復(fù),減少企業(yè)因此而將要承受的損失。

            這需要測試人員的責任心。面對一個測試任務(wù),需要的是細心,耐心以及自我的分析。知道成本和效益的關(guān)系,了解客戶最大的需求,知道面對的這個任務(wù),自己的輕重緩急在哪里,不能磨磨蹭蹭,以至于耽誤了最佳的測試時間。

            如果測試產(chǎn)品從測試人員手中流過,卻沒有被檢測出隱含的最大的問題,那么就是測試人員的失職。就如同一個醫(yī)生面對一個病人,經(jīng)過一番檢查,卻沒有任何的診斷抑或遺漏了最大的病患。

            但是反過來講,測試人員不能對產(chǎn)品的任何瑕疵都負責任,不可能為產(chǎn)品的質(zhì)量去100%買單。測試人員只對測試的質(zhì)量去買單,只為測試的成果負責。

            測試人員雖然盡心盡力的對產(chǎn)品進行了最為有效的測試,但是因為客戶的決定,或者開發(fā)人員的推委,導(dǎo)致產(chǎn)品的已發(fā)現(xiàn)的重大的問題沒有被解決掉。面對這部分,測試人員不需要去負責。

            但是也不要因此就影響了士氣。雖然,很多時候,人們總說,一個軟件做好了,是開發(fā)人員的功勞;做得不好,使測試人員的不是。也有很多人,因為這個原因而離開了測試隊伍。因為覺得自己跟“替罪羔羊”一樣的無奈和無辜。

            其實,很多時候,任何角落,都有一些前臺的和幕后的英雄,并不是站在領(lǐng)獎臺上的人才是最光榮的。無論是設(shè)計者,開發(fā)者還是測試人員,都是軟件生命周期中不可或缺的重要組成人員,大家共同的努力才成就了軟件的上市以及企業(yè)的盈利和良好信譽。每一個都要為自己的存在而感到自豪。自己的地位靠自己的努力來不斷的得到證明,自己的能力不需要別人的證明。金子在沙地也是金子,沙子在金堆也總是沙子。如果你覺得自己被輕視了,那么,不要放棄,請你努力!相信吧,自己今天的努力一定會換來你更美好的明天。

            測試人員在面對測試任務(wù)之前一定學(xué)會思考,從客戶,從市場,從軟件本身的特點去方方面面的思考,知道自己該如何把握,該怎樣策劃你的測試用例。該如何更加有效的去發(fā)現(xiàn)更有價值的bug。

            很多測試人員都覺得很郁悶,當他們的bug被開發(fā)的以不需要修復(fù)為由而拒掉。但是這個時候抱怨沒有用的。開發(fā)人員這樣做,你要找到理由。開發(fā)人員絕對不會貿(mào)貿(mào)然把一個可能導(dǎo)致軟件崩潰的bug置之不理。如果是這樣的bug,那么,可能時間已經(jīng)不夠,修復(fù)的風險太大,這個時候你要理解,而且要幫助他們出主意,看看怎樣解決才是最好。如果你的bug無足輕重,而還有一大堆的問題你都沒有去發(fā)掘,那么,坐冷板凳是應(yīng)該的。這個時候,你能做得最好的事情就是,自己多去想,有效地發(fā)現(xiàn)出更多更有效的更重要的bug來。

          posted @ 2011-12-16 15:17 順其自然EVO 閱讀(190) | 評論 (0)編輯 收藏

          教你使用Linux系統(tǒng)的Shell腳本維護Oracle

            系統(tǒng)管理員與 DBA 之間在職責方面存在差別。但實際上,這種差別通常并不明顯。許多 IT 部門雇傭一些可解決數(shù)據(jù)庫級以及操作系統(tǒng)級問題的員工。當然,Oracle 數(shù)據(jù)庫本身使用操作系統(tǒng)資源,并能與其環(huán)境緊密交互。

            此外,許多系統(tǒng)管理員和DBA 發(fā)現(xiàn)將其工作相關(guān)的任務(wù)自動化很有必要或比較方便。軟件安裝、系統(tǒng)資源監(jiān)視以及系統(tǒng)管理涉及一些重復(fù)和容易出錯的任務(wù),而自動過程可以比手動過程更好地完成這些任務(wù)。

            將這些任務(wù)自動化的方法之一是shell 腳本。 Shell 腳本自 Linux 系統(tǒng)安裝之初就起著重要作用。啟動和關(guān)閉系統(tǒng)時就會調(diào)用各種腳本。 Oracle 和其他第三方供應(yīng)商的實用程序也是通過 shell 腳本可調(diào)用的。由于這些腳本可以快速開發(fā),因此歷來就用它們構(gòu)建應(yīng)用程序原型。系統(tǒng)管理員已利用通過 shell 腳本實現(xiàn)的功能提供針對其監(jiān)視的系統(tǒng)的特定要求和特征定制的解決方案了。

            在本文中,我將介紹 “bash”shell 腳本可以實現(xiàn)的、與在 Linux 平臺上安裝、運行和維護 Oracle 數(shù)據(jù)庫相關(guān)的功能。注意,本文適用于 Linux 腳本初學(xué)者或?qū)?Linux 相對陌生的 DBA ;對大多數(shù)經(jīng)驗豐富的 Linux 系統(tǒng)管理員則不適用。

            ◆Shell 腳本是什么?

            shell 腳本是一個包含命令序列的文本文件。當運行文件(或腳本)時,將執(zhí)行該文件中包含的命令。術(shù)語 shell 僅指與 Linux 內(nèi)核通信所使用的特定命令行用戶界面。目前有多個不同的 shell ,其中包括 C shell (csh) 、 Korn shell (ksh) 、 Bourne shell (sh) 和 Bourne-Again shell (bash) 。 shell 本身就是一個從文件或終端讀取命令、解釋這些命令并通常執(zhí)行其他命令的命令。 Bourne-Again shell 合并了上述其他 shell 的特性,本文就使用該腳本進行演示。

            腳本文件中的第一行可用于指定使用哪個 shell 來運行該腳本。以下是所有腳本示例中包含的第一行的含義:

            #!/bin/bash

            ◆為什么使用 Shell 腳本?

            由于 shell 腳本與 DBA 的工作相關(guān),因此您可能不會馬上看到 shell 腳本的價值,這跟您的工作經(jīng)歷有關(guān)。如果您以前從未使用過 UNIX 或類似 UNIX 的系統(tǒng),那么可能會對大量含義晦澀的命令感到一愁莫展。此外,除了作為關(guān)系數(shù)據(jù)庫外, Oracle 10 g 還提供了一個用于處理數(shù)據(jù)庫數(shù)據(jù)的強健平臺以及幾個用于在數(shù)據(jù)庫外部與操作系統(tǒng)交互的方法。

            但您會發(fā)現(xiàn)幾個探究 shell 腳本領(lǐng)域的原因,其中包括:

            ● 必須支持已經(jīng)存在的腳本。

            ● 需要在安裝 Oracle 軟件前自動設(shè)置系統(tǒng)。例如,您可以編寫一個腳本來檢查 OS 的初始狀態(tài)并報告安裝軟件前必須滿足的任何前提條件。該腳本還可以創(chuàng)建相關(guān)的 OS 用戶和組并為用戶設(shè)置環(huán)境變量。

            ● 可以使用正在運行的 Oracle 數(shù)據(jù)庫來執(zhí)行手動或計劃的任務(wù)。但在數(shù)據(jù)庫 未 運行時需要運行某些任務(wù)。可以使用腳本停止或啟動數(shù)據(jù)庫(以及偵聽器或相關(guān)的數(shù)據(jù)庫進程)。無法從數(shù)據(jù)庫內(nèi)部啟動此類動作。

            ● 您需要一種監(jiān)視數(shù)據(jù)庫狀態(tài)(例如,是否正在運行并可進行進程查詢)的機制。這樣的腳本還可以監(jiān)視非特定于 Oracle 的其他進程和資源,從而提供系統(tǒng)當前運行情況的更詳細信息。

            ● 需要將備份自動化。 Oracle Recovery Manager (RMAN) 是一個用于開發(fā)可以在任何平臺上運行的備份腳本的實用程序。可以從 shell 腳本中調(diào)用 Oracle Recovery Manager 并使用它執(zhí)行各種備份和恢復(fù)活動。

            ● 您可能有一個并非特定于某個數(shù)據(jù)庫的要求。您可能在一臺計算機上安裝了多個數(shù)據(jù)庫。建議您不要使用單個數(shù)據(jù)庫滿足此要求,因為那樣會引發(fā)潛在的安全性問題。在這些情況下, shell 腳本提供了一種既可以滿足此要求又不會將進程與單個數(shù)據(jù)庫關(guān)聯(lián)的方法。

            ◆什么情況下不使用 Shell 腳本?

            Oracle 數(shù)據(jù)庫包含了超出 RDBMS 傳統(tǒng)定義的功能。與軟件的任何其他部分一樣,它使用操作系統(tǒng)提供的資源,但它所“ 看到” 并“ 更改” 其環(huán)境的程度遠遠超過了其他軟件。SQL 和 Oracle 的固定視圖從數(shù)據(jù)庫內(nèi)部提供了系統(tǒng)視圖,而shell 腳本從數(shù)據(jù)庫外部提供了系統(tǒng)視圖。Shell 腳本并不是適用于所有問題的解決方案。

            必須意識到,操作系統(tǒng)的許多方面可以從數(shù)據(jù)庫內(nèi)部進行監(jiān)視和修改。可以使用Oracle 的固定視圖(帶 v$ 前綴的視圖)確定計算機的主機名 (v$instance) 或數(shù)據(jù)庫正在其中運行的平臺的名稱 (v$database) 。還可以通過這種方式確定與數(shù)據(jù)庫相關(guān)的文件的位置和其他屬性。可以直接從數(shù)據(jù)庫中查詢數(shù)據(jù)文件(v$datafile 、 dba_data_files )、臨時文件(v$tempfile 、 dba_temp_files )、重做日志 (v$logfile) 、存檔日志 (v$archived_log) 和控制文件 (v$controlfile) 的位置和其他屬性。可以通過該視圖以及通過查看某些 init.ora 參數(shù)(db_recovery_file_dest 、 db_recovery_file_dest_size )確定有關(guān)閃回恢復(fù)區(qū) ($recovery_file_dest) 的信息。還可以查詢進程 (v$process) 和內(nèi)存(v$sga 、 v$sgastat 等)的狀態(tài)。有各種內(nèi)置的 PL/SQL 程序包,并能夠創(chuàng)建允許對底層 OS 進行其他訪問的Java 和C 數(shù)據(jù)庫對象。

            如果您正在考慮為一個需要大量數(shù)據(jù)庫訪問的任務(wù)編寫腳本,則腳本可能并不是最佳選擇。本文的稍后部分將介紹如何使用SQL*Plus 訪問數(shù)據(jù)庫,但在很多情況下,使用其他語言可以更好地解決此問題。

          posted @ 2011-12-16 15:16 順其自然EVO 閱讀(170) | 評論 (0)編輯 收藏

          SQL Server監(jiān)控系列之調(diào)優(yōu)排錯

           使用SQL Server Profile GUI工具還是很多優(yōu)勢,首先是減少了我們監(jiān)控的復(fù)雜性,可以款速的建立監(jiān)控,在跟蹤屬性中,可以可以選擇MSSQL為我們提供的模版,包括常用的T-SQL、T-SQL Duration、T-SQL Locks模版分別監(jiān)控當前DB運行的所有查詢,所有查詢的耗時、所有的鎖定狀態(tài)。

            在跟蹤屬性 –> 選擇事件選擇 我們可以選擇自己需要的事件,所有的事件在MSDN 都有定義->單擊列篩選器 可以自定義過濾,排序噪點干擾因素

          (我隨便選擇了一個耗時 = 500 微妙的過濾條件)

            其他的模版大家可以自己看看MSDN 手冊,自己嘗試一下:SQL Server 2008 R2 本機 MSDN

            服務(wù)器端跟蹤和物理方式收集

            SQL Server Profile 只是對一些存儲過程的封裝,我更傾向于,自己定義常用的腳本,將監(jiān)控結(jié)果保存在本機,用來大量的分析和存檔。

            當然涉及4個存儲過程,雖然設(shè)置過濾的腳本非常麻煩,但是SQL Server Profile 可以利用 文件->導(dǎo)出 可以導(dǎo)出監(jiān)控腳本意味著,我們不需要編寫復(fù)雜的T-SQL 腳本,不過還是建議大家熟悉這幾個存儲過程:

            sp_trace_create 定義跟蹤 ,創(chuàng)建的跟蹤會在sys.traces查詢的到。

            s_trace_setevent 設(shè)置監(jiān)控事件

            sp_trace_setfilter 設(shè)置過濾

            sp_trace_setstatus 設(shè)置跟蹤的狀態(tài) 常用的是 sp_trace_setstatus @traceid,0 停止功能 、sp_trace_setstatus @traceid,2 移除跟蹤,這將導(dǎo)致sys.traces最終查詢不到該跟蹤

            其實整個跟蹤還是比較簡單的。我這里有一個常用的腳本:

            用來 監(jiān)控超過指定秒數(shù) 和 數(shù)據(jù)庫 的 批處理和存儲過程 語句(超過5MB的文件,會執(zhí)行ROLLOVER,根據(jù)文件名在后面添加類似_1,_2.trc的跟蹤結(jié)果):

          以下是代碼片段:
          CREATE PROC [dbo].[sp_trace_sql_durtion] @DatabaseName nvarchar(128), @Seconds bigint, @FilePath nvarchar(260) AS BEGIN DECLARE @rc int,@TraceID int,@MaxFileSize bigint; SET @MaxFileSize = 5; EXEC sp_trace_create @TraceID OUTPUT,2,@FilePath,@MaxFileSize,NULL; IF @rc != 0 RETURN; DECLARE @On bit; SET @On = 1; EXEC sp_trace_setevent @TraceID,10,35,@On; EXEC sp_trace_setevent @TraceID,10,1,@On; EXEC sp_trace_setevent @TraceID,10,13,@On; EXEC sp_trace_setevent @TraceID,41,35,@On; EXEC sp_trace_setevent @TraceID,41,1,@On; EXEC sp_trace_setevent @TraceID,41,13,@On; SET @Seconds = @Seconds * 1000000; EXEC sp_trace_setfilter @TraceID,13,0,4,@Seconds; IF @DatabaseName IS NOT NULL EXEC sp_trace_setfilter @TraceID,35,0,0,@DatabaseName EXEC sp_trace_setstatus @TraceID,1 SELECT TraceID = @TraceID; END

            參數(shù)非常的明了,數(shù)據(jù)庫名稱、執(zhí)行事件超過多少秒、保存的路徑。

            當我們運行這個腳本一段事件以后,可以快速的發(fā)現(xiàn)大量耗時的T-SQL,我們可以通過

            SELECT * FROM fn_trace_gettable(N'監(jiān)控文件路徑',1);

            來查看行方式的結(jié)果。

            同樣的富有創(chuàng)造力的讀者可以自己創(chuàng)建監(jiān)控鎖定,監(jiān)控死鎖等方式保存文件,但是我的建議是盡可能的減少噪音,也就是說我們要達到什么目地就在《Microsfot SQL Server 2005 技術(shù)內(nèi)幕: T-SQL 程序設(shè)計》 中有一個正則,用來將類似的語句全部組合成,只有參數(shù)形式替換具體值的SQL CLR,但是我認為那個正則還有bug,等我空了給大家寫一個,自己也能使用的更完善。


           使用SQL Server Profile GUI工具還是很多優(yōu)勢,首先是減少了我們監(jiān)控的復(fù)雜性,可以款速的建立監(jiān)控,在跟蹤屬性中,可以可以選擇MSSQL為我們提供的模版,包括常用的T-SQL、T-SQL Duration、T-SQL Locks模版分別監(jiān)控當前DB運行的所有查詢,所有查詢的耗時、所有的鎖定狀態(tài)。

            在跟蹤屬性 –> 選擇事件選擇 我們可以選擇自己需要的事件,所有的事件在MSDN 都有定義->單擊列篩選器 可以自定義過濾,排序噪點干擾因素

          (我隨便選擇了一個耗時 = 500 微妙的過濾條件)

            其他的模版大家可以自己看看MSDN 手冊,自己嘗試一下:SQL Server 2008 R2 本機 MSDN

            服務(wù)器端跟蹤和物理方式收集

            SQL Server Profile 只是對一些存儲過程的封裝,我更傾向于,自己定義常用的腳本,將監(jiān)控結(jié)果保存在本機,用來大量的分析和存檔。

            當然涉及4個存儲過程,雖然設(shè)置過濾的腳本非常麻煩,但是SQL Server Profile 可以利用 文件->導(dǎo)出 可以導(dǎo)出監(jiān)控腳本意味著,我們不需要編寫復(fù)雜的T-SQL 腳本,不過還是建議大家熟悉這幾個存儲過程:

            sp_trace_create 定義跟蹤 ,創(chuàng)建的跟蹤會在sys.traces查詢的到。

            s_trace_setevent 設(shè)置監(jiān)控事件

            sp_trace_setfilter 設(shè)置過濾

            sp_trace_setstatus 設(shè)置跟蹤的狀態(tài) 常用的是 sp_trace_setstatus @traceid,0 停止功能 、sp_trace_setstatus @traceid,2 移除跟蹤,這將導(dǎo)致sys.traces最終查詢不到該跟蹤

            其實整個跟蹤還是比較簡單的。我這里有一個常用的腳本:

            用來 監(jiān)控超過指定秒數(shù) 和 數(shù)據(jù)庫 的 批處理和存儲過程 語句(超過5MB的文件,會執(zhí)行ROLLOVER,根據(jù)文件名在后面添加類似_1,_2.trc的跟蹤結(jié)果):

          以下是代碼片段:
          CREATE PROC [dbo].[sp_trace_sql_durtion] @DatabaseName nvarchar(128), @Seconds bigint, @FilePath nvarchar(260) AS BEGIN DECLARE @rc int,@TraceID int,@MaxFileSize bigint; SET @MaxFileSize = 5; EXEC sp_trace_create @TraceID OUTPUT,2,@FilePath,@MaxFileSize,NULL; IF @rc != 0 RETURN; DECLARE @On bit; SET @On = 1; EXEC sp_trace_setevent @TraceID,10,35,@On; EXEC sp_trace_setevent @TraceID,10,1,@On; EXEC sp_trace_setevent @TraceID,10,13,@On; EXEC sp_trace_setevent @TraceID,41,35,@On; EXEC sp_trace_setevent @TraceID,41,1,@On; EXEC sp_trace_setevent @TraceID,41,13,@On; SET @Seconds = @Seconds * 1000000; EXEC sp_trace_setfilter @TraceID,13,0,4,@Seconds; IF @DatabaseName IS NOT NULL EXEC sp_trace_setfilter @TraceID,35,0,0,@DatabaseName EXEC sp_trace_setstatus @TraceID,1 SELECT TraceID = @TraceID; END

            參數(shù)非常的明了,數(shù)據(jù)庫名稱、執(zhí)行事件超過多少秒、保存的路徑。

            當我們運行這個腳本一段事件以后,可以快速的發(fā)現(xiàn)大量耗時的T-SQL,我們可以通過

            SELECT * FROM fn_trace_gettable(N'監(jiān)控文件路徑',1);

            來查看行方式的結(jié)果。

            同樣的富有創(chuàng)造力的讀者可以自己創(chuàng)建監(jiān)控鎖定,監(jiān)控死鎖等方式保存文件,但是我的建議是盡可能的減少噪音,也就是說我們要達到什么目地就在《Microsfot SQL Server 2005 技術(shù)內(nèi)幕: T-SQL 程序設(shè)計》 中有一個正則,用來將類似的語句全部組合成,只有參數(shù)形式替換具體值的SQL CLR,但是我認為那個正則還有bug,等我空了給大家寫一個,自己也能使用的更完善。

           監(jiān)控異常

            在上個系列中,講述了具體的SQL Event抓去的異常,可以及時通知,但是具體的異常信息,并不是特別詳細。因此我們可以選擇事件中的Error來添加有關(guān)T-SQL批處理和SP的所有異常,用于分析,這個跟蹤非常有利于我們監(jiān)控一些異常情況!!!我創(chuàng)建了一個跟蹤的腳本,和上面的跟蹤事件的腳本一樣,超過5MB RollOver。我們要定期的執(zhí)行這個跟蹤,雖然不建議長期開啟,但是定期監(jiān)控處理異常是有利我們系統(tǒng)更加長時間運作的。

          以下是代碼片段:
          CREATE PROC [dbo].[sp_trace_sql_exception] @FilePath nvarchar(260) AS DECLARE @rc int,@TraceID int,@Maxfilesize bigint SET @maxfilesize = 5 EXEC @rc = sp_trace_create @TraceID output, 2, @FilePath, @Maxfilesize, NULL IF (@rc != 0) RETURN; DECLARE @on bit SET @on = 1 EXEC sp_trace_setevent @TraceID, 33, 1, @on EXEC sp_trace_setevent @TraceID, 33, 14, @on EXEC sp_trace_setevent @TraceID, 33, 51, @on EXEC sp_trace_setevent @TraceID, 33, 12, @on EXEC sp_trace_setevent @TraceID, 11, 2, @on EXEC sp_trace_setevent @TraceID, 11, 14, @on EXEC sp_trace_setevent @TraceID, 11, 51, @on EXEC sp_trace_setevent @TraceID, 11, 12, @on EXEC sp_trace_setevent @TraceID, 13, 1, @on EXEC sp_trace_setevent @TraceID, 13, 14, @on EXEC sp_trace_setevent @TraceID, 13, 51, @on EXEC sp_trace_setevent @TraceID, 13, 12, @on DECLARE @intfilter int,@bigintfilter bigint; EXEC sp_trace_setstatus @TraceID, 1 SELECT TraceID=@TraceID GOTO finish ERROR: SELECT ErrorCode=@rc FINISH:

            定期執(zhí)行吧,同志們,找異常。。。

            默認跟蹤和黑盒跟蹤

            在sys.traces中的TraceID = 1的跟蹤是SQL Server 默認跟蹤,這個跟蹤比較輕量級,一般監(jiān)控服務(wù)器的啟用停止,對象的創(chuàng)建和刪除,日志和數(shù)據(jù)文件自動增長以及其他數(shù)據(jù)庫的變化。(監(jiān)控那些沒事刪錯了表的人,是最好的,當然前提不要都使用一個帳號!)

            可以通過

          以下是代碼片段:
          EXEC sp_configure 'default trace enabled',0; RECONFIGURE WITH OVERRIDE;

            來關(guān)閉默認跟蹤。

            黑盒跟蹤,就是可以幫助我們診斷數(shù)據(jù)庫沒事自個奔了的異常,在MSDN 搜索sp_create_trace的時候應(yīng)該也發(fā)現(xiàn)了

            的選項,那么我們也能創(chuàng)建一個類似的存儲過程來快速的創(chuàng)建黑盒跟蹤,幫助我們診斷一些異常!

          以下是代碼片段:
          CREATE PROCEDURE sp_trace_blackbox @FilePath nvarchar(260) AS BEGIN DECLARE @TraceID int,@MaxFileSize bigint SET @MaxFileSize = 25; EXEC sp_trace_create @TraceID OUTPUT,8,@FilePath,@MaxFileSize EXEC sp_trace_setstatus @TraceID,1; END

            我這里提供@FilePath = NULL參數(shù),這個默認就保存在SQL Server的數(shù)據(jù)文件夾中。

            結(jié)尾

            這里詳細的描述了SQL Server Trace 的各種功能特性,有興趣的朋友可以深入到MSDN研究監(jiān)控,我這是也只是一筆帶過,也參考了MSDN 和《Microsoft SQL Server 2005調(diào)優(yōu)》那本書,下面的監(jiān)控可能和大家講述 DDL觸發(fā)器監(jiān)控,C2審核以及SQL Server的事件通知(涉及的Service Broker我會開一個系列和大家詳細說說Service Broker),最后的結(jié)束可能就是說說2008的數(shù)據(jù)收集監(jiān)控

          posted @ 2011-12-16 15:02 順其自然EVO 閱讀(200) | 評論 (0)編輯 收藏

          Java內(nèi)存泄露的理解與解決

           Java內(nèi)存管理機制

            在C++ 語言中,如果需要動態(tài)分配一塊內(nèi)存,程序員需要負責這塊內(nèi)存的整個生命周期。從申請分配、到使用、再到最后的釋放。這樣的過程非常靈活,但是卻十分繁瑣,程序員很容易由于疏忽而忘記釋放內(nèi)存,從而導(dǎo)致內(nèi)存的泄露。 Java 語言對內(nèi)存管理做了自己的優(yōu)化,這就是垃圾回收機制。 Java 的幾乎所有內(nèi)存對象都是在堆內(nèi)存上分配(基本數(shù)據(jù)類型除外),然后由 GC ( garbage collection)負責自動回收不再使用的內(nèi)存。

            上面是Java 內(nèi)存管理機制的基本情況。但是如果僅僅理解到這里,我們在實際的項目開發(fā)中仍然會遇到內(nèi)存泄漏的問題。也許有人表示懷疑,既然 Java 的垃圾回收機制能夠自動的回收內(nèi)存,怎么還會出現(xiàn)內(nèi)存泄漏的情況呢?這個問題,我們需要知道 GC 在什么時候回收內(nèi)存對象,什么樣的內(nèi)存對象會被 GC 認為是“不再使用”的。

            Java中對內(nèi)存對象的訪問,使用的是引用的方式。在 Java 代碼中我們維護一個內(nèi)存對象的引用變量,通過這個引用變量的值,我們可以訪問到對應(yīng)的內(nèi)存地址中的內(nèi)存對象空間。在 Java 程序中,這個引用變量本身既可以存放堆內(nèi)存中,又可以放在代碼棧的內(nèi)存中(與基本數(shù)據(jù)類型相同)。 GC 線程會從代碼棧中的引用變量開始跟蹤,從而判定哪些內(nèi)存是正在使用的。如果 GC 線程通過這種方式,無法跟蹤到某一塊堆內(nèi)存,那么 GC 就認為這塊內(nèi)存將不再使用了(因為代碼中已經(jīng)無法訪問這塊內(nèi)存了)。

            通過這種有向圖的內(nèi)存管理方式,當一個內(nèi)存對象失去了所有的引用之后,GC 就可以將其回收。反過來說,如果這個對象還存在引用,那么它將不會被 GC 回收,哪怕是 Java 虛擬機拋出 OutOfMemoryError 。

            Java內(nèi)存泄露

            一般來說內(nèi)存泄漏有兩種情況。一種情況如在C/C++ 語言中的,在堆中的分配的內(nèi)存,在沒有將其釋放掉的時候,就將所有能訪問這塊內(nèi)存的方式都刪掉(如指針重新賦值);另一種情況則是在內(nèi)存對象明明已經(jīng)不需要的時候,還仍然保留著這塊內(nèi)存和它的訪問方式(引用)。第一種情況,在 Java 中已經(jīng)由于垃圾回收機制的引入,得到了很好的解決。所以, Java 中的內(nèi)存泄漏,主要指的是第二種情況。

            可能光說概念太抽象了,大家可以看一下這樣的例子:

          1. Vector v = new  Vector( 10 );  
          2. for  ( int  i = 1 ;i < 100 ; i ++ ){  
          3. Object o = new  Object();  
          4. v.add(o);  
          5. o = null ;  
          6. }

            在這個例子中,代碼棧中存在Vector 對象的引用 v 和 Object 對象的引用 o 。在 For 循環(huán)中,我們不斷的生成新的對象,然后將其添加到 Vector 對象中,之后將 o 引用置空。問題是當 o 引用被置空后,如果發(fā)生 GC ,我們創(chuàng)建的 Object 對象是否能夠被 GC 回收呢?答案是否定的。因為, GC 在跟蹤代碼棧中的引用時,會發(fā)現(xiàn) v 引用,而繼續(xù)往下跟蹤,就會發(fā)現(xiàn) v 引用指向的內(nèi)存空間中又存在指向 Object 對象的引用。也就是說盡管 o 引用已經(jīng)被置空,但是 Object 對象仍然存在其他的引用,是可以被訪問到的,所以 GC 無法將其釋放掉。如果在此循環(huán)之后, Object 對象對程序已經(jīng)沒有任何作用,那么我們就認為此 Java 程序發(fā)生了內(nèi)存泄漏。

            盡管對于C/C++ 中的內(nèi)存泄露情況來說, Java 內(nèi)存泄露導(dǎo)致的破壞性小,除了少數(shù)情況會出現(xiàn)程序崩潰的情況外,大多數(shù)情況下程序仍然能正常運行。但是,在移動設(shè)備對于內(nèi)存和 CPU 都有較嚴格的限制的情況下, Java 的內(nèi)存溢出會導(dǎo)致程序效率低下、占用大量不需要的內(nèi)存等問題。這將導(dǎo)致整個機器性能變差,嚴重的也會引起拋出 OutOfMemoryError ,導(dǎo)致程序崩潰。

            一般情況下內(nèi)存泄漏的避免

            在不涉及復(fù)雜數(shù)據(jù)結(jié)構(gòu)的一般情況下,Java 的內(nèi)存泄露表現(xiàn)為一個內(nèi)存對象的生命周期超出了程序需要它的時間長度。我們有時也將其稱為“對象游離”。

            例如:

          1. public class FileSearch{  
          2.       private byte [] content;  
          3.       privateFile mFile;  
          4.      public FileSearch(File file){  
          5.       mFile = file;  
          6.       }  
          7.      public boolean hasString(String str){  
          8.          int size = getFileSize(mFile);  
          9.         content =  new  byte [size];  
          10.          loadFile(mFile, content);  
          11.          String s =  new String(content);  
          12.          return s.contains(str);  
          13.      }  
          14. }

          posted @ 2011-12-16 14:20 順其自然EVO 閱讀(193) | 評論 (0)編輯 收藏

          SQL Server 阻塞的常見原因和解決辦法

            1、由于語句運行時間太長而導(dǎo)致的阻塞,語句本身在正常運行中,只須等待某些系統(tǒng)資源

            解決辦法:

            a)語句本身有沒有可優(yōu)化的空間

            b)Sql Server 整體性能如何,是不是有資源瓶頸影響了語句執(zhí)行速度,如 內(nèi)存、硬盤 和 CPU 等

            2、由于一個未按預(yù)期提交的事務(wù)導(dǎo)致的阻塞

            這一類阻塞的特征,就是問題連接早就進入了空閑狀態(tài)(sysprocesses.status='sleeping'和sysprocesses.cms='awaiting command'),但是,如果檢查 sysprocesses.open_tran,就會發(fā)現(xiàn)它不為0,以及事務(wù)沒有提交。這類問題很多都是因為應(yīng)用端遇到了一個執(zhí)行超時,或者其他原因,當時執(zhí)行的語句倍提前終止了,但是連接還保留著。應(yīng)用沒有跟隨發(fā)來的事務(wù)提交或回滾指令,導(dǎo)致一個事務(wù)被遺留在 Sql Server 里。

            解決辦法:

            應(yīng)用程序本身必須意識到任何語句都有可能遇到意外終止的情況,做好錯誤處理工作。這些工作包括:

            ● 在做 Sql Server 調(diào)用的時候,須加上錯誤捕捉和處理語句:If @@Trancount>0 RollBack Tran;(在程序中設(shè)置If @@Error<>0 Rollback Tran; 并不總是能執(zhí)行到該語句)

            ● 設(shè)置連接屬性"Set XACT_ABORT ON"。如果沒有辦法很規(guī)范應(yīng)用程序的錯誤撲捉和處理語句,一個最快的方法就是在每個連接建立以后,或是容易出問題的存儲過程開頭,運行 "Set XACT_ABORT ON"

            ● 考慮是否要關(guān)閉連接池。發(fā)一句 sp_reset_connection 命令清理當前連接上次遺留下來的所有對象,包括回滾未提交的事務(wù)。

            3、由于客戶端沒有及時把結(jié)果集取出而導(dǎo)致的語句長時間運行

            語句在 Sql Server 內(nèi)執(zhí)行總時間不僅包含 Sql Server 的執(zhí)行時間,還包含把結(jié)果集發(fā)給客戶端的時間。如果結(jié)果集比較大,Sql Server 會分幾次打包發(fā)出,沒發(fā)一次,都要等待客戶端的確認。只有確認以后,Sql Server 才會發(fā)送下一個結(jié)果集包。所有結(jié)果都發(fā)完以后,Sql Server才認為語句執(zhí)行完畢,釋放執(zhí)行申請的資源(包括鎖資源)。如果出于某種原因,客戶端應(yīng)用處理結(jié)果非常緩慢甚至沒有響應(yīng),或者干脆不理睬 Sql Server 發(fā)送結(jié)果集的請求,則 Sql Server 會耐心的等待,銀次會導(dǎo)致語句長時間執(zhí)行而產(chǎn)生阻塞。

            解決辦法:

            a)慎重返回大結(jié)果集

            b)如果a短期內(nèi)不能實現(xiàn),則嘗試大結(jié)果集的連接使用 Read Uncommitted 事務(wù)隔離級別,這樣查詢就不會申請 S 鎖了

          posted @ 2011-12-15 15:48 順其自然EVO 閱讀(219) | 評論 (0)編輯 收藏

          Java常量池詳解之抓狂的面試題

          http://bbs.51testing.com/viewthread.php?tid=516291&extra=&page=3


           今天My partner問我一個讓他頭疼的Java question,求輸出結(jié)果:

          1. /** 
          2.  *  
          3.  * @author DreamSea 2011-11-19 
          4.  */ 
          5. public class IntegerTest { 
          6.     public static void main(String[] args) {     
          7.         objPoolTest(); 
          8.     } 
          9.     public static void objPoolTest() { 
          10.         Integer i1 = 40
          11.         Integer i2 = 40
          12.         Integer i3 = 0
          13.         Integer i4 = new Integer(40); 
          14.         Integer i5 = new Integer(40); 
          15.         Integer i6 = new Integer(0); 
          16.          
          17.         System.out.println("i1=i2\t" + (i1 == i2)); 
          18.         System.out.println("i1=i2+i3\t" + (i1 == i2 + i3)); 
          19.         System.out.println("i4=i5\t" + (i4 == i5)); 
          20.         System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));     
          21.          
          22.         System.out.println();         
          23.     } 
          24. }

            輸出結(jié)果:

          i1=i2true
          i1=i2+i3   true
          i4=i5false
          i4=i5+i6true

            看起來比較Easy的問題,但是Console輸出的Result和我們所想的確恰恰相反,我們就疑惑了,這是為什么咧?

            最后通過網(wǎng)上搜索得知Java為了提高性能提供了和String類一樣的對象池機制,當然Java的八種基本類型的包裝類(Packaging Type)也有對象池機制。

            Integer i1=40;Java在編譯的時候會執(zhí)行將代碼封裝成Integer i1=Integer.valueOf(40);通過查看Source Code發(fā)現(xiàn):

            Integer.valueOf()中有個內(nèi)部類IntegerCache(類似于一個常量數(shù)組,也叫對象池),它維護了一個Integer數(shù)組cache,長度為(128+127+1)=256,Integer類中還有一個Static Block(靜態(tài)塊)。

            從這個靜態(tài)塊可以看出,Integer已經(jīng)默認創(chuàng)建了數(shù)值【-128-127】的Integer緩存數(shù)據(jù)。所以使用Integer i1=40時,JVM會直接在該在對象池找到該值的引用。也就是說這種方式聲明一個Integer對象時,JVM首先會在Integer對象的緩存池中查找有木有值為40的對象,如果有直接返回該對象的引用;如果沒有,則使用New keyword創(chuàng)建一個對象,并返回該對象的引用地址。因為Java中【==】比較的是兩個對象是否是同一個引用(即比較內(nèi)存地址),i2和i2都是引用的同一個對象,So i1==i2結(jié)果為”true“;而使用new方式創(chuàng)建的i4=new Integer(40)、i5=new Integer(40),雖然他們的值相等,但是每次都會重新Create新的Integer對象,不會被放入到對象池中,所以他們不是同一個引用,輸出false。

            對于i1==i2+i3、i4==i5+i6結(jié)果為True,是因為,Java的數(shù)學(xué)計算是在內(nèi)存棧里操作的,Java會對i5、i6進行拆箱操作,其實比較的是基本類型(40=40+0),他們的值相同,因此結(jié)果為True。

            好了,我想說道這里大家應(yīng)該都會對Integer對象池有了更進一步的了解了吧,我在諾諾的問一句如果把40改為400猜猜會輸出什么?

          i1=i2false
          i1=i2+i3true
          i4=i5false
          i4=i5+i6true

            這是因為Integer i1=400,Integer i2=400他們的值已經(jīng)超出了常量池的范圍,JVM會對i1和i2各自創(chuàng)建新的對象(即Integer i1=new Integer(400)),所以他們不是同一個引用。

          posted @ 2011-12-15 15:47 順其自然EVO 閱讀(254) | 評論 (0)編輯 收藏

          Coverity談“開發(fā)中測試”與程序員最常犯的編碼錯誤

           Coverity公司位于美國加州舊金山,他們的產(chǎn)品包括Coverity Integrity Control、Coverity Static Analysis等一系列代碼分析工具與解決方案。日前,Coverity公司產(chǎn)品副總Ezi Boteach先生就“開發(fā)中測試”、代碼復(fù)查和開發(fā)人員最常犯的編碼錯誤接受了采訪。

            問題:能否介紹下Coverity的“開發(fā)中測試”理念和你們的Development Testing Platform?

            Ezi:“開發(fā)中測試”是新出現(xiàn)的一種技術(shù),包括一系列流程和軟件,例如靜態(tài)分析。開發(fā)中測試的目的是要幫助開發(fā)人員、管理層和業(yè)務(wù)人員能在開發(fā)周期的早期,找到并修復(fù)質(zhì)量和安全方面的問題,這些代碼還在開發(fā)之中,不會影響上市時間、成本或客戶滿意度。

            “開發(fā)中測試”擴大了傳統(tǒng)測試范圍,可以包括功能測試性能測試和安全審核,為開發(fā)團隊提供更快、更便捷的方式來測試代碼中的缺陷,而且是以非侵入的方式。這種方式下,開發(fā)人員能夠把注意力集中在創(chuàng)新上,管理層能夠在開發(fā)周期早期盡早了解問題以作出決策,業(yè)務(wù)人員能持續(xù)向市場交付高質(zhì)量的產(chǎn)品,獲得競爭優(yōu)勢。

            問題:代碼復(fù)查是人們高度推薦的編程實踐。如果使用你們的產(chǎn)品,對于代碼復(fù)查,您有什么建議?

            Ezi:代碼復(fù)查是軟件“開發(fā)中測試”很重要的部分,而且其成本很高,因為需要另一個開發(fā)人員來復(fù)審代碼,很多時候這個開發(fā)人員還必須是資深人員。在代碼復(fù)查之前先做靜態(tài)分析,這能讓代碼復(fù)審過程更快,而且成本更低。使用自動化分析來檢查變更以及于系統(tǒng)其他部分的集成點,以此來識別和消滅代碼錯誤,代碼復(fù)審就可以更集中于邏輯和功能錯誤,而不是代碼的缺陷,這樣做更劃算,能夠自動化,而且易于重復(fù)。

            我們推薦測試驅(qū)動開發(fā)所有的工具和實踐,包括代碼復(fù)審、單元測試和代碼覆蓋率。當然,要是能和Coverity的自動化代碼測試工具一起使用就更好了。

            問題:你們的產(chǎn)品如何與像xUnit這樣的工具一起配合使用?

            Ezi:單元測試是“開發(fā)中測試”的重要組成,需要支持測試驅(qū)動開發(fā)。使用Coverity 5.5,我們引入了“開發(fā)中測試”的平臺,能夠讓多種不同工具與測試工作流集成。目前我們還不能專門與xUnit集成在一起,但是我們的客戶現(xiàn)在能夠很方便地把他們使用的測試工具與Coverity Development Testing平臺集成。舉個例子:Coverity 5.5.1版本包括與常用Java靜態(tài)分析工具FindBugs的集成。這樣的集成讓管理人員能夠降低維護多個測試工具的成本,并通過統(tǒng)一的工具來推行策略。開發(fā)人員也有統(tǒng)一的界面來查看缺陷,并排定解決的優(yōu)先級。

            問題:你們的產(chǎn)品是否能與持續(xù)交付流程集成?

            Ezi:Coverity Static Analysis可以與多個構(gòu)建系統(tǒng)集成,包括Jenkins這個常用的持續(xù)集成系統(tǒng)。一般來說,與Jenkins和持續(xù)集成系統(tǒng)的集成是為了確保所有的持續(xù)構(gòu)建都能運行自動化代碼測試工具。如果分析中發(fā)現(xiàn)了新的缺陷,一個構(gòu)建版本就是失敗的。這確保新的缺陷不會引入到交付的軟件的主干代碼中,而交付過程是持續(xù)交付流程的一部分。這也能保證失敗的構(gòu)建版本不會進入流程的下一個階段,一般來說是QA階段。Coverity就像是交付過程中的一道閘門。

            問題:除了使用你們的產(chǎn)品,您是否還能為開發(fā)人員和架構(gòu)師提供一些其他的原則與實踐?

            Ezi:確保軟件的質(zhì)量,防止安全漏洞,這需要良好協(xié)作、工具和開發(fā)流程管理這幾方面的結(jié)合。從清晰的需求文檔開始,這是開發(fā)任何新功能的基礎(chǔ)。需求文檔之后,就是功能和系統(tǒng)架構(gòu)師完成的功能和需求設(shè)計。代碼開發(fā)完成后,“開發(fā)中測試”應(yīng)該是這個流程的有機部分。不僅僅是一個產(chǎn)品,而應(yīng)該是流程和技術(shù)的組合,幫助開發(fā)組織在開發(fā)周期早期、撰寫代碼的時候,就能修復(fù)軟件的問題,確保代價高昂的缺陷不會進入后續(xù)階段和生產(chǎn)環(huán)境。

            架構(gòu)師要確保軟件的架構(gòu)良好。這需要人工復(fù)審和架構(gòu)分析,此外還要有經(jīng)過考驗的軟件開發(fā)方法論。與之類似,開發(fā)人員也要保證,除了使用靜態(tài)和動態(tài)分析的自動化測試之外,也要使用代碼復(fù)審和單元測試。質(zhì)量保證(QA)是任何軟件開發(fā)過程中都很重要的階段,以確保功能測試和性能測試順利通過。最后,安全審核也很重要,保證在識別、修復(fù)、移除代碼缺陷時不會帶入新的安全漏洞。

            問題:根據(jù)Coverity收集的數(shù)據(jù),您能否列舉一些開發(fā)人員最常犯的錯誤?

            Ezi:開源項目SCAN(scan.coverity.com)能夠很好地發(fā)現(xiàn)開發(fā)人員常犯的錯誤。從2006年開始,Coverity與美國國土安全部一起,研發(fā)了Coverity SCAN項目,來保證開源軟件的安全性和完整性。Coverity SCAN分析了超過290個開源項目,包括Linux、Apache、PHP和Android,識別出49,654個缺陷,開源軟件開發(fā)人員已經(jīng)修復(fù)了超過15,000個缺陷。蝦米的表格就展示出了開源軟件中最常出現(xiàn)的缺陷,商業(yè)軟件也與之類似。

           SCAN項目中的出現(xiàn)頻率 風險程度 
          NULL指針引用 27.60% 中 
          資源泄露 23.19% 高 
          非原意圖表達式 9.76% 中 
          讀未初始化的值 8.41% 高 
          釋放后使用 5.91% 高 
          緩沖區(qū)溢出 5.52% 高 

            很重要的一點要指出:像NULL指針引用、內(nèi)存泄露和緩沖區(qū)溢出常常會帶來很嚴重的質(zhì)量和安全風險。很多這樣的缺陷,使用傳統(tǒng)的測試方法,有時難以找到。使用Coverity的工具會更易于發(fā)現(xiàn)類似問題。

            要想了解更多關(guān)于SCAN項目的信息,可以訪問 2010 SCAN報告,其中包括對于Android核心代碼的分析結(jié)果。

            問題:對于代碼分析可視化的重要性,程序員們認識得越來越明白了。您能否列出3個最重要的相關(guān)分析圖?

            Ezi:Coverity的Development Testing平臺能以代碼可視化形式讓開發(fā)人員和管理層看到代碼的質(zhì)量。可視化能夠在幾個方面起到幫助作用:它有助于標識代碼的所有者和缺陷,能幫助展示出軟件代碼的整體可讀性,以及質(zhì)量和安全風險較高的代碼區(qū)域,還能有助于推行代碼完整性的檢查策略。

            只談3個圖很困難,但我想選的是:未解決的缺陷與已解決的缺陷的對比、每個軟件組件中的缺陷個數(shù)、新的Integrity Control熱度圖。

          posted @ 2011-12-14 15:58 順其自然EVO 閱讀(295) | 評論 (0)編輯 收藏

          高手真經(jīng) 13條Java核心技術(shù)

          、>>>最高位用0填充,>>最高位用符號位填充 ,沒有<<。

            2、強制轉(zhuǎn)換是直接截斷,要四舍五入的話需要用Math.round();

            3、boolean不要于任何數(shù)值類型進行轉(zhuǎn)換。除非b?1:0

            4、Java沒有內(nèi)置字符串類型。

            5、String類沒有提供用于修改字符串的方法,方便字符串共享。

            6、C++重載了==,可以用它來檢測字符串的相等性。Java沒有重載。C也不用==對字符串進行比較,而使用strcmp函數(shù)。Java的compareTo()方法與strcmp類似。

          greeting.compareTo("Hello")==0

            7、length()返回代碼單元數(shù)量;

            codePointCount()返回代碼點數(shù)量。

            charAt(n)將返回位置n的代碼單元,n介于0-s.length()-1。

            得到第i個代碼點,

          1. greeting.offsetByCodePoints(0,i); 
          2. greeting.codePointAt(i);

          1. StringBuilder builder = new 
          2. StringBuilder();builder.append(ch/str); 
          3. or String completeString = builder.toString();

            返回一個與構(gòu)建器或緩沖器相同的字符串。

            8、輸入: Scanner類位于 java.util.*

            Console類可以實現(xiàn)控制臺讀取密碼:

          1. Console cons = System.console(); 
          2. String username = cons.readLine("User name:"); 
          3. char[] passwd = cons.readPassword("Password:");

            9、被格式化的參數(shù)索引:

          System.out.printf("%1$s %2$tB %2$te %2$ty""Due date:" , new Date());

            10、文件的輸入與輸出:

          1. Scanner in = new Scanner(new File("myfile.txt")); //如果文件名包含反斜杠 ,要轉(zhuǎn)義,加一個反斜杠。 
          2. PrintWriter out = new PrintWriter("myfile.txt");

            如果用一個不存在的文件構(gòu)造一個Scanner,或者用一個不能被創(chuàng)建的文件名構(gòu)造一個PrintWriter,那么就會發(fā)異常。

            11、如果整數(shù),浮點不能滿足精度要求,可以使用java.math包中的兩個類:BigInteger 和 BigDecimal

          BigInteger a = BigInteger.valueOf(100);

            不能使用+ *來處理大數(shù)值,而是add 和multiply方法。

            12、

          for(variable : collection) statement;

            打印數(shù)組更見的方法: Arrays.toString(a); //返回一個包含數(shù)組元素的字符串。

            數(shù)組的初始化:

          1. 1int[] smallPrimes = {2,3,4,5,6,7}; //不需要使用new。 
          2. 2new int[] {2,3,4,5,6,7//匿名初始化,將創(chuàng)建一個新的數(shù)組 并利用括號中提供的值進行初始化,數(shù)組的大小就是初始值的個數(shù)。

            Java允許數(shù)組長度為0。

            允許數(shù)組拷貝,這是兩個變量引用同一個數(shù)組。如果要拷貝到一個新的數(shù)組 需要使用Arrays.copyOf(number , length),通常用這個方法來增加數(shù)組的大小,剩余的數(shù)值賦0,布爾型賦false。

            Java數(shù)組與C++數(shù)組在堆棧上有很大不同,但基本上與分配在heap上的數(shù)組指針一樣。

          int[] a = new int[100]; //java []被預(yù)定義為檢查數(shù)組邊界,而沒有指針運算,即不能通過a+1得到數(shù)組下一個元素。

            不同于

          int a[100//c++

            而等同于

          int *a = new int[100]; //c++

            數(shù)組排序: sort

            快速打印一個二維數(shù)組的數(shù)據(jù)元素列表:Arrays.deepToString(a);

            Java實際上只有一維數(shù)組。

            13、命令行參數(shù)

          java Message -g cruel world
          args[0]: "-g" args[1]:"cruel" args[2]: world

          posted @ 2011-12-14 15:57 順其自然EVO 閱讀(217) | 評論 (0)編輯 收藏

          JVM分代垃圾回收策略的基礎(chǔ)概念

           由于不同對象的生命周期不一樣,因此在JVM的垃圾回收策略中有分代這一策略。本文介紹了分代策略的目標,如何分代,以及垃圾回收的觸發(fā)因素。

            文章總結(jié)了JVM垃圾回收策略為什么要分代,如何分代,以及垃圾回收的觸發(fā)因素。

            為什么要分代

            分代的垃圾回收策略,是基于這樣一個事實:不同的對象的生命周期是不一樣的。因此,不同生命周期的對象可以采取不同的收集方式,以便提高回收效率。

            在Java程序運行的過程中,會產(chǎn)生大量的對象,其中有些對象是與業(yè)務(wù)信息相關(guān),比如Http請求中的Session對象、線程、Socket連接,這類對象跟業(yè)務(wù)直接掛鉤,因此生命周期比較長。但是還有一些對象,主要是程序運行過程中生成的臨時變量,這些對象生命周期會比較短,比如:String對象,由于其不變類的特性,系統(tǒng)會產(chǎn)生大量的這些對象,有些對象甚至只用一次即可回收。

            試想,在不進行對象存活時間區(qū)分的情況下,每次垃圾回收都是對整個堆空間進行回收,花費時間相對會長,同時,因為每次回收都需要遍歷所有存活對象,但實際上,對于生命周期長的對象而言,這種遍歷是沒有效果的,因為可能進行了很多次遍歷,但是他們依舊存在。因此,分代垃圾回收采用分治的思想,進行代的劃分,把不同生命周期的對象放在不同代上,不同代上采用最適合它的垃圾回收方式進行回收。

            如何分代

            如圖所示:

            如何分代

            虛擬機中的共劃分為三個代:年輕代(Young Generation)、年老點(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java類的類信息,與垃圾收集要收集的Java對象關(guān)系不大。年輕代和年老代的劃分是對垃圾收集影響比較大的。

            年輕代:

            所有新生成的對象首先都是放在年輕代的。年輕代的目標就是盡可能快速的收集掉那些生命周期短的對象。年輕代分三個區(qū)。一個Eden區(qū),兩個Survivor區(qū)(一般而言)。大部分對象在Eden區(qū)中生成。當Eden區(qū)滿時,還存活的對象將被復(fù)制到Survivor區(qū)(兩個中的一個),當這個Survivor區(qū)滿時,此區(qū)的存活對象將被復(fù)制到另外一個Survivor區(qū),當這個Survivor去也滿了的時候,從第一個Survivor區(qū)復(fù)制過來的并且此時還存活的對象,將被復(fù)制“年老區(qū)(Tenured)”。需要注意,Survivor的兩個區(qū)是對稱的,沒先后關(guān)系,所以同一個區(qū)中可能同時存在從Eden復(fù)制過來 對象,和從前一個Survivor復(fù)制過來的對象,而復(fù)制到年老區(qū)的只有從第一個Survivor去過來的對象。而且,Survivor區(qū)總有一個是空的。同時,根據(jù)程序需要,Survivor區(qū)是可以配置為多個的(多于兩個),這樣可以增加對象在年輕代中的存在時間,減少被放到年老代的可能。

           年老代:

            在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對象,就會被放到年老代中。因此,可以認為年老代中存放的都是一些生命周期較長的對象。

            持久代:

            用于存放靜態(tài)文件,如今Java類、方法等。持久代對垃圾回收沒有顯著影響,但是有些應(yīng)用可能動態(tài)生成或者調(diào)用一些class,例如Hibernate等,在這種時候需要設(shè)置一個比較大的持久代空間來存放這些運行過程中新增的類。持久代大小通過-XX:MaxPermSize=<N>進行設(shè)置。

            什么情況下觸發(fā)垃圾回收

            由于對象進行了分代處理,因此垃圾回收區(qū)域、時間也不一樣。GC有兩種類型:Scavenge GC和Full GC。

            Scavenge GC

            一般情況下,當新對象生成,并且在Eden申請空間失敗時,就會觸發(fā)Scavenge GC,對Eden區(qū)域進行GC,清除非存活對象,并且把尚且存活的對象移動到Survivor區(qū)。然后整理Survivor的兩個區(qū)。這種方式的GC是對年輕代的Eden區(qū)進行,不會影響到年老代。因為大部分對象都是從Eden區(qū)開始的,同時Eden區(qū)不會分配的很大,所以Eden區(qū)的GC會頻繁進行。因而,一般在這里需要使用速度快、效率高的算法,使Eden去能盡快空閑出來。

            對整個堆進行整理,包括Young、Tenured和Perm。Full GC因為需要對整個對進行回收,所以比Scavenge GC要慢,因此應(yīng)該盡可能減少Full GC的次數(shù)。在對JVM調(diào)優(yōu)的過程中,很大一部分工作就是對于FullGC的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:

            ◆ 年老代(Tenured)被寫滿

            ◆ 持久代(Perm)被寫滿

            ◆ System.gc()被顯示調(diào)用

            ◆ 上一次GC之后Heap的各域分配策略動態(tài)變化


          posted @ 2011-12-14 15:24 順其自然EVO 閱讀(197) | 評論 (0)編輯 收藏

          僅列出標題
          共394頁: First 上一頁 347 348 349 350 351 352 353 354 355 下一頁 Last 
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 昌都县| 江华| 涿州市| 新乡县| 武城县| 鹿泉市| 郓城县| 阳山县| 双流县| 上思县| 阳西县| 沅江市| 内黄县| 绍兴县| 偃师市| 乳山市| 达拉特旗| 大庆市| 永安市| 峨山| 沙田区| 葵青区| 阳东县| 大庆市| 比如县| 铁岭县| 且末县| 南华县| 扎赉特旗| 江门市| 涞水县| 潜山县| 延长县| 牡丹江市| 区。| 云霄县| 颍上县| 西峡县| 西华县| 蒙城县| 固镇县|