顯示具有 JAVA程式 標籤的文章。 顯示所有文章
顯示具有 JAVA程式 標籤的文章。 顯示所有文章

2025/2/18

spring boot Operator SIMPLE_PROPERTY 錯誤

 錯誤訊息範例如下:

Caused by: java.lang.IllegalStateException: Operator SIMPLE_PROPERTY on searchDto requires a scalar argument, found class com.fasterxml.jackson.databind.JsonNode in method public abstract se.company.search.Search se.company.search.SearchRepository.findFirstBySearchDto(com.fasterxml.jackson.databind.JsonNode).
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.throwExceptionOnArgumentMismatch(PartTreeJpaQuery.java:171)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.validate(PartTreeJpaQuery.java:147)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:90)
    ... 73 common frames omitted.
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.throwExceptionOnArgumentMismatch(PartTreeJpaQuery.java:171) ~[spring-data-jpa-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.validate(PartTreeJpaQuery.java:147) ~[spring-data-jpa-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:90) ~[spring-data-jpa-2.2.4.RELEASE.jar:2.2.4.RELEASE]
    ... 74 common frames omitted


 

說明:

網路上找的都是要把結尾加上In...等解決方式

但是我不需要由JPA來幫我mapping,我會自己自定義查詢的method

 解決方式:

    正確: import org.springframework.data.jpa.repository.Query;

    錯誤:import org.springframework.data.jdbc.repository.query.Query;

原因:

  我POM.xml裡面 有引入

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-jdbc</artifactId>

</dependency>

 

 

 

 

2023/3/13

JPA+complex key+custom Query

 

來源:

https://www.cnblogs.com/520playboy/p/6512592.html 


整個來說,就是有複合主鍵

然後要使用 

public interface XxXXxxDAO extends CrudRepository<TcAgvjReady, String> {


如果報『.hibernate.QueryException: could not resolve property』

不要以為要什麼特殊設定

就是來源網站裡面說的 

『要寫xml的name』 ,而我bean裡面的id是什麼宣告,就宣告什麼


2019/10/16

JasperSoft report心得筆記-20191016


很多來源,
找有中文的:
https://www.cnblogs.com/liupuLearning/p/5810535.html

有兩個要注意:
<property name="net.sf.jasperreports.page.break.no.pagination" value="apply"/>

excel要能分頁
<property name="net.sf.jasperreports.export.xls.one.page.per.sheet" value="true"/>



1.設定不分頁


2.只有匯出excel,需要個別分頁










3. 同2,記得新增Break


4.如果要指定excel分頁名稱,拿其中一個textfield指定sheet name

5.excel匯出時,自動調整欄寬(待測試)
目前知道的是可以填滿整個欄寬



6.excel匯出後,凍結窗格

7.定期報表內,excel沒有框線
https://community.jaspersoft.com/questions/521719/excel-cell-border-not-displayed


8.文字自動換行設置
https://blog.csdn.net/liuxiyangyang/article/details/8949560

  A.選中要自動換行的text框,勾選中屬性面板中的「StretchWith Overflow」屬性
  B.選中該字段所在行的所有字段(包括行頭),在「屬性」面板中將「Stretch Type」設置為「Relative to Tallest Object」



2017/3/14

Lombok 安裝、入門 - 消除冗長的 java 代碼


來源:
http://www.blogjava.net/fancydeepin/archive/2012/07/12/lombok.html

lombok 提供了簡單的註解的形式來幫助我們簡化消除一些必須有但顯得很臃腫的 java 代碼。特別是相對於 POJO

重點是這一段:
lombok 註解:
    lombok 提供的註解不多,可以參考官方視頻的講解和官方文檔。
    Lombok 註解在線幫助文檔:http://projectlombok.org/features/index.    下面介紹幾個我常用的 lombok 註解:
        
@Data   :註解在類上;提供類所有屬性的 getting 和 setting 方法,此外還提供了equals、canEqual、hashCode、toString 方法
        
@Setter:註解在屬性上;為屬性提供 setting 方法
        
@Getter:註解在屬性上;為屬性提供 getting 方法
        
@Log4j :註解在類上;為類提供一個 屬性名為log 的 log4j 日誌對象
        
@NoArgsConstructor:註解在類上;為類提供一個無參的構造方法
        
@AllArgsConstructor:註解在類上;為類提供一個全參的構造方法

2016/6/4

C# sealed vs Java final

FROM:http://stackoverflow.com/questions/10170633/c-sharp-sealed-vs-java-final

回答的很精妙:

That's because final in Java means plenty of different things depending on where you use it whereas sealed in C# applies only to classes.
In Java final can be applied to:
  • classes, which means that the class cannot be inherited. This is the equivalent of C#'s sealed.   

  • methods, which means that the method cannot be overridden in a derived class. This is the default in C#, unless you declare a method as virtual and in a derived class this can be prevented for further derived classes with sealed again.

  • fields and variables, which means that they can only be initialized once. For fields the equivalent in C# is readonly.

自己的github


自己做個備忘,也替自己廣告(雖然這裡平常很冷清)
https://github.com/otaku119

2016/2/15

正規表示式 Regular Expression


From:
正規表示式 Regular Expression

資料來源:張智星的網站 – 正規表示式
正規表示式 說明及範例 比對不成立之字串
/a/ 含字母 “a” 的字串,例如 “ab”, “bac”, “cba” “xyz”
/a./ 含字母 “a” 以及其後任一個字元的字串,例如 “ab”, “bac”(若要比對.,請使用 \.) “a”, “ba”
/^xy/ 以 “xy” 開始的字串,例如 “xyz”, “xyab”(若要比對 ^,請使用 \^) “axy”, “bxy”
/xy$/ 以 “xy” 結尾的字串,例如 “axy”, “abxy”以 “xy” 結尾的字串,例如 “axy”, “abxy” (若要比對 $,請使用 \$) “xya”, “xyb”
[13579] 包含 “1” 或 “3” 或 “5” 或 “7” 或 “9” 的字串,例如:”a3b”, “1xy” “y2k”
[0-9] 含數字之字串 不含數字之字串
[a-z0-9] 含數字或小寫字母之字串 不含數字及小寫字母之字串
[a-zA-Z0-9] 含數字或字母之字串 不含數字及字母之字串
b[aeiou]t “bat”, “bet”, “bit”, “bot”, “but” “bxt”, “bzt”
[^0-9] 不含數字之字串(若要比對 ^,請使用 \^) 含數字之字串
[^aeiouAEIOU] 不含母音之字串(若要比對 ^,請使用 \^) 含母音之字串
[^\^] 不含 “^” 之字串,例如 “xyz”, “abc” “xy^”, “a^bc”
.
正規表示式的特定字元 說明 等效的正規表示式
\d 數字 [0-9]
\D 非數字 [^0-9]
\w 數字、字母、底線 [a-zA-Z0-9_]
\W 非 \w [^a-zA-Z0-9_]
\s 空白字元 [ \r\t\n\f]
\S 非空白字元 [^ \r\t\n\f]
.
正規表示式 說明
/a?/ 零或一個 a(若要比對? 字元,請使用 \?)
/a+/ 一或多個 a(若要比對+ 字元,請使用 \+)
/a*/ 零或多個 a(若要比對* 字元,請使用 \*)
/a{4}/ 四個 a
/a{5,10}/ 五至十個 a
/a{5,}/ 至少五個 a
/a{,3}/ 至多三個 a
/a.{5}b/ a 和 b中間夾五個(非換行)字元
.
字元 說明 簡單範例
\ 避開特殊字元 /A\*/ 可用於比對 “A*”,其中 * 是一個特殊字元,為避開其特殊意義,所以必須加上 “\”
^ 比對輸入列的啟始位置 /^A/ 可比對 “Abcd” 中的 “A”,但不可比對 “aAb”
$ 比對輸入列的結束位置 /A$/ 可比對 “bcdA” 中的 “A”,但不可比對 “aAb”
* 比對前一個字元零次或更多次 /bo*/ 可比對 “Good boook” 中的 “booo”,亦可比對 “Good bk” 中的 “b”
+ 比對前一個字元一次或更多次,等效於 {1,} /a+/ 可比對 “caaandy” 中的 “aaa”,但不可比對 “cndy”
? 比對前一個字元零次或一次 /e?l/ 可比對 “angel” 中的 “el”,也可以比對 “angle” 中的 “l”
. 比對任何一個字元(但換行符號不算) /.n/ 可比對 “nay, an apple is on the tree” 中的 “an” 和 “on”,但不可比對 “nay”
(x) 比對 x 並將符合的部分存入一個變數 /(a*) and (b*)/ 可比對 “aaa and bb” 中的 “aaa” 和 “bb”,並將這兩個比對得到的字串設定至變數 RegExp.$1 和 RegExp.$2。
xy 比對 x 或 y /a*b*/g 可比對 “aaa and bb” 中的 “aaa” 和 “bb”
{n} 比對前一個字元 n 次,n 為一個正整數 /a{3}/ 可比對 “lllaaalaa” 其中的 “aaa”,但不可比對 “aa”
{n,} 比對前一個字元至少 n 次,n 為一個正整數 /a{3,}/ 可比對 “aa aaa aaaa” 其中的 “aaa” 及 “aaaa”,但不可比對 “aa”
{n,m} 比對前一個字元至少 n 次,至多 m 次,m、n 均為正整數 /a{3,4}/ 可比對 “aa aaa aaaa aaaaa” 其中的 “aaa” 及 “aaaa”,但不可比對 “aa” 及 “aaaaa”
[xyz] 比對中括弧內的任一個字元 /[ecm]/ 可比對 “welcome” 中的 “e” 或 “c” 或 “m”
[^xyz] 比對不在中括弧內出現的任一個字元 /[^ecm]/ 可比對 “welcome” 中的 “w”、”l”、”o”,可見出其與 [xyz] 功能相反。(同時請注意 /^/ 與 [^] 之間功能的不同。)
[\b] 比對退位字元(Backspace character) 可以比對一個 backspace ,也請注意 [\b] 與 \b 之間的差別
\b 比對英文字的邊界,例如空格 例如 /\bn\w/ 可以比對 “noonday” 中的 ‘no’ ;
/\wy\b/ 可比對 “possibly yesterday.” 中的 ‘ly’
\B 比對非「英文字的邊界」 例如, /\w\Bn/ 可以比對 “noonday” 中的 ‘on’ ,
另外 /y\B\w/ 可以比對 “possibly yesterday.” 中的 ‘ye’
\cX 比對控制字元(Control character),其中 X 是一個控制字元 /\cM/ 可以比對 一個字串中的 control-M
\d 比對任一個數字,等效於 [0-9] /[\d]/ 可比對 由 “0” 至 “9” 的任一數字 但其餘如字母等就不可比對
\D 比對任一個非數字,等效於 [^0-9] /[\D]/ 可比對 “w” “a”… 但不可比對如 “7” “1” 等數字
\f 比對 form-feed 若是在文字中有發生 “換頁” 的行為 則可以比對成功
\n 比對換行符號 若是在文字中有發生 “換行” 的行為 則可以比對成功
\r 比對 carriage return
\s 比對任一個空白字元(White space character),等效於 [ \f\n\r\t\v] /\s\w*/ 可比對 “A b” 中的 “b”
\S 比對任一個非空白字元,等效於 [^ \f\n\r\t\v] /\S/\w* 可比對 “A b” 中的 “A”
\t 比對定位字元(Tab)
\v 比對垂直定位字元(Vertical tab)
\w 比對數字字母字元(Alphanumerical characters)或底線字母(”_”),等效於 [A-Za-z0-9_] /\w/ 可比對 “.A _!9” 中的 “A”、”_”、”9″。
\W 比對非「數字字母字元或底線字母」,等效於 [^A-Za-z0-9_] /\W/ 可比對 “.A _!9” 中的 “.”、” “、”!”,可見其功能與 /\w/ 恰好相反。
\ooctal 比對八進位,其中octal是八進位數目 /\oocetal123/ 可比對 與 八進位的ASCII中 “123” 所相對應的字元值。
\xhex 比對十六進位,其中hex是十六進位數目 /\xhex38/ 可比對 與 16進位的ASCII中 “38” 所相對應的字元。

2015/12/9

jsp頁面的頭部空白行


From:http://www.111cn.net/jsp/Java/55593.htm
           http://kirby86a.pixnet.net/blog/post/111632383-%E8%A8%AD%E5%AE%9Atomcat-7%EF%BC%8C%E5%8E%BB%E9%99%A4%E7%B7%A8%E8%AD%AF%E5%BE%8C%E7%9A%84jsp%E4%B8%8A%E6%96%B9%E7%94%A2%E7%94%9F%E5%A4%A7%E9%87%8F%E7%9A%84
原因是網頁上方宣告,
例如:
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
若是在宣告使用其他taglib或引入其他方法,那麼空白行就會更多,

方案一:
<%out.clear();%>
缺點:
後面的部分都要緊跟向前縮進不推,
主要是自己也還是暫用一行空白不推薦

方案二:
<%@ page trimDirectiveWhitespaces="true" %>

方案三: in web.xml
<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <trim-directive-whitespaces>true</trim-directive-whitespaces>
  </jsp-property-group>
</jsp-config>


方案四:
如果Tomcat是 Tomcat5.x版本,即JSP2.0和Servlet2.4的規範
web.xml:
<servlet>
         <servlet-name>jsp</servlet-name>
         <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
             <param-name>trimSpaces</param-name>
             <param-value>true</param-value>
         </init-param>
         <load-on-startup>3</load-on-startup>
     </servlet>

2015/8/5

task java:26503 blocked for more than 120 seconds


案發原因:
JAVA process一直活著,但莫名其妙無法服務,檢查/var/log/messages,發現有下面訊息:
Jul 31 06:25:19 localhost kernel: INFO: task java:6498 blocked for more than 120 seconds.
Jul 31 06:25:19 localhost kernel:      Not tainted 2.6.32-504.el6.x86_64 #1
Jul 31 06:25:19 localhost kernel: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
Jul 31 06:25:19 localhost kernel: java          D 0000000000000000     0  6498  26501 0x00000080
Jul 31 06:25:19 localhost kernel: ffff88003cd6be08 0000000000000082 ffff88003cd6bdc8 ffff88003cd6bdc8
Jul 31 06:25:19 localhost kernel: ffff88003cd6bdc8 ffff88000000070d 0000000000000001 00000009ffffffff
Jul 31 06:25:19 localhost kernel: ffff880000000000 ffffffffa0121e08 ffff88007c99d058 ffff88003cd6bfd8
Jul 31 06:25:19 localhost kernel: Call Trace:
Jul 31 06:25:19 localhost kernel: [<ffffffffa0121e08>] ? ext4_file_write+0x58/0x190 [ext4]
Jul 31 06:25:19 localhost kernel: [<ffffffff81236ba1>] ? file_has_perm+0xd1/0xe0
Jul 31 06:25:19 localhost kernel: [<ffffffff8152cae5>] rwsem_down_failed_common+0x95/0x1d0
Jul 31 06:25:19 localhost kernel: [<ffffffff8152cc43>] rwsem_down_write_failed+0x23/0x30
Jul 31 06:25:19 localhost kernel: [<ffffffff812989f3>] call_rwsem_down_write_failed+0x13/0x20
Jul 31 06:25:19 localhost kernel: [<ffffffff8152c142>] ? down_write+0x32/0x40
Jul 31 06:25:19 localhost kernel: [<ffffffff8114545c>] sys_mmap_pgoff+0x5c/0x2d0
Jul 31 06:25:19 localhost kernel: [<ffffffff81012499>] sys_mmap+0x29/0x30
Jul 31 06:25:19 localhost kernel: [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b
google大神告訴我:
http://www.blackmoreops.com/2014/09/22/linux-kernel-panic-issue-fix-hung_task_timeout_secs-blocked-120-seconds-problem/

Make it permanent

When the server seemed more stable and no Kernel/Swap/Memory Panic for a week, I edited /etc/sysctl.conf file to make these permanent after reboot.
someuser@servercore [/home/someuser]$ sudo vi /etc/sysctl.conf

vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
 reboot,繼續觀察是否解決

補充:
另外搜尋到關鍵字:hung_task_timeout_secs
查詢到相關資訊:

http://blog.uouo123.com/post/700.html

解決辦法:
按照告警裡的提示將該提醒disable
echo 0 > /proc/sys/kernel/hung_task_timeout_secs

意思就是:
告知是linux會設置40%的可用內存用來做系統cache,當flush數據時這40%內存中的數據由於和IO同步問題導致超時(120s),所將40%減小到10%,避免超時。






2015/5/19

about ThreadLocal......


From:
http://minglight.pixnet.net/blog/post/35569918-threadlocal
http://blog.csdn.net/qjyong/article/details/2158097

直接講感言:
threadLocal提供了一個比較安全的方式,利用currentThread為PKey,
來取得當前thread的區域變數
我自己也實做類似的方式,但是沒有threadLocal來的安全
建立一個大家都要繼承的Object,裡面宣告一個static的Map
 然後利用Thread.currentThread().getName()+"Name",來存放當時的TX與session

public abstract class ServerObject {
   protected final static HashMap<String,Thread> threadPoolHashMap=new HashMap<String, Thread>();
   protected final static HashMap<String,Object> threadPoolSessionObjectHashMap=new HashMap<String, Object>();
   protected Transaction tx;
   protected org.hibernate.Session Hibernatesession;
     protected void reloadProperty() throws FileNotFoundException, IOException {
        Hibernatesession=(Session) threadPoolSessionObjectHashMap.get(Thread.currentThread().getName()+"hibernate-session");
        tx= (Transaction) threadPoolSessionObjectHashMap.get(Thread.currentThread().getName()+"hibernate-transaction");
      }
   
}

一開始進入點,就先宣告好當時的session,並且宣告好開始TX
Hibernatesession = HibernateSessionFactory.getSession();
threadPoolSessionObjectHashMap.put(Thread.currentThread().getName()+"hibernate-session", Hibernatesession);
tx = Hibernatesession.beginTransaction();
threadPoolSessionObjectHashMap.put(Thread.currentThread().getName()+"hibernate-transaction", tx);

之後一層一層繼承下來,需要取用的時候才抓出來

這樣看起來好處是:自己開發的,自己習慣
壞處就是:其他object要取值、remove,無法控制

後續再來找時間研究 有沒有更幽雅寫法

2015/5/11

關於hibernate查詢--



來源:
http://www.cnblogs.com/balaamwe/archive/2012/03/13/2393912.html
http://shilinfeng.cool.blog.163.com/blog/static/1183214652013528113441283/

起因:
使用hibernate查詢一個TABLE,此table的資料,由另外一組hibernate來負責
剛啟動時正常,但是一段時間之後,就一直停留在固定一筆欄位
一開始推測:browser自己建立cache,所以要強制F5
後來還是一樣狀況
開始追查,推測是hibernate取出資料有錯
查詢到部分網頁,可解決方式有二:
A.每次重新取得一個session
B.使用flush

摘錄如下:

A.
問題描述:這個最開始查詢時是讀取數據庫的,但是在頁面如果對數據進行刪改後,再來查詢就會出現結果錯誤!
原因:查出的數據會放入到緩存中,而我插入和刪除數據用的是存儲過程做的,因為存儲過程會直接將數據插入到數據庫中而不會放入到緩存中,所以當再次查詢數據時由於是獲取的當前的session,就會默認從緩存中查找數據,就導致了查出的數據會和數據庫的數據不對應!
結局辦法就是重新打開一個session,就正常了!

HibernateUtil.getSessionFactory().openSession();

 B.
Hibernate會儘量將與數據庫的操作延遲,直到必須要與數據庫進行交互,例如save方法一般會在提交時才真正執行,最終在提交時會以批處理的方式與數據庫進行交互,以提高效率。
而將操作延遲,就是利用緩存,將最後要處理的操作放到緩存中。
通過設置session.setFlushMode(),可以精確控制Hibernate的FlushMode.
(1) FlushMode.AUTO:Hibernate判斷對象屬性有沒有改變,如果被更改成為髒數據,則在一個查詢語句前將更新此改動以保證數據庫的同步。這也是Hibernate的默認清理模式。
(2) FlushMode.COMMIT:在事務結束之前清理session的緩存。這樣有可能導致查出髒數據
(3) FlushMode.NEVER:除非強制調用Session.flush(),否則永遠不清理Session。相當於將數據庫設置為一個只讀的數據庫。
       【如果此時進行數據的寫入操作,會發生錯誤】
(4) FlushMode.ALWAYS:在每一個查詢數據之前都調用Session.flush()。很顯然這種效率很低。 

筆記下來,以後好查詢


2015/4/29

useing Log4J2 with Hibernate and slf4J,logger example




<?xml version="1.0" encoding="UTF-8"?>
<configuration xsixmlns="Log4j-config.xsd">
    <Appenders>
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>

        <RollingFile name="RollingFile_Listener" fileName="logs/SocketServerListener.log"
            filePattern="logs/$${date:yyyy-MM}/SockServerListener-%d{MM-dd-yyyy}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT"
                    onMismatch="DENY" />
            </Filters>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="500 MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>

        <RollingFile name="RollingFile_TRACE" fileName="logs/SocketServerTRACE.log"
            filePattern="logs/$${date:yyyy-MM}/SockServerTRACE-%d{MM-dd-yyyy}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO" onMatch="DENY"
                    onMismatch="NEUTRAL" />
                <ThresholdFilter level="DEBUG" onMatch="DENY"
                    onMismatch="NEUTRAL" />
                <ThresholdFilter level="TRACE" onMatch="ACCEPT"
                    onMismatch="DENY" />
            </Filters>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy max="10" />
        </RollingFile>
        <RollingFile name="RollingFile_DEBUG" fileName="logs/SocketServerDEBUG.log"
            filePattern="logs/$${date:yyyy-MM}/SockServerDEBUG-%d{MM-dd-yyyy}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO" onMatch="DENY"
                    onMismatch="NEUTRAL" />
                <ThresholdFilter level="DEBUG" onMatch="ACCEPT"
                    onMismatch="DENY" />
            </Filters>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="200 MB" />
            </Policies>
            <DefaultRolloverStrategy max="10" />
        </RollingFile>

        <RollingFile name="RollingFile_INFO" fileName="logs/SocketServer.log"
            filePattern="logs/$${date:yyyy-MM}/SockServer-%d{MM-dd-yyyy}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT"
                    onMismatch="DENY" />
            </Filters>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="500 MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>

    </Appenders>
    <Loggers>
        <logger name="org.hibernate.SQL">
            <level value="INFO" />
        </logger>
        <logger name="org.hibernate">
            <level value="INFO" />
        </logger>
        <logger name="SocketServerStatusListener" level="INFO"
            additivity="false">
            <AppenderRef ref="RollingFile_Listener" />
        </logger>
        <Root level="INFO">
            <AppenderRef ref="RollingFile_INFO" />
            <AppenderRef ref="RollingFile_TRACE" />
            <AppenderRef ref="RollingFile_DEBUG" />
            <AppenderRef ref="CONSOLE" />
        </Root>
    </Loggers>
</configuration>
 important:
myCLASSPATH=./JAR/JSON.jar:./JAR/c3p0-0.9.1.jar:./JAR/hibernate41.jar:./JAR/slf4j-api-1.7.6.jar:./JAR/log4j-api-2.1.jar:./JAR/log4j-core-2.1.jar:./JAR/log4j-1.2-api-2.1.jar:./JAR/slf4j-log4j12-1.7.6.jar:./JAR/httpclient-4.4.jar:./JAR/fluent-hc-4.4.jar:./JAR/httpclient-cache-4.4.jar:./JAR/httpclient-win-4.4.jar:./JAR/httpcore-4.4.jar:./JAR/httpmime-4.4.jar:./JAR/jna-4.1.0.jar:./JAR/jna-platform-4.1.0.jar:./JAR/commons-logging-1.2.jar:./JAR/hibernate-entitymanager-4.1.4.Final.jar:./JAR/antlr-2.7.7.jar:./JAR/dom4j-1.6.1.jar:./JAR/hibernate-commons-annotations-4.0.1.Final.jar:./JAR/hibernate-core-4.1.4.Final.jar:./JAR/hibernate-jpa-2.0-api-1.0.1.Final.jar:./JAR/hibernate-validator-4.2.0.Final.jar:./JAR/javassist-3.15.0-GA.jar:./JAR/jboss-logging-3.1.0.GA.jar:./JAR/jboss-transaction-api_1.1_spec-1.0.0.Final.jar:./JAR/hibernate-envers-4.1.4.Final.jar:./JAR/c3p0-0.9.1.jar:./JAR/hibernate-c3p0-4.1.4.Final.jar:./JAR/ehcache-core-2.4.3.jar:./JAR/hibernate-ehcache-4.1.4.Final.jar:./JAR/hibernate-infinispan-4.1.4.Final.jar:./JAR/infinispan-core-5.1.4.FINAL.jar:./JAR/jboss-marshalling-1.3.11.GA.jar:./JAR/jboss-marshalling-river-1.3.11.GA.jar:./JAR/jgroups-3.0.9.Final.jar:./JAR/rhq-pluginAnnotations-3.0.4.jar:./JAR/stax2-api-3.1.1.jar:./JAR/woodstox-core-asl-4.1.1.jar:./JAR/hibernate-proxool-4.1.4.Final.jar:./JAR/proxool-0.8.3.jar:./JAR/mysql-connector-java-5.0.8-bin.jar:./JAR/jboss-logging-3.1.3.GA.jar:./JAR/jboss-logging-annotations-1.2.0.Beta1.jar::./JAR/dom4j-1.6.1_2.jar:./JAR/xml-apis-1.0.b2.jar:./JAR/javassist-3.18.1-GA.jar:./JAR/antlr-2.7.7_2.jar:./JAR/jandex-1.1.0.Final.jar:./JAR/mysql-connector-java-5.0.5.jar:./JAR/log4j-1.2.17.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar

2015/4/23

java.security.InvalidKeyException: Illegal key size or default parameters



from:http://blog.csdn.net/shangpusp/article/details/7416603


使用AES加密時,當密鑰大於128時,代碼會拋出java.security.InvalidKeyException: Illegal key size or default parameters
Illegal key size or default parameters是指密鑰長度是受限制的,java運行時環境讀到的是受限的policy文件。文件位於${java_home}/jre/lib/security
這種限制是因為美國對軟件出口的控制。



解決辦法:

去掉這種限制需要下載Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.網址如下。
下載包的readme.txt 有安裝說明。就是替換${java_home}/jre/lib/security/ 下面的local_policy.jar和US_export_policy.jar

jdk 5: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jce_policy-1.5.0-oth-JPR
jdk6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

2015/3/31

linux、windows、andorid使用JAVA的AES



提示:如果你用properties,請記得linux跟windows的換行.......

原理:
每個都要有一個KEY,把字串(密碼)用sha-256 來Hash之後,當作KEY
然後加解密

參考:http://magiclen.org/aes/
public static String DataENCryptDECryptProcess(int ENDNMode, String messages, String keyString)
{
String ALGORITHM = "AES";
String TRANSFORMATION = "AES/CBC/PKCS5Padding";
Cipher cipher;
String IvString = "1234567890ABCDEF";
IvParameterSpec DEFAULT_IV = new IvParameterSpec(IvString.getBytes("UTF-8"));

byte[] data=keyString.getBytes("UTF-8");
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(data);
byte[] keyBytes = new byte[32];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
Skeyspec = new SecretKeySpec(keyBytes, ALGORITHM);
cipher = Cipher.getInstance(TRANSFORMATION);

switch (ENDNMode) {
    case ENCRYPT:
       decryptFrom = messages.getBytes("UTF-8");
       cipher.init(Cipher.ENCRYPT_MODE, Skeyspec,DEFAULT_IV);
       result = cipher.doFinal(decryptFrom);
     return new String(alonaBase64.getEncoder().encode(result),"UTF-8");
     case DECRYPT:
       decryptFrom = alonaBase64.getDecoder().decode(messages);
       cipher.init(Cipher.DECRYPT_MODE, Skeyspec,DEFAULT_IV);
       result = cipher.doFinal(decryptFrom);
    return new String(result, "UTF-8");
    default:
    return "ERROR";
}
}

找過另外一種解法,但是在windows與LINUX上面搭配有問題的解法:
經過測試,還是沒辦法解決win與linux上的KEY不同
原因: SecureRandom 實現完全隨操作系統本身的內部狀態,除非調用方在調用 getInstance 方法之後又調用了 setSeed 方法;該實現在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系統上則不同。
if (detectPlatform("Android")) {
    secureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
    System.out.println("iswindows=" + detectPlatform("windows"));
    System.out.println("isLinux=" + detectPlatform("linux"));
    secureRandom = SecureRandom.getInstance("SHA1PRNG");
}   
    secureRandom.setSeed(keyString.getBytes("UTF-8"));
    kgen.init(keysize,secureRandom);
    SecretKey secretKey = kgen.generateKey();
    byte[] enCodeFormat = secretKey.getEncoded();
    System.out.println("enCodeFormat="+parseByte2HexStr(enCodeFormat));
    Skeyspec = new SecretKeySpec(enCodeFormat, ALGORITHM);

2014/11/13

你不知道的 字符集和編碼(編碼字符集與字符集編碼)






http://blog.jobbole.com/79610/

你不知道的 字符集和編碼(編碼字符集與字符集編碼)

我的上篇文章,有朋友提出字符集和編碼的區別,我在此立文和大家討論下
常說的字符集和編碼區別,其實就是編碼字符集和字符集編碼的區別,其實,單單如果只是說字符集,沒有任何編碼的概念的話,那麼字符集其實僅僅是一個 簡單的字符的集合,或者說是一個抽象的字符的集合,包括文字,符號等等,不參與任何存儲形式,只是存在這麼各種各樣標準的字符的集合
如果僅僅是抽象的字符集,我們是無需拿出討論的,因為沒有任何異議,通俗易懂,而常說的字符集指的編碼字符集,比如常見的 unicode、ascii、gb2312、gbk等,這些我們常稱做為字符集(其實是編碼字符集),這些字符集,比如unicode其實本質上是已經 「編碼」過的字符集,即每個字符都有唯一的整數編號,每個字符都有自己特有的編號,同一個字符在不同編碼字符集中編號也會不同,當然很多編碼字符集都是 ascll的超集,所以ascll字符集的編號與很多編碼字符集中編號都一樣,比如英文字母「A」,在ASCII及Unicode及GB2312中,均是 第0×41個字符,說到這裡朋友一定注意到了我上面再描述「 unicode其實本質上是已經「編碼」過的字符集」中的「編碼」二字加了雙引號,我要強調的是這裡的「編碼」並不是真的我下面要說的編碼,這裡只是為每 個字符編了一個對應的編號,但是我們還是習慣專業的稱呼為「編碼字符集」
我們經常說「文章採用的是utf-8編碼方式」
我對於這個編碼方式的意義,個人理解是 將一個字符的整數編號用一個什麼二進制的整數值來對應並在計算機存儲。這和上面說的編碼字符集中的「編碼」千差萬別,這裡我們稱之為「字符集編碼」,即我們常說的編碼
說到這裡,很多人會覺得那麼unicode和utf-8的區別在哪裡?既然上文說到unicode是編碼字符集,那麼utf-8又是什麼?就是常說的編碼?
「文章採用的是utf-8編碼方式」,個人覺得準確的說法是「文章採用的是基於unicode編碼字符集的utf-8的編碼方案」,即
即unicode本身作為編碼字符集沒有任何存儲形式,只是一個編號和字符對應的表而已,如何在計算機存儲?你可能想到了乾脆直接把編號當作二進制 數值來直接存儲,那麼為什麼不這麼做呢?這也算是一種字符集編碼方案,就是基於unicode編碼字符集的utf-32編碼方案,那麼有沒有更加智能一點 的編碼方案呢?為什麼會沒有呢?那就是utf-8、utf-16等等,    等等,在我解釋為何要用utf-8編碼方案的時候,我必須說明一件事情:如下
我在上一篇文章《你不知道的 頁面編碼,瀏覽器選擇編碼,get,post各種亂碼由來》 中說過:「如何查看中文字符的十六進制字符串?方 法:BitConverter.ToString(System.Text.Encoding.UTF8.GetBytes(「阿道夫」));」 請注意我可以改為「System.Text.Encoding.Unicode.GetBytes」 如下圖是vs2013 Encoding鍵入「.」後的智能提示
112227067411272112226562562235
(列表過長,用兩幅圖分別截圖)
上圖有兩個疑問:
1、如果說unicode是編碼字符集,為何會出現在和utf-8這種編碼方案並列的列表中?
2、ASCII或者gb2312都是編碼字符集為何也會出現在和utf-8這種編碼方案並列的列表中?
我們假設有兩個猜測:
1、此處的unicode並不是真正的unicode編碼字符集,可能只是一種和unicode編碼字符集關係非常緊密的一種編碼方案
2、ASCII或者gb2312(其實就是圖中的Default,即操作系統當前的編碼,國內一般為gb2312)是編碼字符集沒有錯,但是對於 ASCII或者gb2312都只有唯一一種編碼,那麼我稱呼它們為ASCII編碼或者GB2312編碼也沒有問題,既然這樣,那我把ascii和 gb2312加入和utf-8這種編碼方案並列的列表中也理所當然?
我的兩個假設,很快得到論證
1、在Encoding 的元數據看到:
1
2
3
4
5
6
7
//
        // 摘要:
        //     获取使用 Little-Endian 字节顺序的 UTF-16 格式的编码。
        //
        // 返回结果:
        //     使用 Little-Endian 字节顺序的 UTF-16 格式的编码。
        public static Encoding Unicode { get; }
這裡解釋在這裡的unicode其實本質上「獲取使用 Little-Endian 字節順序的 UTF-16 格式的編碼」,即使基於unicode編碼字符集的utf-16編碼方案,類似的有BigEndianUnicode(獲取使用 Big Endian 字節順序的 UTF-16 格式的編碼)
2、一般的ASCII或者gb2312,我們可以稱呼為ASCII字符集也可以稱呼為ASCII編碼,只是意義不同而已,因為對於ASCII編碼字符集或 者gb2312編碼字符集都只有唯一一種編碼,就是ASCII編碼和GB2312編碼,那麼列表中顯示的ASCII和GB2312指的不是編碼字符集而是 ASCII和GB2312的編碼方案,我想正是這種原因,才在很多時候,不管是字符集賦值還是編碼方案賦值都可以直接用gb2312或者ascii,比 如:
Encoding gb2312 = Encoding.GetEncoding(「gb2312〞);
Response.ContentEncoding = gb2312;//編碼
Response.Charset=」gb2312〞;//字符集
總結下的說:
就是unicode是字符集,不是編碼!但是ascii(gb2312)是字符集,這個說法肯定正確,但是我表達為「ascii編碼」也不能說大錯特錯,但是這種說法讓人誤解,如果一定要說那麼就說「ascii編碼字符集的編碼」
如果理解上面兩個假設的論證道理,那麼我們繼續討論之前暫停的話題,即「解釋為何要用utf-8等編碼方案(其他utf編碼方案類似)」
utf-8將很大一部分基於unicode編碼字符集的字符的整數編號作了變換後存儲在計算機中。(引用)以「漢」字為例,「漢」的Unicode值為 0x6C49,但其編碼為UTF-8格式後的值為0xE6B189(注意到變成了三個字節)。對於UTF-16編碼方案,則是對unicode編碼字符集 中的前65536個字符編號都不做變換,直接作為計算機存儲時使用的值(對65536以後的字符,仍然要做變換),例如「漢」字的Unicode編號為 0x6C49,那麼經過UTF-16編碼後存儲在計算機上時,它的表示仍為0x6C49,對於UTF-32編碼方案,他對所有的Unicode字符均不做 變換,直接使用編號存儲,只是這種編碼方案太浪費存儲空間(就連1個字節就可以搞定的英文字符,它都必須使用4個字節)
既然unicode編碼字符集有如此多的編碼方案,那麼
utf-8,字母數字符號等佔1字節,漢字佔三字節
utf-16,對unicode編碼字符集中的前65536個字符都佔兩個字節
utf-32,全部佔四字節
如果還有人問:
「unicode編碼每個字符佔幾個字節」,我們可以理直氣壯的說,第一unicode不是編碼!第二每個字符具體佔多少字節是要看編碼方案!
很多面試題會問:
1
2
3
string param = "abc阿道夫";
int length1 = System.Text.Encoding.Unicode.GetBytes(param).Length;//别忘了这里的unicode本质是utf-16编码方案
int length2 = param.Length;
那麼答案就是12和6了
最後,對於gb2312或者ascii編碼字符集的字符的編號就是直接存儲在計算機中的二進制數,也就是說gb2312和ascii編碼字符集都只 有一種編碼方案,因為在gb2312編碼字符集中的ascii字符集部分的編號並沒有變化(即和ascii編碼字符集中的編碼一致),所以gb2312的 ascii部分字符存入計算機的二進制數還是佔用1個字節,而中文字符存入計算機的二進制數也是該中文字符在gb2312編碼字符集中的編號,該編號一般 轉換成二進制數都佔兩個字節,這個過程也就變成了所謂的gb2312編碼
如果上面的改為System.Text.Encoding.Default.GetBytes(param).Length,則值就是9和6了
如果需要瞭解更加深入的編碼內部原理請參考:
http://blog.csdn.net/nodeathphoenix/article/details/7057760

2014/6/26

java 1.7與iDrac無法啟動KVM出現:missing required permissions manifest attribute


關鍵字:missing required permissions manifest attribute
參考下面兩個連結
http://corden-hsu.blogspot.com/2014/03/java.html
http://2hei.net/connect-to-dell-idrac6-virtual-console.html#more-566

原因無他,JAVA 1.7之後多了一個RIA權限設定
舊版的就被犧牲,所以我實際解決方法:
把他媽的JAVA安全性給調整到「中」

搞定,收工

2008/6/9

[轉]明明白白Unsupported major.minor version 49.0的錯誤

轉載自http://www.blogjava.net/Unmi/archive/2007/12/04/165035.html
一:要解決的問題

我 們在嘗鮮 JDK1.5 的時候,相信不少人遇到過 Unsupported major.minor version 49.0 錯誤,當時定會茫然不知所措。因為剛開始那會兒,網上與此相關的中文資料還不多,現在好了,網上一找就知道是如何解決,大多會告訴你要使用 JDK 1.4 重新編譯。那麼至於為什麼,那個 major.minor 究竟為何物呢?這就是本篇來講的內容,以使未錯而先知。

我覺得我是比 較幸運的,因為在遇到那個錯誤之前已研讀過《深入 Java 虛擬機》第二版,英文原書名為《Inside the Java Virtual Machine》( Second Edition),看時已知曉 major.minor 藏匿於何處,但沒有切身體會,待到與 Unsupported major.minor version 49.0 真正會面試,正好是給我驗證了一個事實。

首先我們要對 Unsupported major.minor version 49.0 建立的直接感覺是:JDK1.5 編譯出來的類不能在 JVM 1.4 下運行,必須編譯成 JVM 1.4 下能運行的類。(當然,也許你用的還是 JVM 1.3 或 JVM 1.2,那麼就要編譯成目標 JVM 能認可的類)。這也解決問題的方向。

二:major.minor 棲身於何處

何謂 major.minor,且又居身於何處呢?先感性認識並找到 major.minor 來。

寫一個 Java Hello World! 代碼,然後用 JDK 1.5 的編譯器編譯成,HelloWorld.java

  1. package com.unmi;
  2. public class HelloWorld
  3. {
  4. public static void main(String[] args)
  5. {
  6. System.out.println("Hello, World!");
  7. }
  8. }


用 JDK 1.5 的 javac -d . HelloWorld.java 編譯出來的字節碼 HelloWorld.class 用 UltraEdit 打開來的內容如圖所示:

HelloWorldClassUnmi.jpg


從 上圖中我們看出來了什麼是 major.minor version 了,它相當於一個軟件的主次版本號,只是在這裡是標識的一個 Java Class 的主版本號和次版本號,同時我們看到 minor_version 為 0x0000,major_version 為 0x0031,轉換為十制數分別為0 和 49,即 major.minor 就是 49.0 了。

三:何謂 major.minor 以及何用

Class 文件的第 5-8 字節為 minor_version 和 major_version。Java class 文件格式可能會加入新特性。class 文件格式一旦發生變化,版本號也會隨之變化。對於 JVM 來說,版本號確定了特定的 class 文件格式,通常只有給定主版本號和一系列次版本號後,JVM 才能夠讀取 class 文件。如果 class 文件的版本號超出了 JVM 所能處理的有效範圍,JVM 將不會處理該 class 文件。

在 Sun 的 JDK 1.0.2 發佈版中,JVM 實現支持從 45.0 到 45.3 的 class 文件格式。在所有 JDK 1.1 發佈版中的 JVM 都能夠支持版本從 45.0 到 45.65535 的 class 文件格式。在 Sun 的 1.2 版本的 SDK 中,JVM 能夠支持從版本 45.0 到46.0 的 class 文件格式。

1.0 或 1.2 版本的編譯器能夠產生版本號為 45.3 的 class 文件。在 Sun 的 1.2 版本 SDK 中,Javac 編譯器默認產生版本號為 45.3 的 class 文件。但如果在 javac 命令行中指定了 -target 1.2 標誌,1.2 版本的編譯器將產生版本號為 46.0 的 class 文件。1.0 或 1.1 版本的 JVM 上不能運行使用-target 1.2 標誌所產生的 class 文件。

JVM 實現的 第二版中修改了對 class 文件主版本號和次版本號的解釋。對於第二版而言,class 文件的主版本號與 Java 平台主發佈版的版本號保持一致(例如:在 Java 2 平台發佈版上,主版本號從 45 升至 46),次版本號與特定主平台發佈版的各個發佈版相關。因此,儘管不同的 class 文件格式可以由不同的版本號表示,但版本號不一樣並不代表 class 文件格式不同。版本號不同的原因可能只是因為 class 文件由不同發佈版本的 java 平台產生,可能 class 文件的格式並沒有改變。

上面三段節選自《深入 Java 虛擬機》,囉嗦一堆,JDK 1.2 開啟了 Java 2 的時代,但那個年代仍然離我們很遠,我們當中很多少直接跳在 JDK 1.4 上的,我也差不多,只是項目要求不得不在一段時間裡委屈在 JDK 1.3 上。不過大致我們可以得到的信息就是每個版本的 JDK 編譯器編譯出的 class 文件中都帶有一個版本號,不同的 JVM 能接受一個範圍 class 版本號,超出範圍則要出錯。不過一般都是能向後兼容的,知道 Sun 在做 Solaris 的一句口號嗎?保持對先前版本的 100% 二進制兼容性,這也是對客戶的投資保護。

四:其他確定 class 的 major.minor version 辦法

1)Eclipse 中查看
Eclipse 3.3 加入的新特徵,當某個類沒有關聯到源代碼,打開它會顯示比較詳細的類信息,當然還未到源碼級別了,看下圖是打開 2.0 spring.jar 中 ClasspathXmlApplicationContext.class 顯示的信息

eclipseclass1.jpg


2)命令 javap -verbose
對於編譯出的 class 文件用 javap -verbose 能顯示出類的 major.minor 版本,見下圖:


JavapVerboseUnmi.jpg

3) MANIFEST 文件
把 class 打成的 JAR 包中都會有文件 META-INF\MANIFEST,這個文件一般會有編譯器的信息,下面列幾個包的 META-INF\MANIFEST 文件內容大家看看
·Velocity-1.5.jar 的 META-INFO\MANIFEST 部份內容
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: Apache Ant
Package: org.apache.velocity
Build-Jdk: 1.4.2_08
Extension-Name: velocity
我們看到是用 ant 打包,構建用的JDK是 1.4.2_08,用 1.4 編譯的類在 1.4 JVM 中當然能運行。如果那人用 1.5 的 JDK 來編譯,然後用 JDK 1.4+ANT 來打包就太無聊了。
·2.0 spring.jar 的 META-INFO\MANIFEST 部份內容
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 1.5.0_08-b03 (Sun Microsystems Inc.)
Implementation-Title: Spring Framework
這下要注意啦,它是用的 JDK 1.5 來編譯的,那麼它是否帶了 -target 1.4 或 -target 1.3 來編譯的呢?確實是的,可以查看類的二進制文件,這是最保險的。所在 spring-2.0.jar 也可以在 1.4 JVM 中加載執行。
·自已一個項目中用 ant 打的 jar 包的 META-INFO\MANIFEST
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 1.4.2-b28 (Sun Microsystems Inc.)
用的是 JDK 1.4 構建打包的。

