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

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

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

    2012年1月10日

    perf4j使用四(log4j集成圖表查看)

     

    在使用二這編文章中提到,可以以匯總形式查看日志,也可以通過(guò)圖表來(lái)查看。Perf4jlog4j集成后,其實(shí)也可以以圖表的形式來(lái)查看性能狀況。

     

    我們這篇文章還是使用前一篇文章中提到log4j.xml的配置,其他都一樣,只是在配置中加入了圖表的配置:

    <!-- 生成firstBlock,secondBlock的平均值的圖表 -->

        <appender name="graphExecutionTimes"

                  class="org.perf4j.log4j.GraphingStatisticsAppender">

            <!-- GraphType:Mean(平均值), Min(最小值), Max(最大值), TPS(每秒事務(wù)數(shù)) -->

            <param name="GraphType" value="Mean"/>

            <param name="TagNamesToGraph" value="firstBlock,secondBlock"/>

            <appender-ref ref="graphsFileAppender"/>

        </appender>

     

        <!-- 生成firstBlock,secondBlocktps的圖表 -->

        <appender name="graphExecutionTPS"

                  class="org.perf4j.log4j.GraphingStatisticsAppender">

            <param name="GraphType" value="TPS"/>

            <param name="TagNamesToGraph" value="firstBlock,secondBlock"/>

            <appender-ref ref="graphsFileAppender"/>

        </appender>

       

        <!-- 記錄圖表生成urllog文件 -->

        <appender name="graphsFileAppender" class="org.apache.log4j.FileAppender">

            <param name="File" value="/home/perfGraphs.log"/>

            <layout class="org.apache.log4j.PatternLayout">

                <param name="ConversionPattern" value="%m%n"/>

            </layout>

    </appender>

    另外還需要改一個(gè)地方,就是CoalescingStatistics的配置:

    <appender name="CoalescingStatistics"

                  class="org.perf4j.log4j.AsyncCoalescingStatisticsAppender">

            <!--

                 TimeSlice配置多少時(shí)間間隔去做一次匯總寫(xiě)入文件中

                 默認(rèn)值是 30000 ms

            -->

            <param name="TimeSlice" value="10000"/>

            <appender-ref ref="fileAppender"/>

           

            <appender-ref ref="graphExecutionTimes"/>

            <appender-ref ref="graphExecutionTPS"/>

        </appender>

    黃色那段配置的意思就是把日志寫(xiě)入到圖表日志去。

    運(yùn)行代碼Perf4JAppenderExample,我們?cè)?/span>perfGraphs.log文件中生成了圖表的url

    http://chart.apis.google.com/chart?cht=lxy&chtt=Mean&chs=750x400&chxt=x,x,y&chd=t:0.0,100.0|45.2,78.1|0.0,100.0|98.1,100.0&chco=ff0000,00ff00&chm=d,ff0000,0,-1,5.0|d,00ff00,1,-1,5.0&chdl=firstBlock|secondBlock&chxr=2,0,828.6&chxl=0:|13:23:50|13:24:00|1:|Time&chxp=0,0.0,100.0|1,50&chg=50.0,10

     

    http://chart.apis.google.com/chart?cht=lxy&chtt=TPS&chs=750x400&chxt=x,x,y&chd=t:0.0,100.0|100.0,100.0|0.0,100.0|100.0,100.0&chco=ff0000,00ff00&chm=d,ff0000,0,-1,5.0|d,00ff00,1,-1,5.0&chdl=firstBlock|secondBlock&chxr=2,0,0.5&chxl=0:|13:23:50|13:24:00|1:|Time&chxp=0,0.0,100.0|1,50&chg=50.0,10

    大家可以把url放到瀏覽器訪問(wèn)下。

     

    上面這種方式呢,需要自己登錄到服務(wù)器上,找到log文件,在放到瀏覽器中查看,總的過(guò)程還是比較麻煩。如果大家需要監(jiān)控的工程是一個(gè)web工程的話,那就更方便了,直接配置一個(gè)servlet來(lái)查看。Web.xml的配置如下:

    <!DOCTYPE web-app PUBLIC

     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

     "http://java.sun.com/dtd/web-app_2_3.dtd" >

     

    <web-app>

        <display-name>Archetype Created Web Application</display-name>

     

        <servlet>

           <servlet-name>perf4j</servlet-name>

           <servlet-class>org.perf4j.log4j.servlet.GraphingServlet</servlet-class>

           <!-- graphExecutionTimesgraphExecutionTPS就是我們?cè)?/span>log4j中配置的名稱(chēng) -->

           <init-param>

               <param-name>graphNames</param-name>

               <param-value>graphExecutionTimes,graphExecutionTPS</param-value>

           </init-param>

        </servlet>

     

        <servlet-mapping>

           <servlet-name>perf4j</servlet-name>

           <url-pattern>/perf4j</url-pattern>

        </servlet-mapping>

    </web-app>

    大家可以打包工程,并放到web服務(wù)器下啟動(dòng),然后訪問(wèn)下/perf4j這個(gè)uri

    Maven有一個(gè)jetty插件,可以方便啟動(dòng)web工程,只要大家在pom.xml文件中加入如下配置:

    <plugins>

               <!-- jetty插件, 設(shè)定端口與context path-->

               <plugin>

                  <groupId>org.mortbay.jetty</groupId>

                  <artifactId>jetty-maven-plugin</artifactId>

               </plugin>    

    </plugins>

    在控制臺(tái)中輸入:mvn jetty:run,即可。省去了打包發(fā)布,很省心喔。

    第一次用http://localhost:8080/perf4j訪問(wèn)查看圖表的時(shí)候沒(méi)有生成任何東西,那是因?yàn)閮?nèi)存中沒(méi)有收集到最新的性能數(shù)據(jù)。所以我在index.jsp里調(diào)用下以便產(chǎn)生性能數(shù)據(jù)。然后重新訪問(wèn),這個(gè)時(shí)候就有圖表生成了。


    下載工程

    posted @ 2012-04-19 14:12 yangpingyu 閱讀(1744) | 評(píng)論 (1)編輯 收藏

    perf4j使用三(log4j集成)

    Perf4j最主要的一個(gè)好處就是可以跟log4j或者logback來(lái)性能分析和監(jiān)控線上運(yùn)行的程序。集成的方式主要是:自定義log4j的appenders通過(guò)標(biāo)準(zhǔn)的配置加入到log4j中去(后面會(huì)有配置的例子)。有一個(gè)要注意的地方就是需要使用log4j的1.2.14版本或者更高版本。由于我一般都是使用log4j,所以對(duì)于logback的集成我就不描述了,我覺(jué)得應(yīng)該差不多的。

     

    Perf4j最重要的appender就是AsyncCoalescingStatisticsAppender,它會(huì)把一段時(shí)間內(nèi)StopWatch的信息匯總到一個(gè)獨(dú)立的GroupedTimingStatistics日志信息,然后把這個(gè)獨(dú)立的信息傳給下游的appenders,比如fileappenders,這樣就可以寫(xiě)到文件中去了。也可以傳給per4j的其他自定義appenders。

     

    接下來(lái)我們看一個(gè)log4j.xml的例子,有一個(gè)限制,如果要使用AsyncCoalescingStatisticsAppender就只能使用xml文件而不能使用properties文件。

     

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

     

    <log4j:configuration debug="false" xmlns:log4j="http://jakarta.apache.org/log4j/">

        <!--

             配置控制臺(tái)輸出

        -->

        <appender name="console" class="org.apache.log4j.ConsoleAppender">

            <layout class="org.apache.log4j.PatternLayout">

                <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>

            </layout>

        </appender>

     

        <!-- Perf4J appenders -->

        <!--

           AsyncCoalescingStatisticsAppender收集StopWatch的日志信息并傳送到下游的文件appenders

        -->

        <appender name="CoalescingStatistics"

                  class="org.perf4j.log4j.AsyncCoalescingStatisticsAppender">

            <!--

                 TimeSlice配置多少時(shí)間間隔去做一次匯總寫(xiě)入文件中

                 默認(rèn)值是 30000 ms

            -->

            <param name="TimeSlice" value="10000"/>

            <appender-ref ref="fileAppender"/>

        </appender>

     

        <!-- 把匯總的perf4j的日志信息寫(xiě)到perfStats.log文件中去 -->

        <appender name="fileAppender" class="org.apache.log4j.FileAppender">

            <param name="File" value="/home/perfStats.log"/>

            <layout class="org.apache.log4j.PatternLayout">

                <param name="ConversionPattern" value="%m%n"/>

            </layout>

        </appender>

     

        <!-- Loggers -->

        <!-- 

           配置perf4j logger

           Additivity設(shè)置成false主要因?yàn)槭遣幌胱尨a運(yùn)行時(shí)間的日志輸出給上游appenders,即不要在控制臺(tái)輸出。

        -->

        <logger name="org.perf4j.TimingLogger" additivity="false">

            <level value="INFO"/>

            <appender-ref ref="CoalescingStatistics"/>

        </logger>

     

        <!-- 

           Root logger打印所有日志,但不包含perf4j的信息。原因是在TimingLogger配置中設(shè)置了additivityfalse

        -->

        <root>

            <level value="INFO"/>

            <appender-ref ref="console"/>

        </root>

    </log4j:configuration>

     

     

    黃色背景是perf4j的配置信息。其他都是log4j的基本配置。下面是測(cè)試perf4j與log4j集成的代碼。

    package com.baowu.perf4j;

     

    import org.apache.log4j.Logger;

    import org.perf4j.StopWatch;

    import org.perf4j.log4j.Log4JStopWatch;

     

    public class Perf4JAppenderExample {

        public static void main (String[] args) throws Exception {

            Logger rootLogger = Logger.getRootLogger();

            for (int i = 0; i < 10; i++) {

                // Log4JStopWatch默認(rèn)使用org.perf4j.TimingLogger這個(gè)類(lèi)

                StopWatch stopWatch = new Log4JStopWatch();

                //模擬代碼運(yùn)行時(shí)間

                Thread.sleep((long) (Math.random() * 1000L));

                //打印到控制臺(tái)

                rootLogger.info("Normal logging messages only go to the console");

                stopWatch.lap("firstBlock");

                Thread.sleep((long) (Math.random() * 2000L));

                stopWatch.stop("secondBlock");

            }

        }

    }

     

    運(yùn)行代碼。

    控制臺(tái)輸出:

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

    INFO root - Normal logging messages only go to the console

     

    文件輸出:


     

    輸出格式也可以改成CSV格式。配置:

    <appender name="fileAppender" class="org.apache.log4j.FileAppender">

            <param name="File" value="/home/perfStats.log"/>

            <layout class="org.apache.log4j.PatternLayout">

                <param name="ConversionPattern" value="%m%n"/>

            </layout>

    </appender>

    org.apache.log4j.PatternLayout改成org.perf4j.log4j.StatisticsCsvLayout即可。

    具體的參數(shù)請(qǐng)查看api
    下載工程


    posted @ 2012-04-16 13:59 yangpingyu 閱讀(4628) | 評(píng)論 (0)編輯 收藏

    perf4j使用二

    Perf4j使用一主要演示了性能監(jiān)控的日志直接打印在標(biāo)準(zhǔn)輸出流。那么使用二呢則主要來(lái)演示怎么來(lái)分析打印出來(lái)的日志文件。

     

    由于我們還沒(méi)有跟log4j集成,日志文件打印在標(biāo)準(zhǔn)輸出流,我們需要把標(biāo)準(zhǔn)輸出流重定向到times.log文件中。重定向有兩種方式:直接copy到文件中,或者在eclipse里指定下輸出文件。我主要是用eclipse指定輸出文件。

     

     

    然后運(yùn)行代碼(Perf4j使用一Example.java),控制臺(tái)會(huì)在第一句話中打出[Console output redirected to file:E:\yangpingyu\work\times.log],這樣運(yùn)行的結(jié)果會(huì)同時(shí)打印在文件中和標(biāo)準(zhǔn)輸出中。

     

    有了times.log,我們就可以對(duì)日志文件進(jìn)行分析,以找出有問(wèn)題的代碼。

     

    分析日志命令:

    E:\yangpingyu\work>java -jar perf4j-0.9.16.jar times.log

     

    csv的格式來(lái)查看結(jié)果,命令如下:

    java -jar perf4j-0.9.16.jar -f csv times.log

     

    以上都是以文本的格式進(jìn)行輸出,但文本沒(méi)有圖表更具有表達(dá)力。所以把結(jié)果以圖表形式輸出是必不可少,幸好perf4j也支持,命令如下:

    java -jar perf4j-0.9.16.jar --graph perfGraphs.html times.log

    執(zhí)行命令后,在控制臺(tái)輸出相應(yīng)的統(tǒng)計(jì)信息,相應(yīng)的在磁盤(pán)上也生成了一個(gè)htmlhtml里包含平均值圖表和tps圖表。

    <html>

    <head><title>Perf4J Performance Graphs</title></head>

    <body>

    <br/><br/><img src="http://chart.apis.google.com/chart?cht=lxy&chtt=Mean&chs=750x400&chxt=x,x,y&chd=t:0.0,50.0,100.0|56.3,60.1,6.0|0.0,50.0|88.5,94.5|50.0,100.0|43.2,7.2|0.0,50.0,100.0|71.8,57.4,8.0|0.0,50.0,100.0|100.0,61.2,59.6|0.0,50.0,100.0|63.9,62.0,18.7|0.0,50.0,100.0|34.4,72.1,30.1&chco=ff0000,00ff00,0000ff,00ffff,ff00ff,ffff00,000000&chm=d,ff0000,0,-1,5.0|d,00ff00,1,-1,5.0|d,0000ff,2,-1,5.0|d,00ffff,3,-1,5.0|d,ff00ff,4,-1,5.0|d,ffff00,5,-1,5.0|d,000000,6,-1,5.0&chdl=codeBlock1|codeBlock2.failure|codeBlock2.success|codeBlock3|codeBlock4|codeBlock5|codeBlock6&chxr=2,0,748.5&chxl=0:|18:12:00|18:12:30|18:13:00|1:|Time&chxp=0,0.0,50.0,100.0|1,50&chg=50.0,10"/>

    <br/><br/><img src="http://chart.apis.google.com/chart?cht=lxy&chtt=TPS&chs=750x400&chxt=x,x,y&chd=t:0.0,50.0,100.0|36.4,90.9,9.1|0.0,50.0|27.3,63.6|50.0,100.0|36.4,9.1|0.0,50.0,100.0|36.4,90.9,9.1|0.0,50.0,100.0|36.4,90.9,9.1|0.0,50.0,100.0|36.4,90.9,9.1|0.0,50.0,100.0|27.3,100.0,9.1&chco=ff0000,00ff00,0000ff,00ffff,ff00ff,ffff00,000000&chm=d,ff0000,0,-1,5.0|d,00ff00,1,-1,5.0|d,0000ff,2,-1,5.0|d,00ffff,3,-1,5.0|d,ff00ff,4,-1,5.0|d,ffff00,5,-1,5.0|d,000000,6,-1,5.0&chdl=codeBlock1|codeBlock2.failure|codeBlock2.success|codeBlock3|codeBlock4|codeBlock5|codeBlock6&chxr=2,0,0.4&chxl=0:|18:12:00|18:12:30|18:13:00|1:|Time&chxp=0,0.0,50.0,100.0|1,50&chg=50.0,10"/>

    </body></html>

    以上是html的內(nèi)容,里面最重要的信息就是兩個(gè)img標(biāo)簽,里面具體的圖片是google chart api生成。可以打開(kāi)html直接查看圖表。

    如果想要看更詳細(xì)的參數(shù),可以使用—help來(lái)查看。java -jar perf4j-0.9.16.jar –help

    posted @ 2012-04-15 19:35 yangpingyu 閱讀(1786) | 評(píng)論 (0)編輯 收藏

    小工具

    本文主要記錄下自己在日常工作中感覺(jué)比較好用的一些小工具。目前只有幾個(gè),不過(guò)遇到好的會(huì)不斷更新上來(lái)。

    EmEditor:文本編輯器。
    onenote:主要用來(lái)記錄工作列表和一些計(jì)劃等。
    google chart api:可以用來(lái)制作圖表,很方便。性能測(cè)試的結(jié)果數(shù)據(jù)做對(duì)比圖。
    smartArt:也是圖表制作工具,已經(jīng)集成到2007office中了。
    awk:linux文本處理工具。類(lèi)似于腳本。牛逼的程序員應(yīng)該要掌握的一個(gè)工具。

    add by 2012-06-19
    http://cn.edrawsoft.com/download.php :畫(huà)圖很漂亮的工具。


    待更新。。。

    posted @ 2012-04-15 16:46 yangpingyu 閱讀(271) | 評(píng)論 (0)編輯 收藏

    perf4j使用一

    如果大家使用的是maven工程,那么現(xiàn)在pom文件中加入perf4j的依賴(lài)。

    <dependency>

    <groupId>org.perf4j</groupId>

    <artifactId>perf4j</artifactId>

    <version>0.9.16</version>

    <scope>compile</scope>

    </dependency>

    如果用的是普通工程,那么直接下載jar包放入lib目錄下即可。

     

     

    例子:

    package com.baowu.per4j;

     

    import org.perf4j.LoggingStopWatch;

    import org.perf4j.StopWatch;

     

    public class Example1 {

     

        public static void main(String[] args) throws InterruptedException{

           method1();

           method2();

           method3();

        }

       

        /**

         * 監(jiān)控一處代碼示例

         * @throws InterruptedException

         */

        private static void method1() throws InterruptedException{

           //創(chuàng)建一個(gè)監(jiān)控對(duì)象,這里使用LoggingStopWatch,它是把結(jié)果直接輸出到控制臺(tái)。我們也可以

           //使用StopWatch的其他子類(lèi),比如:Log4JStopWatchCommonsLogStopWatch。不過(guò)這些子類(lèi)需

           //要工程使用日志框架

           StopWatch stopWatch = new LoggingStopWatch("codeBlock1");

     

           //這里就是一些需要監(jiān)控的代碼,我們命名為codeBlock1

           //使用線程休眠是為了模擬代碼執(zhí)行時(shí)間

           Thread.sleep((long)(Math.random() * 1000L));

     

           //停止計(jì)算代碼性能

           stopWatch.stop();

        }

       

        /**

         * 一個(gè)方法多出代碼監(jiān)控

         * @throws InterruptedException

         */

        private static void method2() throws InterruptedException{

           StopWatch stopWatch = new LoggingStopWatch();

           Thread.sleep((long)(Math.random() * 1000L));

           stopWatch.lap("codeBlock3");

           Thread.sleep((long)(Math.random() * 1000L));

           stopWatch.lap("codeBlock4");

           Thread.sleep((long)(Math.random() * 1000L));

           stopWatch.lap("codeBlock5");

           Thread.sleep((long)(Math.random() * 1000L));

           stopWatch.stop("codeBlock6");

        }

       

        /**

         * stop方法可以加入一些說(shuō)明信息

         */

        private static void method3(){

           StopWatch stopWatch = new LoggingStopWatch();

           try {

               // the code block being timed - this is just a dummy example

               long sleepTime = (long)(Math.random() * 1000L);

               Thread.sleep(sleepTime);

               if (sleepTime > 500L) {

                   throw new Exception("Throwing exception");

               }

               stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");

           } catch (Exception e) {

               stopWatch.stop("codeBlock2.failure", "Exception was: " + e);

           }

        }

    }

     

    運(yùn)行結(jié)果:

    start[1334457619937] time[355] tag[codeBlock1]

    start[1334457620296] time[152] tag[codeBlock3]

    start[1334457620453] time[138] tag[codeBlock4]

    start[1334457620593] time[598] tag[codeBlock5]

    start[1334457621187] time[700] tag[codeBlock6]

    start[1334457621890] time[619] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

    posted @ 2012-04-15 10:44 yangpingyu 閱讀(2985) | 評(píng)論 (0)編輯 收藏

    Perf4j簡(jiǎn)介

    Perf4j主要的用途是計(jì)量代碼性能和分析性能數(shù)據(jù)。

     

    為什么要使用這個(gè)工具呢?我們可以聯(lián)想下最早期java開(kāi)發(fā)者調(diào)試代碼使用的方式,以前沒(méi)有日志框架,那java開(kāi)發(fā)就使用System.out.println()來(lái)輸出自己想查看的變量。但是這樣項(xiàng)目上線的話,就要去掉這些打印語(yǔ)句以減少性能影響。那萬(wàn)一在線上出問(wèn)題了,調(diào)試哪里出問(wèn)題就很麻煩,因?yàn)闆](méi)有輸出的日志可查。所以后來(lái)有人開(kāi)發(fā)了日志框架,通過(guò)日志級(jí)別控制日志的輸出。

     

    類(lèi)似的,如果沒(méi)有perf4j,我們?cè)诓榭创a運(yùn)行時(shí)間的話可以用以下代碼來(lái)實(shí)現(xiàn):

    long start = System.currentTimeMillis();

    // execute the block of code to be timed

    System.out.println("ms for block n was: " + (System.currentTimeMillis() - start));

    這種方式有幾個(gè)缺點(diǎn):

    1、 這種方式輸出內(nèi)容比較單一,就是代碼總的運(yùn)行時(shí)間。但是我們代碼需要查看的性能指標(biāo)有更多,比如總的平均值,最小值,最大值,tps等等。

    2、 也許我們的代碼在線上運(yùn)行,我們想把這些值通過(guò)圖表的形式展示出來(lái)。或者把這些內(nèi)容通過(guò)jmx輸出。

    3、 另外,我們可能把perf4jlog4jslf4j等日志框架和日志門(mén)面系統(tǒng)整合起來(lái)。

     

    基于以上這些問(wèn)題,所以開(kāi)源社區(qū)就出現(xiàn)了perf4j(人多力量大,社區(qū)的力量就是強(qiáng)大)。

    Perf4j一些特性:

    簡(jiǎn)單的停止查看機(jī)制來(lái)計(jì)算語(yǔ)句時(shí)間消耗輸出。

    命令行解析log文件產(chǎn)生匯總數(shù)據(jù)和圖表。

    簡(jiǎn)單的集成日志框架和門(mén)面框架。

    自定義log4jlogbackappenders來(lái)產(chǎn)生數(shù)據(jù)和圖表。

    通過(guò)jmx查看性能指標(biāo),并根據(jù)閾值發(fā)送消息。

    Web工程可以通過(guò)servlet來(lái)輸出性能指標(biāo)。

    Perf4j可以和aop等切面框架整合起來(lái)輸出性能指標(biāo)。

    Perf4j是一個(gè)可擴(kuò)展的架構(gòu)。

    posted @ 2012-04-15 10:15 yangpingyu 閱讀(757) | 評(píng)論 (0)編輯 收藏

    Maven與findbugs

    公司最近嚴(yán)抓軟件質(zhì)量問(wèn)題,我抽空了解了下提高代碼質(zhì)量的一些開(kāi)源工具。其中一個(gè)就是findbugs。使用findbugs有很多方式,比如:安裝eclipse findbugs插件,通過(guò)maven調(diào)用生成報(bào)告。今天主要演示下mavenfindbugs集成。

     

    第一步:下載maven,我使用的是maven3。把maven的命令加入PATH環(huán)境變量。

    第二步:創(chuàng)建一個(gè)普通的maven java工程。命令如下:mvn archetype:maven-archetyp-quickstart –DgroupId=com.tianya –DartifactId=baowu。如果正常執(zhí)行的話會(huì)生成如下結(jié)構(gòu)的一個(gè)工程。

    第三步:我們看下pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

        <modelVersion>4.0.0</modelVersion>

        <groupId>com.tianya</groupId>

        <artifactId>baowu</artifactId>

        <version>0.0.1-SNAPSHOT</version>

        <packaging>war</packaging>

     

        <!--配置插件來(lái)源 -->

        <pluginRepositories>

           <pluginRepository>

               <id>Codehaus repository</id>

               <url>http://repository.codehaus.org/</url>

           </pluginRepository>

        </pluginRepositories>

       

        <build>

           <plugins>

               <plugin>

                  <groupId>org.codehaus.mojo</groupId>

                  <artifactId>findbugs-maven-plugin</artifactId>

                  <version>2.3.2</version>

                  <configuration>

                      <!-- <configLocation>${basedir}/springside-findbugs.xml</configLocation> -->

                      <threshold>High</threshold>

                      <effort>Default</effort>

                      <findbugsXmlOutput>true</findbugsXmlOutput>

                       <!-- findbugs xml輸出路徑-->         <findbugsXmlOutputDirectory>target/site</findbugsXmlOutputDirectory>

                  </configuration>

               </plugin>

           </plugins>

        </build>

    </project>

     

    我來(lái)解釋下xml配置:

    配置插件下載地址

    <!--配置插件來(lái)源 -->

        <pluginRepositories>

           <pluginRepository>

               <id>Codehaus repository</id>

               <url>http://repository.codehaus.org/</url>

           </pluginRepository>

        </pluginRepositories>

     

    由于maven核心做的事情都是抽象的構(gòu)建過(guò)程,很多實(shí)際的工作都是具體的插件來(lái)實(shí)現(xiàn)。所以很顯然,maven以插件的方式集成findbugs

    <plugin>

                  <groupId>org.codehaus.mojo</groupId>

                  <artifactId>findbugs-maven-plugin</artifactId>

                  <version>2.3.2</version>

                  <configuration>

                      <!-- <configLocation>${basedir}/springside-findbugs.xml</configLocation> -->

                      <!-- findbugs xml輸出-->                   <findbugsXmlOutput>true</findbugsXmlOutput>

                       <!-- findbugs xml輸出路徑-->         <findbugsXmlOutputDirectory>target/site</findbugsXmlOutputDirectory>

                  </configuration>

               </plugin>

     

    大家注意到了findbugs插件里,我注釋掉了一句話,其實(shí)這句話就是可以使用自己的fingbugs配置來(lái)做檢查。我用的是springside的一個(gè)xml文件。

     

    第四步:配置好相關(guān)文件之后,接下來(lái)就是執(zhí)行相關(guān)命令了。

    mvn compile findbugs:findbugs生成報(bào)告。報(bào)告生成的地址就是${項(xiàng)目根目錄}/target/site。也可以通過(guò)mvn findbugs:gui gui界面查看findbugsreport

    posted @ 2012-04-14 18:55 yangpingyu 閱讀(7205) | 評(píng)論 (0)編輯 收藏

    學(xué)習(xí)書(shū)單和資料

    從學(xué)校畢業(yè)到工作已經(jīng)2年半時(shí)間了,在豆瓣、當(dāng)當(dāng)、京東和亞瑪遜上關(guān)注了很多書(shū)籍,也比較喜歡逛書(shū)店。當(dāng)然買(mǎi)了很多和看了部分,自己家里很多書(shū)還沒(méi)看(人類(lèi)的惰性,借口)。在這兩年半時(shí)間內(nèi),走了一些彎路,所以想總結(jié)下自己的學(xué)習(xí)生涯。

     

    畢業(yè)的時(shí)候去了一家創(chuàng)業(yè)型的互聯(lián)網(wǎng)公司,在這家公司沒(méi)有任何培訓(xùn)機(jī)制,任何東西都需要靠自己來(lái)捉摸。根據(jù)工作需要看了struts2springhibernatejstljspservlet等一些J2EE相關(guān)組件的書(shū)和資料。僅靠這些技術(shù)也能搭建出一個(gè)符合產(chǎn)品的網(wǎng)站。接觸到infoq網(wǎng)站之后,了解了一些大型網(wǎng)站的架構(gòu)變遷等技術(shù),在一年的時(shí)間內(nèi)不斷追尋這些不符合自己目前需要的技術(shù),充其量就是開(kāi)闊了自己技術(shù)的眼界。由于互聯(lián)網(wǎng)公司的一些劣勢(shì),導(dǎo)致我有了跳槽的想法,但是出去面試之后,才知道自己是井底之蛙。自己也算熱愛(ài)技術(shù),也算努力學(xué)習(xí)和研究的,自己反思和總結(jié)了一下:不注重基礎(chǔ)。

     

    那么學(xué)習(xí)什么才算基礎(chǔ)呢?我主要列舉下我的學(xué)習(xí)書(shū)單:

            

    ü 計(jì)算機(jī)基礎(chǔ):任何軟件運(yùn)行的基礎(chǔ)。

    深入理解計(jì)算機(jī)系統(tǒng)(修訂版)

    計(jì)算機(jī)組成原

     

    ü 操作系統(tǒng):硬件管理的軟件,我們的應(yīng)用軟件主要依賴(lài)于操作系統(tǒng)。

    鳥(niǎo)哥的Linux私房菜 基礎(chǔ)學(xué)習(xí)篇

    操作系統(tǒng)原理

    Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)

     

    ü 數(shù)據(jù)結(jié)構(gòu):軟件=數(shù)據(jù)結(jié)構(gòu)+算法。其實(shí)操作系統(tǒng)軟件和應(yīng)用軟件都在大量應(yīng)用數(shù)據(jù)結(jié)構(gòu)。

    大話數(shù)據(jù)結(jié)構(gòu)

     

    ü 網(wǎng)絡(luò):系統(tǒng)一定需要與外部交互,那就需要網(wǎng)絡(luò)。

    計(jì)算機(jī)網(wǎng)絡(luò)

    TCP/IP詳解 1

    TCP/IP詳解 2

    TCP/IP詳解 3

    ü 數(shù)據(jù)庫(kù):存儲(chǔ)數(shù)據(jù)。

    數(shù)據(jù)庫(kù)系統(tǒng)概論

    MySQL 5 權(quán)威指南-(3)

    MySQL性能調(diào)優(yōu)與架構(gòu)設(shè)計(jì)

     

    ü 軟件工程:開(kāi)發(fā)軟件是一個(gè)大工程,需要有一套理論來(lái)管理軟件開(kāi)發(fā)。

    軟件工程

    敏捷軟件開(kāi)發(fā)

     

    ü 算法:尚未接觸。

     

    ü Java基礎(chǔ):具體的高級(jí)語(yǔ)言,最好的學(xué)習(xí)地方就是java的官方網(wǎng)站和開(kāi)源代碼。

    Java JDK6學(xué)習(xí)筆記

    Effective Java中文版

    Java編程思想 (第4版)

    Java網(wǎng)絡(luò)編程(中文版 第三版)

    JAVA并發(fā)編程實(shí)踐

    深入理解Java虛擬機(jī)

    Spring in Action中文版

    深入淺出Hibernate

    Struts2權(quán)威指南

     

    ü Java進(jìn)階:面向?qū)ο笏枷搿⒃O(shè)計(jì)模式和J2EE深入。

    Java與模式

    企業(yè)應(yīng)用架構(gòu)模式

    POJOs IN ACTION中文版

    J2EE設(shè)計(jì)開(kāi)發(fā)編程指南Expert One-on-One J2EE Design and Development

    Expert One-on-One J2EE Development without EJB

     

    學(xué)習(xí)了這些基礎(chǔ)之后,我們?cè)趤?lái)說(shuō)分布式,nosql,云計(jì)算,企業(yè)集成等等。只有掌握了基礎(chǔ)我們才能更好的創(chuàng)新。

    posted @ 2012-02-07 13:45 yangpingyu 閱讀(395) | 評(píng)論 (0)編輯 收藏

    jvm運(yùn)行時(shí)數(shù)據(jù)區(qū)域

    Java語(yǔ)言與c語(yǔ)言有一個(gè)非常重要的區(qū)別就是:內(nèi)存管理方式的不同,java語(yǔ)言?xún)?nèi)存管理不需要程序開(kāi)發(fā)人員關(guān)注,而c語(yǔ)言的內(nèi)存的請(qǐng)求和釋放都是開(kāi)發(fā)人員來(lái)處理。辯證的思維來(lái)看,不同內(nèi)存管理實(shí)現(xiàn)方式有優(yōu)點(diǎn)和缺點(diǎn),所以語(yǔ)言應(yīng)用的場(chǎng)景,效率會(huì)有很大不同。

     

    Jvm運(yùn)行時(shí)的數(shù)據(jù)區(qū)域主要有:程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、方法區(qū)和堆。其中程序計(jì)數(shù)器、虛擬機(jī)棧和本地方法棧是線程獨(dú)享,而方法區(qū)和堆是所有線程共享。

    ü 程序計(jì)數(shù)器:jvm每個(gè)線程都有一個(gè)程序計(jì)數(shù)器。在任一時(shí)刻都有一個(gè)線程的方法在運(yùn)行,如果這個(gè)方法不是本地方法,那么程序計(jì)數(shù)器存放的就是正在執(zhí)行的指令地址;如果是本地方法,那么程序計(jì)數(shù)器中存放的指定地址為undefined

    ü 虛擬機(jī)棧:當(dāng)jvm創(chuàng)建一個(gè)線程的時(shí)候就會(huì)為線程分配一個(gè)虛擬機(jī)棧。主要用于存放方法的一些本地變量和部分結(jié)果,一般這里的大小都是固定,但不是絕對(duì)。一個(gè)方法的執(zhí)行到完成就是棧的入棧和出棧。假設(shè)在某方法中定義了一個(gè)對(duì)象Object obj=new Object();其中obj是存放在棧上,而new Object()是在堆上分配。-Xss可以控制jvm虛擬機(jī)棧的大小。

    ü 本地方法棧:大體跟虛擬機(jī)棧類(lèi)似,不過(guò)是給本地方法使用的。虛擬機(jī)棧和本地方法棧在hotspot是沒(méi)有分開(kāi)實(shí)現(xiàn)的,而是統(tǒng)稱(chēng)為棧。

    ü 方法區(qū):主要存放靜態(tài)變量,常量,類(lèi)加載器加載的類(lèi)等一些信息。

    ü 堆:jvm絕大部分的對(duì)象分配都在堆上分配。-Xmn –Xmx是控制堆最小值和最大值,一般堆的大小在使用了超過(guò)mx設(shè)定的70%的時(shí)候,就會(huì)自動(dòng)擴(kuò)大到最大值,所以防止這種擴(kuò)大和縮小我們?cè)O(shè)置成一樣的值。

    posted @ 2012-02-07 10:27 yangpingyu 閱讀(291) | 評(píng)論 (0)編輯 收藏

    ClassCastException

    ClassCastException類(lèi)型轉(zhuǎn)換異常,是一個(gè)運(yùn)行時(shí)異常。

     

    非常常見(jiàn)就是不同類(lèi)型之間的強(qiáng)制類(lèi)型轉(zhuǎn)換就會(huì)拋出ClassCastException異常。還有一種就是不同ClassLoader加載的相同的類(lèi)型轉(zhuǎn)換也會(huì)拋出ClassCastException。接下來(lái)我用代碼來(lái)詳細(xì)解釋下。

     

    1、 強(qiáng)制類(lèi)型轉(zhuǎn)換

    public class ClassCastExceptionTest {

     

        /**

         * @param args

         */

        public static void main(String[] args) {

           Animal a1 = new Dog(); //1

           Animal a2 = new Cat(); //2

           Dog d1 = (Dog)a1;       //3

           Dog d2 = (Dog)a2;       //4

        }

    }

    把貓轉(zhuǎn)換成狗,是不對(duì)的。后面注釋為4的代碼是無(wú)法正常賦值的。

    Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to Dog

        at ClassCastExceptionTest.main(ClassCastExceptionTest.java:13)

     

     

    2、 不同classloader加載相同類(lèi)型類(lèi)之間的轉(zhuǎn)換

    import java.io.File;

    import java.net.URL;

    import java.net.URLClassLoader;

     

     

    public class ClassCastExceptionTest {

        /**

         * @param args

         */

        public static void main(String[] args) throws Exception {

           File file = new File(Thread.currentThread().getContextClassLoader().getResource("").getPath());

           URL[] urls = {file.toURL()};

           URLClassLoader classloader1 = new URLClassLoader(urls, ClassLoader.getSystemClassLoader().getParent());

           Class classloader1Animal1 = classloader1.loadClass("Dog");

           Dog dog1 = (Dog)classloader1Animal1.newInstance();

          

           URLClassLoader classloader2 = new URLClassLoader(urls, ClassLoader.getSystemClassLoader().getParent());

           Class classloader1Animal2 = classloader1.loadClass("Dog");

           Dog dog2 = (Dog)classloader1Animal1.newInstance();

          

           dog1 = dog2;

        }

     

    }

     

    代碼中我們看到dog1=dog2,這樣賦值是會(huì)拋異常的。

    Exception in thread "main" java.lang.ClassCastException: Dog cannot be cast to Dog

        at ClassCastExceptionTest.main(ClassCastExceptionTest.java:17)

     

    以后大家遇到classCastException的時(shí)候要注意了,不一定是強(qiáng)制類(lèi)型轉(zhuǎn)換導(dǎo)致的,也有可能不同的classloader加載了相同的類(lèi),然后這個(gè)類(lèi)不同的實(shí)例進(jìn)行賦值。

    posted @ 2012-01-10 16:07 yangpingyu 閱讀(580) | 評(píng)論 (0)編輯 收藏

    byte[]轉(zhuǎn)16進(jìn)制bug總結(jié)

    (一)問(wèn)題

             項(xiàng)目中需要對(duì)文件做md5sum,分兩步走:1、對(duì)文件流的每個(gè)字節(jié)用md5實(shí)例進(jìn)行update,然后進(jìn)行digest2digest返回長(zhǎng)度為16byte數(shù)組,一般我們需要把byte數(shù)組轉(zhuǎn)成16進(jìn)制字符串(很多開(kāi)源的md5加密算法如此實(shí)現(xiàn),真正的原因還不是很理解,可能是便于查看和傳輸)。具體的實(shí)現(xiàn)代碼如下:

             /**

        * 對(duì)文件進(jìn)行md5 sum操作

        * @param checkFile 要進(jìn)行做md5 sum的文件

        * @return

        */

        public static String md5sum(File checkFile){

           String md5sumResult = "";

           if(checkFile == null || (!checkFile.exists())){

               return md5sumResult;

           }

           MessageDigest digest = MessageDigest.getInstance("MD5");

           InputStream is = new FileInputStream(checkFile);

           byte[] buffer = new byte[8192];

           int read = 0;

           try {

               while( (read = is.read(buffer)) > 0) {

                  digest.update(buffer, 0, read);

               }

               byte[] md5sum = digest.digest();

               BigInteger bigInt = new BigInteger(1, md5sum);

               md5sumResult = bigInt.toString(16);

           }

           catch(IOException e) {

               throw new RuntimeException("Unable to process file for MD5", e);

           }

           finally {

               try {

                  is.close();

               }

               catch(IOException e) {

                  throw new RuntimeException("Unable to close input stream for MD5 calculation", e);

               }

           }

          

           return md5sumResult;

        }

     

        其中黃色背景色的轉(zhuǎn)換方式是有問(wèn)題的。為什么用bigint轉(zhuǎn)16進(jìn)制會(huì)有問(wèn)題呢,原因是bigint進(jìn)行16進(jìn)制轉(zhuǎn)換的時(shí)候第一個(gè)0被自動(dòng)去掉了.

       

     

    (二)正確解決方式

    那正確的方式是怎么樣的呢?下面有兩種不同的轉(zhuǎn)換方式,但是原理其實(shí)是一致的。

        第一種正確的方式(由王建提供):

        /**

        * 將字節(jié)數(shù)組轉(zhuǎn)換為16進(jìn)制字符串

        *

        * @param buffer

        * @return

        */

       public static String toHex(byte[] buffer) {

          StringBuffer sb = new StringBuffer(buffer.length * 2);

          for (int i = 0; i < buffer.length; i++) {

           sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));

           sb.append(Character.forDigit(buffer[i] & 15, 16));

          }

     

          return sb.toString();

       }

     

        第二種正確的方式:

        public static String bytes2HexString(byte[] b) {

           String ret = "";

           for (int i = 0; i < b.length; i++) {

               String hex = Integer.toHexString(b[i] & 0xFF);

               if (hex.length() == 1) {

                  hex = '0' + hex;

               }

               ret += hex;

           }

           return ret;

        }

     

    (三)問(wèn)題分析

        Md5算法對(duì)任何長(zhǎng)度的字符串進(jìn)行編碼最后輸出是128位長(zhǎng)整數(shù),也就是長(zhǎng)度為16byte數(shù)組。我們項(xiàng)目調(diào)用的是jdk實(shí)現(xiàn)的md5算法,所以一般是沒(méi)問(wèn)題的。

        接下來(lái)我們要處理的事情,分別循環(huán)數(shù)組,把每個(gè)字節(jié)轉(zhuǎn)換成2個(gè)16進(jìn)制字符,也就是說(shuō)每4位轉(zhuǎn)成一個(gè)16進(jìn)制字符。

       

        上面正確的兩種方式也就是做了這樣的事情。

        第一種方式:

           Character.forDigit((buffer[i] & 240) >> 4, 16)把字節(jié)的高4位取出右移4位換算成int,然后通過(guò)forDigit轉(zhuǎn)換成16進(jìn)制字符

           Character.forDigit(buffer[i] & 15, 16)把字節(jié)的低4位取出換算成int,然后通過(guò)forDigit轉(zhuǎn)換成16進(jìn)制字符

       

        第二種方式:

           Integer.toHexString(b[i] & 0xFF)把整個(gè)字節(jié)轉(zhuǎn)成int,然后toHexString也就是做高4位和低4位的運(yùn)算。但是這個(gè)方法如果高四位是0的話就不輸出任何東西,

    所以在輸出的字符前加0即可。

           b[i] & 0xFF就是把byte轉(zhuǎn)成int,為什么用與oxff做與運(yùn)算,是因?yàn)槿绻?/span>b[i]是負(fù)數(shù)的話,從8位變成32位會(huì)補(bǔ)1,所以需要與0xff做與運(yùn)算,可以把前面的24位全部清零,又可以表示成原來(lái)的字節(jié)了。

       

     

    附:

    盡量使用開(kāi)源提供的工具包,比如:

    org.apache.commons.codec.digest.DigestUtils.md5Hex(InputStream data)來(lái)對(duì)文件流進(jìn)行md5即可,更加方便,可靠。

    posted @ 2012-01-10 14:39 yangpingyu 閱讀(8067) | 評(píng)論 (2)編輯 收藏

    <2012年1月>
    25262728293031
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿

    隨筆分類(lèi)

    隨筆檔案

    收藏夾

    linux

    產(chǎn)品交互

    分析,設(shè)計(jì),架構(gòu)

    安全

    技術(shù)牛人

    數(shù)據(jù)庫(kù)

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲午夜久久久精品电影院| 美女网站免费福利视频| 亚洲色婷婷综合久久| 一区二区三区免费视频观看| 免费人成视频在线观看不卡| 亚洲AV成人无码网天堂| 国产美女无遮挡免费网站| jzzijzzij在线观看亚洲熟妇| 国产免费观看网站| 免费国产黄网站在线看| 亚洲精品和日本精品| 一级做a免费视频观看网站| 亚洲日韩中文在线精品第一| 国产va免费观看| 亚洲中文字幕无码一区| 91成人免费观看在线观看| 亚洲国产精品成人精品无码区在线 | 日韩免费电影网址| 图图资源网亚洲综合网站| 99视频精品全部免费观看| 亚洲国产成人在线视频| 可以免费看的卡一卡二| 亚洲七久久之综合七久久| 国产免费av片在线无码免费看| 国产亚洲情侣久久精品| 亚洲另类激情专区小说图片| 99精品免费视频| 久久夜色精品国产噜噜噜亚洲AV | 国产精品hd免费观看| 国产亚洲3p无码一区二区| 67194国产精品免费观看| 色噜噜亚洲男人的天堂| 国产精品美女自在线观看免费| 色网站在线免费观看| 激情97综合亚洲色婷婷五| 久久国产乱子伦精品免费看| 亚洲成aⅴ人片在线影院八| 成人免费毛片观看| 美女视频免费看一区二区| 中文字幕亚洲日韩无线码| 免费无码毛片一区二区APP|