Memo/Java

https://dexlab.net:443/pukiwiki/index.php?Memo/Java
 

MenuBar

Java


JMX: モニタリング

wget http://crawler.archive.org/cmdline-jmxclient/cmdline-jmxclient-0.10.3.jar
timeout 5 java -jar cmdline-jmxclient-0.10.3.jar - localhost:8000 | head -n 5

Windows向けバッチファイル

  • example.jar を起動する例
    @echo off
    IF EXIST "C:/Program Files/Java/jre8/bin/java.exe" (GOTO JRE8_64)
    IF EXIST "C:/Program Files (x86)/Java/jre8/bin/java.exe" (GOTO JRE8_32)
    IF EXIST "C:/Program Files/Java/jre7/bin/java.exe" (GOTO JRE7_64)
    IF EXIST "C:/Program Files (x86)/Java/jre7/bin/java.exe" (GOTO JRE7_32)
    
    GOTO NOTFOUND
    
    :JRE8_64
    set JAVA_PATH="C:/Program Files/Java/jre8/bin/"
    GOTO EXEC
    
    :JRE8_32
    set JAVA_PATH="C:/Program Files (x86)/Java/jre8/bin/"
    GOTO EXEC
    
    :JRE7_64
    set JAVA_PATH="C:/Program Files/Java/jre7/bin/"
    GOTO EXEC
    
    :JRE7_32
    set JAVA_PATH="C:/Program Files (x86)/Java/jre7/bin/"
    GOTO EXEC
    
    :NOTFOUND
    echo Java Not Found
    set JAVA_PATH=
    GOTO EXEC
    
    :EXEC
    %JAVA_PATH%java -version
    %JAVA_PATH%java -jar example.jar
    
    :END

JVMはDNS解決するとIPアドレスをキャッシュする

JVMのデフォルトでは起動時にDNS解決したIPアドレスを無期限(-1)で使う。 これはAWS ELB等動的にIPアドレスが変わるサービスではトラブルの原因となるため、DNSキャッシュしないか、短めの値を使った方が良い

  • "-1"は無期限(デフォルト)、"0"はキャッシュしない
  • networkaddress.cache.ttl=60
  • sun.net.inetaddr.ttl=0
  • sun.net.inetaddr.negative.ttl=0
grep networkaddress.cache.ttl /usr/java/jdk1.8.0_20/jre/lib/security/java.security
#networkaddress.cache.ttl=-1

メモリーダンプを取得する

  • 実行ユーザで取得すると詳細が取れる。サイズが大きいので注意
    pgrep -u <USER NAME> java
    2222
    
    # または $JAVA_HOME/bin/jps -v | grep [PROCESS_NAME]
    
    $JAVA_HOME/bin/jmap -dump:file=/tmp/memorydump.$(date +%Y%m%d).map 2222
    gzip /tmp/memorydump.*.map

スレッドダンプ/ヒープダンプを取得する

ログにも出ないようなエラーが発生した時に便利。

  • スレッドダンプの取得。実行ユーザで取得すると詳細が取れる
    pgrep -u <USER NAME> java
    2222
    
    # または $JAVA_HOME/bin/jps -v | grep [PROCESS_NAME]
    
    $JAVA_HOME/bin/jstack -F 2222 | gzip > /tmp/threaddump.$(date +%Y%m%d).log.gz
    • kill -3 [PID] だと、catalina.out に出る
  • ヒープダンプの取得(ヒープサイズによっては数十分程度時間がかかる)
    $JAVA_HOME/bin/jmap -F -dump:format=b,file=heapdump.map 2222 | gzip > /tmp/heapdump.$(date +%Y%m%d).log.gz

jps:javaプロセスだけ表示

  • CentOSの場合、jdk-1.6.0, java-1.6.0-openjdk-develパッケージに入っていた
    # プロセスID, 実行クラス名
    $JAVA_HOME/bin/jps
    
    # 実行クラス名が完全修飾名(FQCN)で表示
    $JAVA_HOME/bin/jps -l
    
    # 詳細情報
    $JAVA_HOME/bin/jps -v

入門