第 一第二種辦法能明確知道 major.minor version,而第三種方法應該也沒問題,但是碰到變態構建就難說了,比如誰把那個 META-INFO\MANIFEST 打包後換了也未可知。直接查看類的二進制文件的方法可以萬分保證,準確無誤,就是工具篡改我也認了。

五:編譯器比較及症節之所在

現在不妨從 JDK 1.1 到 JDK 1.7 編譯器編譯出的 class 的默認 minor.major version 吧。(又走到 Sun 的網站上翻騰出我從來都沒用過的古董來)

JDK 編譯器版本target 參數十六進制 minor.major十進制 minor.major
jdk1.1.8不能帶 target 參數00 03 00 2D45.3
jdk1.2.2不帶(默認為 -target 1.1)00 03 00 2D45.3
jdk1.2.2-target 1.200 00 00 2E46.0
jdk1.3.1_19不帶(默認為 -target 1.1)00 03 00 2D45.3
jdk1.3.1_19-target 1.300 00 00 2F47.0
j2sdk1.4.2_10不帶(默認為 -target 1.2)00 00 00 2E46.0
j2sdk1.4.2_10-target 1.400 00 00 3048.0
jdk1.5.0_11不帶(默認為 -target 1.5)00 00 00 3149.0
jdk1.5.0_11-target 1.4 -source 1.400 00 00 3048.0
jdk1.6.0_01不帶(默認為 -target 1.6)00 00 00 3250.0
jdk1.6.0_01-target 1.500 00 00 3149.0
jdk1.6.0_01-target 1.4 -source 1.400 00 00 3048.0
jdk1.7.0不帶(默認為 -target 1.6)00 00 00 3250.0
jdk1.7.0-target 1.700 00 00 3351.0
jdk1.7.0-target 1.4 -source 1.400 00 00 3048.0
Apache Harmony 5.0M3不帶(默認為 -target 1.2)00 00 00 2E46.0
Apache Harmony 5.0M3-target 1.400 00 00 3048.0