Apache Maven

  • wikipedia Apache_Maven
    cd /tmp/
    wget http://ftp.riken.jp/net/apache/maven/maven-3/3.0.4/binaries/apache-maven-3.0.4-bin.tar.gz
    tar xvfz apache-maven-3.0.4-bin.tar.gz
    sudo mv apache-maven-3.0.4 /usr/share/
    sudo ln -s /usr/share/apache-maven-3.0.4 /usr/share/maven
    
    sudo vim /etc/profile.d/maven.sh
    ----
    export M2_HOME=/usr/share/maven
    export M2=$M2_HOME/bin
    export PATH=$M2:$PATH
    ----
    source /etc/profile.d/maven.sh

複数バージョンをalternativesで切り替えて使う

CentOS5.x, 6.xをインストールする時にjavaパッケージをインストールすると、デフォルトのjavaとして"gcj"がインストールされる。
他のバージョンのjavaを簡単に切り替えて使うための設定をする

# 追加。複数ファイルで構成されている場合は--slaveオプションも付ける
# --install [シンボリックリンク名] [グループ名] [バイナリ本体] [優先度] \
#   --slave [シンボリックリンク名] [グループ名] [バイナリ本体]
# ※優先度は大きいほど高い
alternatives --install /usr/bin/java java /usr/java/jdk1.6.0_31/bin/java 16031 \
  --slave /usr/bin/jar java-jar /usr/java/jdk1.6.0_31/bin/jar \
  --slave /usr/bin/javac java-javac /usr/java/jdk1.6.0_31/bin/javac \
  --slave /usr/bin/javadoc java-javadoc /usr/java/jdk1.6.0_31/bin/javadoc \
  --slave /usr/bin/javaws java-javaws /usr/java/jdk1.6.0_31/bin/javaws \
  --slave /usr/bin/jcontrol java-jcontrol /usr/java/jdk1.6.0_31/bin/jcontrol

# 手動選択
alternatives --config java
# 自動選択
alternatives --set java /usr/java/jdk1.6.0_31/bin/java

# 削除
# --remove [グループ名] [削除したいバイナリ本体]
alternatives --remove java /usr/java/jdk1.6.0_31/bin/java

# 現在の設定
alternatives --display java
java - ステータスは手動です。
リンクは現在 /usr/java/jdk1.6.0_31/bin/java を指しています。
/usr/java/jdk1.6.0_31/bin/java - 優先項目 30
現在の「最適」バージョンは /usr/java/jdk1.6.0_31/bin/java です。

# 設定情報
ls -l /etc/alternatives/

バージョン確認

  • java
    java -version
    
    # 複数のjavaがインストールされている場合
    alternatives --display java
  • tomcat
    ps aux | grep -o -P 'tomcat-\d\.\d' | sort | uniq -c
  • tomcatのバージョン
    /opt/tomcat-8.0/bin/version.sh  | grep -i "jvm version"
    JVM Version:    1.8.0_66-b17

md5を文字列として取得

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

String md5( String str ) throws NoSuchAlgorithmException
{
	MessageDigest md = MessageDigest.getInstance("MD5");
	byte[] dat = str.getBytes();
	md.update(dat);//dat配列からダイジェストを計算する
	byte[] digest = md.digest();

	StringBuilder sb = new StringBuilder();
	for (int i = 0; i < digest.length; i++) {
		sb.append(String.format("%02x", 0xff & digest[i]));
	}
	return sb.toString();
}

System.out.printf("md5: %s\n", md5("1234567890")); // => md5: e807f1fcf82d132f9bb018ca6738a19f

配列内を検索する

  • http://commons.apache.org/lang/ から commons-lang3-3.0.1-bin.zip をダウンロードし、適当なフォルダに展開
  • プロジェクトを右クリック > ビルド・パス > ビルド・パスの構成 > ライブラリタブ > 外部Jarの追加で指定
import org.apache.commons.lang3.*;

String[] string = {"A", "B", "C"};

System.out.println(ArrayUtils.indexOf(string, "A")); // => 0
System.out.println(ArrayUtils.indexOf(string, "X")); // => -1

配列のコピー