上面比較是 Windows 平台下的 JDK 編譯器的情況,我們可以此作些總結:

1) -target 1.1 時 有次版本號,target 為 1.2 及以後都只用主版本號了,次版本號為 0
2) 從 1.1 到 1.4 語言差異比較小,所以 1.2 到 1.4 默認的 target 都不是自身相對應版本
3) 1.5 語法變動很大,所以直接默認 target 就是 1.5。也因為如此用 1.5 的 JDK 要生成目標為 1.4 的代碼,光有 -target 1.4 不夠,必須同時帶上 -source 1.4,指定源碼的兼容性,1.6/1.7 JDk 生成目標為 1.4 的代碼也如此。
4) 1.6 編譯器顯得較為激進,默認參數就為 -target 1.6。因為 1.6 和 1.5 的語法無差異,所以用 -target 1.5 時無需跟著 -source 1.5。
5) 注意 1.7 編譯的默認 target 為 1.6
6) 其他第三方的 JDK 生成的 Class 文件格式版本號同對應 Sun 版本 JDK
7) 最後一點最重要的,某個版本的 JVM 能接受 class 文件的最大主版本號不能超過對應 JDK 帶相應 target 參數編譯出來的 class 文件的版本號

上面那句話有點長,一口氣讀過去不是很好理解,舉個例子:1.4 的 JVM 能接受最大的 class 文件的主版本號不能超過用 1.4 JDK 帶參數 -target 1.4 時編譯出的 class 文件的主版本號,也就是 48。

因為 1.5 JDK 編譯時默認 target 為 1.5,出來的字節碼 major.minor version 是 49.0,所以 1.4 的 JVM 是無法接受的,只有拋出錯誤。

那麼又為什麼從 1.1 到 1.2、從 1.2 到 1.3 或者從 1.3 到 1.4 的 JDK 升級不會發生 Unsupported major.minor version 的錯誤呢,那是因為 1.2/1.3/1.4 都保持了很好的二進制兼容性, 看看 1.2/1.3/1.4 的默認 target 分別為 1.1/1.1/1.2 就知道了,也就是默認情況下1.4 JDK 編譯出的 class 文件在 JVM 1.2 下都能加載執行,何況於 JVM 1.3 呢?(當然要去除使用了新版本擴充的 API 的因素)

六:找到問題解決的方法

那 麼現在如果碰到這種問題該知道如何解決了吧,還會像我所見到有些兄弟那樣,去找個 1.4 的 JDK 下載安裝,然後用其重新編譯所有的代碼嗎?其實大可不必如此費神,我們一定還記得 javac 還有個 -target 參數,對啦,可以繼續使用 1.5 JDK,編譯時帶上參數 -target 1.4 -source 1.4 就 OK 啦,不過你一定要對哪些 API 是 1.5 JDK 加入進來的瞭如指掌,不能你的 class 文件拿到 JVM 1.4 下就會 method not found。目標 JVM 是 1.3 的話,編譯選項就用 -target 1.3 -source 1.3 了。