デフォルトでは参照扱いなので、配列のコピーをしようと思っても参照コピーになる
1次元配列と多次元配列では結果が異なる

  • ディープコピー(値渡し)
    Arrays.copyOf(src, src.length);
    Arrays.copyOfRange(src, from, to);
    System.arraycopy(src, src_pos, dst, dst_pos, len);
  • シャローコピー(参照渡し)
    Object.clone() // 1次元:ディープコピー、多次元:シャローコピー
  • 2次元配列のコピー
    • 失敗
      String[][] a = {
      		{ "a", "b", "c"},
      		{ "d", "e", "f"},
      	};
      
      String[][] b = a;
      a[0][0]="g";
      System.out.printf("%s\n", b[0][0]); // => "g"
    • 単純なループ
      String[][] a = {
      		{ "a", "b", "c"},
      		{ "d", "e", "f"},
      	};
      
      String[][] b = new String[2][3];
      for(int i=0; i<2; i++){
      	for(int j=0; j<3; j++){
      		b[i][j] = a[i][j];
      	}
      }
      a[0][0]="g";
      System.out.printf("%s\n", b[0][0]); // => "a"
    • Arrays.copyOf()を使う
      import java.util.Arrays;
      
      String[][] a = {
      		{ "a", "b", "c"},
      		{ "d", "e", "f"},
      	};
      
      String[][] b = new String[2][]; // b=Arrays.copyOf(a, a.length); だとシャローコピーになって失敗
      for(int i=0; i<2; i++){
      	b[i] = Arrays.copyOf(a[i], 3);
      }
      a[0][0]="g";
      System.out.printf("%s\n", b[0][0]); // => "a"

変数のダンプ

  • 変数
    String str="test";
    System.out.printf("%s\n", str); // test
  • 多次元配列 (JDK 1.5)
    import java.util.Arrays;
    
    int[][] matrix = { {0,1,2}, {3,4,5}, {6,7,8} };
    System.out.println(Arrays.deepToString(matrix)); // [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

キュー構造

  • Queue java 1.5.0以降
    import java.util.LinkedList;
    import java.util.Queue;
    
    Queue<String> q = new LinkedList<String>();
    q.offer("1");
    q.offer("2");
    
    System.out.println(q.poll()); //=> 1
    System.out.println(q.poll()); //=> 2

スタック構造

  • Stack java 1.5.0 以降
    import java.util.Stack;
    
    Stack<String> st = new Stack<String>();
    st.push("var");
    st.push("foo");
    
    System.out.println(st.pop()); //=> foo

ソースの文字コード

  • ソースファイルの文字コード指定
    javac -encoding UTF-8 Hello.java
  • 実行時のコード指定
    java -Dfile.encoding=UTF-8 Hello
  • UTF-8,UTF8
  • Shift_JIS,SJIS
  • Windows-31J,MS932 : SJIS+Windows拡張文字
  • ISO-2022-JP,ISO2022JP
  • EUC-JP,EUC_JP

空きメモリ量を得る

Runtime.getRuntime().freeMemory()
Runtime.getRuntime().totalMemory()

プリプロセッサを使う