相應的如果使用 ant ,它的 javac 任務也可對應的選擇 target 和 source



如果是在開發中,可以肯定的是現在真正算得上是 JAVA IDE 對於工程也都有編譯選項設置目標代碼的。例如 Eclipse 的項目屬性中的 Java Compiler 設置,如圖


EclipseCompiler.JPG


自 已設定編譯選項,你會看到選擇不同的 compiler compliance level 是,Generated class files compatibility 和 Source compatibility 也在變,你也可以手動調整那兩項,手動設置後你就不用很在乎用的什麼版本的編譯器了,只要求他生成我們希望的字節碼就行了,再引申一下就是即使源代碼是用 VB 寫的,只要能編譯成 JVM 能執行的字節碼都不打緊。在其他的 IDE 也能找到相應的設置對話框的。

其他時候,你一定要知道當前的 JVM 是什麼版本,能接受的字節碼主版本號是多少(可對照前面那個表)。獲息當前 JVM 版本有兩種途徑:

第一:如果你是直接用 java 命令在控制台執行程序,可以用 java -version 查看當前的 JVM 版本,然後確定能接受的 class 文件版本

第 二:如果是在容器中執行,而不能明確知道會使用哪個 JVM,那麼可以在容器中執行的程序中加入代碼 System.getProperty("java.runtime.version"); 或 System.getProperty("java.class.version"),獲得 JVM 版本和能接受的 class 的版本號。

最 後一絕招,如果你不想針對低版本的 JVM 用 target 參數重新編譯所有代碼;如果你仍然想繼續在代碼中用新的 API 的話;更有甚者,你還用了 JDK 1.5 的新特性,譬如泛型、自動拆裝箱、枚舉等的話,那你用 -target 1.4 -source 1.4 就沒法編譯通過,不得不重新整理代碼。那麼告訴你最後一招,不需要再從源代碼著手,直接轉換你所正常編譯出的字節碼,繼續享用那些新的特性,新的 API,那就是:請參考之前的一篇日誌:Retrotranslator讓你用JDK1.5的特性寫出的代碼能在JVM1.4中運行,我就是這麼用的,做好測試就不會有問題的。

七:再議一個實際發生的相關問題

這 是一個因為拷貝 Tomcat 而產生的 Unsupported major.minor version 49.0 錯誤。情景是:我本地安裝的是 JDK 1.5,然後在網上找了一個 EXE 的 Tomcat 安裝文件安裝了並且可用。後來同事要一個 Tomcat,不想下載或安裝,於是根據我以往的經驗是把我的 Tomcat 整個目錄拷給他應該就行了,結果是拿到他那裡瀏覽 jsp 文件都出現 Unsupported major.minor version 49.0 錯誤,可以確定的是他安裝的是 1.4 的 JDK,但我還是有些納悶,先前對這個問題還頗有信心的我傻眼了。慣性思維是編譯好的 class 文件拿到低版本的 JVM 會出現如是異常,可現並沒有用已 JDK 1.5 編譯好的類要執行啊。

後來仔細看異常信息,終於發現了 %TOMCAT_HOME%\common\lib\tools.jar 這一眉目,因為 jsp 文件需要依賴它來編譯,打來這個 tools.jar 中的一個 class 文件來看看,49.0,很快我就明白原來這個文件是在我的機器上安裝 Tomcat 時由 Tomcat 安裝程序從 %JDK1.5%\lib 目錄拷到 Tomcat 的 lib 目錄去的,造成在同事機器上編譯 JSP 時是 1.4 的 JVM 配搭著 49.0 的 tools.jar,那能不出錯,於是找來 1.4 JDK 的 tools.jar 替換了 Tomcat 的就 OK 啦。

八:小結

其實理解 major.minor 就像是我們可以這麼想像,同樣是微軟件的程序,32 位的應用程序不能拿到 16 位系統中執行那樣。

如果我們發佈前瞭解到目標 JVM 版本,知道怎麼從 java class 文件中看出 major.minor 版本來,就不用等到服務器報出異常才著手去解決,也就能預知到可能發生的問題。

其他時候遇到這個問題應具體解決,總之問題的根由是低版本的 JVM 無法加載高版本的 class 文件造成的,找到高版本的 class 文件處理一下就行了。

2008/6/2

關於java的Out of Memory--websphere

2007-08-21
關於java的Out of Memory(內存洩漏) - [workspace]

昨天項目上線測試發生了Out of Memory的JVM錯誤,導致系統down掉並且服務器文件系統撐爆。檢查原因是出現過多內存洩漏,系統的可用內存和性能持續下降;最終將導致內存不足 (OutOfMemory)。我們開發用的是IBM WebSphere平台,在websphere/AppServer下生成大量javacore*、heapdump*之類的文件,致使 websphere的垃圾回收功能失敗而導致。其中,javacore文件是關於cpu的,heapdump文件是關於內存的。

生產環境是 ibm小型機,按照手冊修改了:應用程序服務器 > server1 > 進程定義 > Java 虛擬機,將"最大堆大小(默認為 256)"改為768或1024以上。刪除文件系統中的javacore*,heapdump*後基本恢復正常。分析原因,一是JVM設置問題,二(最終原因)程序不夠健壯,很多資源沒有即時釋放導致資源撐爆。尤其是數據庫連接資源。以前也遇到過進程掛起的情況,與此次不同,進程掛起主要原因是SQL查詢不能及時返回結果導致頁面一直等待資源返回而掛起(suspend)。三是產生大數據量的結果集返回結果。一直懷疑我們用的數據結構不夠合理,但是也沒有嘗試修改。

總結一下:

關於架構應該使用健全的模式,使用資源後要及時釋放和回收垃圾;

儘量採用分佈式的結構,類似MVC模式;

努力從程序上解決根本問題。

附:轉載

WebSphere應用服務器內存洩漏探測與診斷工具

級別: 中級 李 學朝 (lixuec@cn.ibm.com), 高級軟件工程師,IBM中國軟件開發中心

2006 年 11 月 21 日

本文介紹了如何在WebSphere應用服務器中實現應用程序內存洩漏的探測,並且針對IBM所提供的系列分析與診斷工具,給出了具體的配置步驟和使用最佳實踐。
引言

內存洩漏是比較常見的一種應用程序性能問題,一旦發生,則系統的可用內存和性能持續下降;最終將導致內存不足(OutOfMemory),系統徹底宕掉,不能響應任何請求,其危害相當嚴重。同時,Java堆(Heap)中大量的對象以及對象間之複雜關係,導致內存洩漏問題的探測和分析均比較困難,採用相應的輔助工具是很必要的。

WebSphere應用服務器提供了系列針對內存問題的探測和分析診斷工具,這些工具可以幫助用戶進行內存問題的及時探測,保證系統在發生OOM之前,用戶可以在無須進行複雜分析的條件下,預知在其部署的應用中是否存在內存洩漏的問題。如果確有內存洩漏現象發生, WebSphere還提供了相應的工具,可以幫助用戶進行分析診斷,從而找到內存洩漏的真正原因。

1. 內存洩漏探測和診斷步驟

實踐中,我們可以採用以下的步驟來處理內存洩漏的問題:

(1) 首先,在WebSphere中我們啟用實時探測內存洩漏工具, WebSphere性能診斷顧問會對內存洩漏提前發出警告信息。

(2) 啟用WebSphere自帶的Tivoli性能查看器監視系統的JVM使用狀況,確定內存洩漏是否正在發生。

(3) 根據需要,生成詳細內存回收日誌,使用PMAT工具分析並確定洩漏的時間,週期等。

(4) 生成單個或者多個Heapdump文件,選用MDD4J進行分析診斷,找到內存洩漏的真正原因。

(5) 提交開發部門進行代碼修復,然後重新部署到WebSphere應用服務器。

接下來的部分,我們針對每個環節的配置和工具使用進行闡述。

2.WebSphere應用服務器中內存洩漏的探測工具

2.1 性能診斷顧問介紹

性能診斷顧問(Performance and Diagnostic Advisor),在WebSphere應用服務器6.0.2版本之前稱為運行時性能顧問(Runtime Performance Advisor)。該工具可以週期性的檢查WebSphere的設置,並給出調整的推薦值。自WebSphere應用服務器6.0.2版本開始,該工具實現了一種輕量級的內存探測機制,可以非常容易的幫助用戶探測是否在系統中存在內存洩漏問題,並提前通過日誌和管理控制台進行通知。這樣就給用戶以足夠的時間採取必要的措施防止系統宕掉,同時可以收集或生成相關的文件以進行離線的分析,來查找洩漏的根本原因。

2.2配置

可以在WebSphere應用服務器的管理控制台中啟用性能診斷顧問

(1) 訪問管理控制台 ->服務器-> 應用程序服務器。

(2) 選擇所要配置的服務器。

(3) 在性能區域,選擇性能和診斷顧問程序配置。

(4) 如圖所示,有兩個Tab, 運行時和配置。區別在於,運行時裡面的內容無須重啟服務器就可以生效,但下次重啟服務器的時候,這些配置也會丟失。配置Tab裡面的內容只有在服務器重啟後才生效,而且配置的內容也會一直存在,除非再次登陸並去掉所選項。

(5)在其他屬性區域,點擊性能和診斷建議配置,確保內存洩漏規則處於運行狀態(綠色箭頭)。

2.3 查看洩漏警告信息

WebSphere性能診斷顧問輸出信息可以顯示在WebSphere的管理控制台,並記錄在WebSphere應用服務器的SystemOut.log日誌文件裡面。

(1) SystemOut.log日誌

[8/31/06 13:21:43:545 CST] 00000010 TraceResponse W TUNE9001W: Heap
utilization patterns indicate that you may have a memory leak
Additional explanatory data follows.
Data values for free memory between 8/31/06 1:20 PM and 8/31/06 1:21 PM were
consistently below minimum required percentage.

(2) 管理控制台

-登陸管理控制台->故障診斷 ->運行時消息 ->點擊運行時警告

3. Java 虛擬機概要分析和詳細垃圾回收

進一步檢測是否有內存洩漏的發生,以及洩漏發生的時間,週期和速度,我們可以啟用Java虛擬機中的詳細垃圾回收,然後分析相應的日誌。 WebSphere應用服務器6.1使用了Java SDK5.0, 在Window, Linux, AIX, i5/OS,z/Linux 和z/OS上使用了IBM的JAVA虛擬機, 在Solaris和HP-UX上使用Sun的JVM。Java 虛擬機概要分析工具接口(Java Virtual Machine Tool Interface,JVMTI)支持從運行應用程序服務器的 Java 虛擬機(JVM)收集信息(如,關於垃圾回收的數據、對象利用和線程狀態)並且支持更全面的性能分析。一旦啟用了 JVMTI,可以使用 PMI 定製選項來啟用所選統計信息以收集特定數據。

3.1啟用 Java 虛擬機概要分析和詳細垃圾回收配置步驟

配置步驟:

1. 在控制台導航樹中單擊服務器 > 應用程序服務器

2. 單擊選擇所需應用程序服務器。

3. 在"服務器基礎結構"下,單擊 Java 和進程管理-> 進程定義。

4. 在"其他屬性"下,單擊 Java 虛擬機。

5. 選中配置Tab的詳細垃圾回收選項。

6. 在通用 JVM 參數字段中輸入 -agentlib:pmiJvmtiProfiler。

注: WebSphere6.1中,JVM概要分析接口改為Java Virtual Machine Tool Interface (JVMTI)。之前版本是JVMPI。如果需要JVMPI的時候,也可以此處輸入-XrunpmiJvmpiProfiler。另外,啟用JVMTI接口對性能影響較大,儘量避免在生產環境中使用。

7.點擊應用或者確定。

8. 單擊保存按鈕。

9.重啟WebSphere應用服務器。

3.2 GC數據分析工具PMAT

在WebSphere 應用服務器的日誌目錄下,native_stderr.log文件就是我們需要的內存回收分析文件。我們推薦使用IBM Pattern Modeling and Analysis Tool for Java Garbage Collector 工具,簡稱PMAT。 PMAT工具解析JAVA SDK的詳細內存回收(GC)日誌,並提供統計信息,圖表,分析並推薦Java堆配置。PMAT提供了豐富的圖形界面來顯示Java堆的使用狀況,從而更輕鬆地判斷是否有內存問題發生。該工具可以從IBM的alphaWorks網站下載,只有英文版。

我們可以把GC文件從服務器上下載到PMAT所在機器,然後根據WebSphere的平台選擇打開相應的GC文件進行分析。下面是一個GC日誌片斷,手動分析是比較費勁,而且需要深入瞭解JVM相關知識。

PMAT在分析GC日誌後,給出一個總結。下圖為例,我們可以看出GC對系統性能的影響,以及完成的垃圾回收次數等,並且我們可以看出工具給出的推薦(Recommendations)顯示系統的Java堆使用情況是持續增加的。

進一步,我們可以查看GC的詳情,點擊Analysis菜單,然後選擇Graph View All,我們就可以根據需要選擇所要查看的曲線。如圖所示,紅色曲線代表已使用內存,藍色曲線代表每次垃圾回收後可用的內存。已使用內存逐漸增加,可用內存的持續降低表明系統可能存在內存洩漏。