デバック時だけ有効にしたいコード等を使用する事ができる。

  • Cコンパイラのプリプロセッサ機能のみを使う方法 [#v0555ad8]
    • コマンドラインのBorland C++Compiler 5.5が無償提供されているので、その中のcpp32.exeを使う。出力は 「.i」ファイルとなる。
    • Visual Studio の「cl.exe /P」を使う。.CPPしか入力できないので、.javaを.cppにリネームする
    • 参考リンク
  • その他
  • http://denchu.jp/java/
    • JavaDoc?形式(/** 〜 */)のコメント時エラー、__LINE__が展開されない不具合あり。パッチ作成し、作者に報告済み。
    • DoJa?用ビルドスクリプト
      fileDoJa_build_bat.zip
    • パッチ適用後の「JavaPP」「ビルドスクリプト」をパスの通った場所にコピー
    • DoJa?でメニューの設定 -> ビルドの設定で以下のようにする
      • ビルド前スクリプト
        set PATH=C:\WINDOWS\SYSTEM32\;C:\java\j2sdk1.4.2_08\bin;
        JavaPP_start.bat
      • ビルド後スクリプト
        set PATH=C:\WINDOWS\SYSTEM32\;C:\java\j2sdk1.4.2_08\bin;
        JavaPP_end.bat
    • ビルド実行するだけ。ただし、コンパイルに失敗するとソースが元に戻らないので注意が必要。

チェックサム

  • 1byte
    	/**
    	* チェックサム
    	*
    	* @note
    	* - 1byte チェックサム
    	* - 順序エラーは検出できない
    	*/
    	public String checksum(String str)
    	{
    		int sum = 0;
    		byte[] bytes = null;
    		try{
    			bytes = str.getBytes("SJIS");
    		}catch(Exception ex){
    		}
    		for(int i=0; i < bytes.length; i++){
    			sum += bytes[i];
    			sum &= 0xFF;
    		}
    		String s = Integer.toHexString(sum);
    		if(s.length() < 2) s = "0" + s;
    		
    		return s;
    	}

簡単な暗号化

  • rot13
    	/**
    	* rot13
    	*
    	* @note
    	* - シーザー暗号で 13 文字ずらして、かつ大文字小文字を保存する方法を rot13 という。\n
    	* 例えば "a" だったら 13 文字ずらすと "n"、"N" は "A" になる。\n
    	* alphabet は 26 文字なので、rot13 暗号化を 2 回繰り返せば、元に戻る。
    	* - 'a'〜'z'、'A' 〜 'Z'が暗号化される。
    	*/
    	public String rot13(String str)
    	{
    		String buf = null;
    		byte[] bytes = null;
    		try{
    			bytes = str.getBytes("SJIS");
    		}catch(Exception ex){
    		}
    		for(int i=0; i < bytes.length; i++){
    			int c = bytes[i];
    			if ( c < 'A' ){
    			}else if (c <= 'M'){
    				c = (c + 13);
    			}else if (c <= 'Z'){
    				c = (c - 13);
    			}else if (c < 'a'){
    			}else if (c <= 'm'){
    				c = (c + 13);
    			}else if (c <= 'z') {
    				c = (c - 13);
    			}
    			bytes[i] = (byte)c;
    		}
    		try{
    			buf = new String(bytes, "SJIS");
    		}catch(Exception ex){
    		}
    		return buf;
    	}
  • rot47
    	/**
    	* rot47
    	*
    	* @note
    	* - シーザー暗号で 47 文字ずらす。
    	* - 半角英数字が暗号化される。
    	* - 全角文字はそのまま
    	* - 2回関数を呼ぶと平文に戻る
    	*/
    	public String rot47(String str)
    	{
    		String buf = null;
    		byte[] bytes = null;
    		try{
    			bytes = str.getBytes("SJIS");
    		}catch(Exception ex){
    		}
    		for(int i=0; i < bytes.length; i++){
    			int c = bytes[i];
    			if ( c < '!' ){
    			}else if ( c <= 'O' ){
    				c =  (c + 47);
    			}else if ( c <= '~' ){
    				c = (c - 47);
    			}
    			bytes[i] = (byte)c;
    		}
    		try{
    			buf = new String(bytes, "SJIS");
    		}catch(Exception ex){
    		}
    		return buf;
    	}

16進数ダンプ

「sun.misc.HexDumpEncoder?」がある。

byte[] bytes = new byte[100];
for ( int i=0; i<bytes.length; i++ ) bytes[i] = (byte)i;

HexDumpEncoder encoder = new HexDumpEncoder();
System.out.println( encoder.encodeBuffer(bytes) );

try {
    encoder.encodeBuffer( bytes, System.out );
} catch ( IOException ioex ) {}

byte型配列への変換サポート

int a = 1000;
byte b[];
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(out);
dout.writeInt(a); // 変数aの内容を書き出す
b = out.toByteArray(); // 書き出した結果のbyte配列を取得
dout.close();
out.close();

負荷テストツールJMeter


添付ファイル: fileJavaPP200a_patch.lzh 1017件 [詳細] fileJavaPP2.0a_plus.zip 1676件 [詳細] fileDoJa_build_bat.zip 1631件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-09-15 (土) 07:31:37 (35d)