4. TPV監視JVM的狀況

另外一種方法是借助TPV和PMI來實時監視JVM,分析性能曲線來判斷是否有內存洩漏的狀況發生。 WebSphere性能監控基礎結構(PMI)和Java虛擬機概要分析工具接口(JVMTI)可以幫助我們收集系統的性能狀況數據,使用Tivoli性能查看器(TPV)以圖形的方式顯示這些數據(性能計數器),可以進一步證實是否系統正在發生內存洩漏。

4.1 PMI與TPV

PMI 提供WebSphere運行時和應用程序資源行為的一組全面的數據,。例如,PMI 提供數據庫連接池大小、servlet 響應時間、 Enterprise JavaBeans(EJB)方法響應時間、Java 虛擬機(JVM)垃圾回收時間以及 CPU 使用量等等。使用 PMI 數據,可以識別並修正應用程序服務器中的性能瓶頸, 還可使用 PMI 數據來監控應用程序服務器的運行狀況。PMI 數據可以由 Tivoli Performance Viewer(TPV)、其他 Tivoli 工具、您自己的應用程序或第三方工具來監控和分析。TPV 是隨 WebSphere Application Server 一起提供的 PMI 數據圖形查看器。

Tivoli Performance Viewer(TPV)使得我們可以通過查看圖表或表格,從而解讀WebSphere的性能監控基礎結構(PMI)數據。

4.2 PMI的配置方法

默認情況下,PMI已經開啟,級別是默認(Default)。配置步驟:

1. 在控制台導航樹中單擊監視&調整-> 性能監視基礎結構(PMI)。

2. 選擇所要配置的服務器名字。

3.單擊配置選項卡,這裡可以根據監控內容的需要,來選擇PMI的任一種統計信息集(無,基本,擴展,全部,定製)。我們這裡選擇"定製"。

註:如果在配置選項卡中,則當重新啟動服務器時應用設置。如果在運行時選項卡中,則立即應用設置。

4.點擊定製 -> 在定製監視級別的樹中,選擇配置選項卡,然後點開JVM運行時,可以根據需要,啟用或禁用相應的計數器。

5.保存並重啟WebSphere服務器。

4.3 TPV的使用方法

實時查看 TPV 性能模塊的步驟:

(1) 在控制台導航樹中,單擊監控和調整 -> 性能查看器 -> 當前活動 -> 服務器名字)-> 性能模塊。

(2) 選中要查看的每個性能模塊,例如JVM運行時。

(3) 單擊查看模塊按鈕。 在頁面的右側會顯示所選性能數據的圖形或切換成表格。註:每個模塊有與其關聯的多個計數器。這些計數器會顯示在數據圖形或表格下面的表中。您可以通過選擇或取消選擇計數器旁的複選框,將計數器添加到圖表或表中,或從中除去。

TPV顯示的已使用內存的圖形理想情況下應該是鋸齒狀,圖形中每個坡(下降)對應著一次內存的垃圾回收(Garbage collection),如下圖已使用內存的曲線,顯示的是沒有發生內存洩漏的狀況。

如果測試過程中出現如下情況,則有可能發生了內存洩漏:

-每次垃圾回收後的已使用內存的數值驟增。

-TPV對應的已使用內存圖形更接近於階梯(staircase),或者鋸齒形狀嚴重不規則。

-也可以查看分配的對象數與釋放的對象數之差值,如果這個數值越來越大,則有內存洩漏(如果需要查看對象數,需要啟用JVMTI接口並在PMI中啟用相應的JVM計數器)。

上圖,紅色曲線代表已使用的內存,從整體趨勢,我們可以看出已使用內存一直在增長。 TPV可以幫助發現內存洩漏,為了得到最優結果,我們可以重複試驗,而且每次可以增加測試的時間,例如測試1000,3000或5000個頁面請求。

5. 生成Heap dump文件

WAS6.1 中,在使用IBM JDK的平台上,可以直接使用以下的方法,隨時生成所需的heapdump文件。如果在性能診斷顧問程序配置裡面選中了"啟用自動堆轉儲收集,則可以自動在WebSphere profile所在的路徑下(例如/opt/IBM/WebSphere/WAS6.1/profiles/AppSrv01)生成heapdump文件,備用戶進行分析。

在使用IBM SDK的平台上,例如AIX, Linux和Windows,在啟用了性能診斷顧問工具後,如果探測到有內存洩漏發生,WebSphere會自動生成兩個heapdump文件,供後續分析使用。

我們在任何時候,可以隨時手動生成所需的heap dump文件。在WAS6.1 profile的bin目錄下,首先運行wsadmin 腳本客戶端,然後可以調用generateHeapDump操作來完成。

關鍵步驟:

1. 找到JVM對象名字。

set objectName
WebSphere:type=JVM,process=,node=<節點名字>,*]
2. 對JVM MBean調用generateHeapDump操作。

$AdminControl invoke $objectName generateHeapDump
例如:

[root@csspvm bin]# pwd
/opt/IBM/WebSphere/WAS6.1/profiles/AppSrv01/bin
[root@csspvm bin]# ./wsadmin.sh -username root -password demo4you
WASX7209I: Connected to process "server1" on node csspvmNode02 using SOAP
connector; The type of process is: UnManagedProcess
WASX8011W: AdminTask object is not available.
WASX7029I: For help, enter: "$Help help"
wsadmin>set objectName [$AdminControl queryNames
WebSphere:type=JVM,process=server1, node=csspvmNode02,*]
WebSphere:name=JVM,process=server1,platform=proxy,node=csspvmNode02,
j2eeType=JVM,J2EEServer=server1,
version=6.1.0.0,type=JVM,mbeanIdentifier=JVM,cell=csspvmNode02Cell,spec=1.0
wsadmin>$AdminControl invoke $ objectName generateHeapDump
/opt/IBM/WebSphere/WAS6.1/profiles/AppSrv01/./heapdump.20060904.075650.3576.phd
wsadmin>quit


理想情況下,在探測到問題時,盡快生成一個初始的heap dump,然後密切監控內存使用情況,等到洩漏了足夠的內存的時候,再生成另外一個heap dump,這樣可以對比分析以更準確地找到洩漏的原因。

註: 生成HeapDump文件的過程是比較耗資源的,所以請只在必須的時候做這樣的操作。

6內存洩漏的分析診斷工具-MDD4J

一旦確定了系統中有內存洩漏,並且為此生成了heap dump。接下來,我們可以把這些文件從WebSphere應用服務器轉移到離線的分析工具所在的機器,進行離線分析診斷。

6.1 工具介紹

MDD4J (Memory Dump Diagnostic for Java)是一個內存洩漏分析工具,用於對運行 WebSphere Application Server 的虛擬機(JVM)所生成的常用內存轉儲(堆轉儲)格式進行分析。進行內存轉儲(Memory dump)分析的目的,是為了確定 Java 堆中真正導致內存洩漏的類和包(classes and packages),這樣可以縮小內存洩漏的範圍並找到真正的原因,此分析還確定應用程序 Java 堆佔用量的主要組成部分以及它們之間的擁有關係。

此工具支持下列格式的內存轉儲格式有:

-IBM 的PHD格式(heapdump.phd)

-IBM 文本堆轉儲(heapdump.txt)

-HPROF 堆轉儲格式(hprof.txt,主要針對Solaris和HP-UX平台)

-SVC 轉儲(dump.bin,IBM z-Series上的WebSphere)

該工具提供了兩種分析機制:單轉儲分析以及對兩個轉儲進行的比較分析。

單轉儲分析最常用於在發生 OutOfMemoryException 時自動觸發的內存轉儲。此類分析查找可疑的數據結構,能夠相對快速地提供可疑洩漏對象的分析結果。

比較分析用於對運行內存洩漏應用程序期間(即可用 Java 堆內存流失時)獲取的兩個內存轉儲進行分析。在運行洩漏應用程序的早期觸發的內存轉儲被稱為基線內存轉儲,發生洩漏的應用程序運行一段時間(以允許洩漏程度加大)後觸發的內存轉儲被稱為主內存轉儲。在發生了內存洩漏的情況下,主內存轉儲可能包含大量對象,而這些對象佔用的 Java 堆空間量會比基線內存轉儲大很多。

為了獲得更好的分析結果,建議使主內存轉儲的觸發點與基線內存轉儲的觸發點在時間上拉開一定距離,從而使總耗用堆大小在兩個觸發點之間大幅增長。

MDD4J的分析結果顯示是基於WEB界面的,具有下列特徵:

- 列示分析結果、堆內容、大小和增長幅度的總結

- 列示可疑的數據結構、數據類型和包,它們是造成堆使用量增加(對於比較分析)和堆大小較大(對於單轉儲分析)的主要原因。

- 擁有關係上下文視圖顯示了佔用量主要組成部分之間的關係,以及一組彙總的主要佔用量組成部分所包含的重要數據類型。

- 在堆轉儲內容的交互式樹形視圖中,瀏覽功能能夠顯示堆中任何對象的所有進入引用(在樹中只顯示一個引用,其餘引用單獨顯示)和外出引用,而子對象按到達大小排序。

- 導航功能使您能夠從可疑對象列表轉到所有關係上下文,以及從內容視圖轉到瀏覽視圖。

- 提供了內存轉儲中所有對象和數據類型的表視圖,視圖中具有過濾器和經過排序的列。

6.2工具的使用

WebSphere 應用服務器v6.1的附帶光盤裡面有IBM Support Assistant工具的安裝文件,運行相應的安裝文件,MDD4J作為插件同時被安裝了。

另外,也可以從IBM 技術支持站點http://www-306.ibm.com/software/support/isa/ 下載Support Assistant工具,然後選擇更新程序,獨立安裝MDD4J插件。

啟動步驟:

(1) 程序->IBM Support Assitant ->IBM Support Assistant v3

(2) 在Support Assistant窗口中,選擇工具 -> 選擇WebSphere版本號。

點擊MDD4J的鏈接,就可以開啟MDD4J工具。在該界面中,我們可以提交單個heap dump文件進行單轉儲分析,或同時提交兩個文件進行比較分析。也可以從內存轉儲分析結果的下拉選項中選擇以前的分析結果,從而查看以前的分析內容。

查看分析進度

單擊"上載並分析"按鈕後,MDD4J開始分析heap dump文件。在分析執行過程中,登錄頁面將自動刷新,以反映當前正在執行的分析步驟以及整體分析進度。如果該頁面由於某種原因而不刷新,您可以單擊"刷新"按鈕以瞭解當前分析狀態。如果您希望停止分析,可以單擊"停止"按鈕,這將在當前正在執行的模塊完成後終止分析。

在提交了heap dump文件,MDD4J顯示分析狀態。

查看分析結果

分析完成後,Mdd4J頁面將重定向到"分析結果"頁面。"分析結果"頁面包含 4 個選項卡:

"分析總結"選項卡:顯示分析結果總結,並列示下一組用於查看分析結果的步驟。

"可疑對象"選項卡:它顯示四類可疑對象,即對增長幅度影響最大的數據結構、到達大小顯著流失的數據結構、有大量實例的對象類型以及有大量對象實例的 Java 包。

"察看上下文和內容"選項卡:顯示主內存轉儲中 Java 堆佔用量的主要組成部分的擁有關係上下文圖,以及圖中所選節點的內容。

"瀏覽"選項卡:根據對對象引用圖執行的深度優先遍歷,用樹形視圖顯示主內存轉儲的所有內容。

其他內容,請參照MDD4J工具附帶的Help文檔,該幫助文檔有詳細的使用說明,在此不再贅述。

7.小結

IBM 提供了一系列的工具輔助用戶進行內存問題的監控和分析,在合適的階段選擇合理的工具可以幫助我們輕鬆搞定內存洩漏。這裡介紹的工具都是WebSphere 附帶或者免費的,IBM Tivoli工具還提供了更強大的監控和診斷功能,例如ITCAM (IBM Tivoli Composite Application Management),可以根據實際情況選用。

2008/5/30

log4j 配置詳解

log4j 配置詳解 - [log4j]

版權聲明:轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明
http://huahuazhu.blogbus.com/logs/20920245.html

log4j配置文件有三個主要的組件:Logger,Appender和Layout,分別為日誌類型,日誌輸出目的地,日誌輸出格式。
log4j.rootLogger = [level], appenderName, appenderName, ... (level是錯誤級別,appenderName是輸出目的地,本例設為mylog,可以定義多個)
level優先級分別為FATAL、ERROR、WARN、INFO、DEBUG 5個級別.通過定義的級別,你可以控制程序中的日誌輸出.比如在這裡定義了ERROR級別,程序中只有FARAL、ERROR 級別的LOG會被輸出.
log4j.appender.mylog= 輸出目的地 (這裡的appenderName是在前面定義的,可任意起名)
Log4j提供的輸出目的地有以下幾種:
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天產生一個日誌文件)
org.apache.log4j.RollingFileAppender(文件到達指定大小時產生一個新文件)
org.apache.log4j.WriterAppender(將日誌信息以流格式發送到任何地方)

log4j.appender.filelog.File=your file dir
log4j.appender.filelog.MaxFileSize=your filesize
log4j.appender.mylog.MaxBackupIndex=num設置保存備份文件數量

log4j.appender.appenderName.layout = 佈局類型(設置佈局類型)
Log4j提供的layout有以下4種:
org.apache.log4j.HTMLLayout(以HTML表格形式佈局)
org.apache.log4j.SimpleLayout(包含日誌信息的級別和信息字符串)
org.apache.log4j.TTCCLayout(包含日誌產生的時間、線程、類別等等信息)
org.apache.log4j.PatternLayout(可以靈活地指定佈局模式)
如果使用PatternLayout佈局就要指定的打印信息的具體格式ConversionPattern,打印參數如下:
%m 輸出代碼中指定的消息
%p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL
%r 輸出自應用啟動到輸出該log信息耗費的毫秒數
%c 輸出所屬的類目,通常就是所在類的全名
%t 輸出產生該日誌事件的線程名
%n 輸出一個回車換行符,Windows為"rn",Unix為"n"
%d 輸出日誌時間,比如:%d{yyyy MMM dd HH:mm:ss,SSS},輸出:2007年5月17日 19:30:00,000
%l 輸出日誌事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數
[QC]是log信息的開頭,可以為任意字符,一般為項目簡稱

程序中並沒有直接用到log4j的類,而是使用了commons-logging提供的日誌類。commons-logging是為"所有的Java日誌實現"提供一個統一的接口,它的功能據說「平常弱」。
Log (基本記錄器)和LogFactory(負責創建Log實例)。當commons-logging.jar被加入到CLASSPATH之後,它會合理地猜 測你喜歡的日誌工具,然後進行自我設置,用戶根本不需要做任何設置。默認的LogFactory是按照下列的步驟去發現並決定那個日誌工具將被使用的(按 照順序,尋找過程會在找到第一個工具時中止):
1.尋找當前factory中名叫org.apache.commons.logging.Log配置屬性的值
2.尋找系統中屬性中名叫org.apache.commons.logging.Log的值
3.如果應用程序的classpath中有log4j,則使用相關的包裝(wrapper)類(Log4JLogger)
4.如果應用程序運行在jdk1.4的系統中,使用相關的包裝類(Jdk14Logger)
5.使用簡易日誌包裝類(SimpleLog)

java Out Of Memory

版權聲明:轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明
http://big360.blogbus.com/logs/17205480.html

來自:BlogJava-首頁技術區 作者: tacy lee 發表時間:昨天22:38:00

某項目,年前開始報OOM,頻率保持在一月一次,發生OOM的時候,heap free size還有7~800M,比較奇怪,年後系統上集群,系統發生OOM的頻率開始變得頻繁,基本在4-5天,由於用的是sun jdk 1.4.2_08,無法獲取到heap dump,建議用戶升級到1.4.2_14(該版本以後sun添加了HeapDumpOnOutOfMemoryError參數,便於獲取dump幫助診 斷該類問題),4天之後,我們獲取到了heapdump文件,通過對dump的分析,基本上排除了對象洩漏。

根據環境(64bit Solaris + 32bit JDK),客戶把Heap最大設置為2G,開始懷疑32bit JDK無法分配這麼大的Heap,經過驗證,不存在這樣的問題(sun網站也有相關說明,在solaris 64bit系統上,32bit jdk最大可以設置到4G)

但是從dump看到application classes loader大小已經到了60M以上,有點懷疑Perm區設置太小導致,查了一下sun的文檔,Perm區缺省大小為64M,估計是應用加載太多classes導致Perm區溢出,

我們也簡單模擬了一下Perm溢出,強制設置max perm大小為32M,並對GC進行了監控,結果和我們預想的一致,看下面的gc log:

151.836: [Full GC 151.836: [Tenured: 25735K->25736K(1048576K), 0.8380858 secs] 25911K->25736K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8382804 secs]
152.676: [Full GC 152.676: [Tenured: 25736K->25722K(1048576K), 0.8464782 secs] 25752K->25722K(1557568K), [Perm : 32767K->32766K(32768K)], 0.8466638 secs]
153.525: [Full GC 153.525: [Tenured: 25722K->25724K(1048576K), 0.8419056 secs] 25738K->25724K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8420986 secs]
154.368: [Full GC 154.368: [Tenured: 25724K->25724K(1048576K), 0.8398816 secs] 25724K->25724K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8400498 secs]
155.212: [Full GC 155.212: [Tenured: 25724K->25725K(1048576K), 0.8365448 secs] 25788K->25725K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8367370 secs]
156.050: [Full GC 156.050: [Tenured: 25725K->25722K(1048576K), 0.8422488 secs] 25725K->25722K(1557568K), [Perm : 32767K->32766K(32768K)], 0.8424328 secs]
156.895: [Full GC 156.895: [Tenured: 25722K->25724K(1048576K), 0.8443532 secs] 25738K->25724K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8445450 secs]
157.740: [Full GC 157.741: [Tenured: 25724K->25724K(1048576K), 0.8427754 secs] 25740K->25724K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8429634 secs]
158.587: [Full GC 158.588: [Tenured: 25724K->25726K(1048576K), 0.8352290 secs] 25820K->25726K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8354212 secs]
159.424: [Full GC 159.424: [Tenured: 25726K->25723K(1048576K), 0.8435336 secs] 25726K->25723K(1557568K), [Perm : 32767K->32766K(32768K)], 0.8437092 secs]
160.270: [Full GC 160.270: [Tenured: 25723K->25725K(1048576K), 0.8477722 secs] 25739K->25725K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8479596 secs]
161.119: [Full GC 161.119: [Tenured: 25725K->25725K(1048576K), 0.8543338 secs] 25725K->25725K(1557568K), [Perm : 32767K->32767K(32768K)], 0.8545040 secs

從日誌看,和我們現場的狀況非常相似,heap空間充足,但是perm已經到了32M,無法再進一步分配 空間,直接導致jvm頻繁做Full GC,控制台也開始拋出OOM(Perm引起的回收都是full gc),這樣看基本我們判斷是Perm太小,導致無法加載classes導致的

和客戶溝通之後,我們本來打算進一步驗證(在生產環節打 開PrintGCDetail,獲取詳細的GC log),後面仔細檢查nohup.out,發現裡面已經拋出了 OutOfMemoryError:PermGen Space,至此我們確定是Perm設置不合理導致了本次事故,和客戶確認之後,我們在啟動參數中加上了MaxPermSize

後面想到中間上了集群之後,eos加載了大量的jboss cache class,這也直接解釋了為什麼這段時間OOM出現的頻率比之前更頻繁的原因

這裡總結一下,希望對碰到類似問題的tx有借鑑意義,強烈建議用sun jdk 1.4.2的同學升級到>=1.4.2_12,便於對OOM問題的診斷,並加上GC log協助驗證。

這裡再介紹一下JVM發生OOM的幾種情況:

1、java.lang.OutOfMemoryError: Java heap space

這是我們平常理解的OOM,是由於heap space確實沒有空間分配,這種一般是由於內存洩漏導致,也有可能是heap space設置太小。需要具體分析

2、java.lang.OutOfMemoryError: PermGen space

jvm 規範裡面有定義一個method space,這裡主要放classes和method list和一個string pool,string有一個intern方法,通過這個方法定義的string都放在這裡(好像不常用),這裡設置不太小會導致OOM,缺省64M,主 要由於現在應用依賴的第三方類越來越多,導致這類問題頻繁發生,需要引起重視

3、Requested array size exceeds VM limit
這種是由於申請的array size超出了heap space大小,比如在一個256M的heap space中申請一個512M的array,這種基本都是應用bug導致

4、request bytes for . Out of swap space?
這種是由於heap size設置相對於系統物理內存太大,導致系統swap space不足,這種的解決辦法就是減小heap size大小

5、 (Native method)
這種估計是最麻煩的了,也是最少碰到的,是由於jni或native method導致,如果自己沒有寫這類的東西,基本可以說是jdk問題

手機QQ禁用NFC

一圖解千言萬語 應用程式權限:透過NFC起動