home ホーム search 検索 -  login ログイン  | help ヘルプ

find 検索

141 - 150 / 1320    [|<]  [|<]  [<]  11  12  13  14  15  16  17  18  19  20   [>]  [>|][>|]
タイトル/名前 更新者 更新日
Java/SPI(Service Provider Interface) msakamoto-sf 2014-12-23 13:04:06
Java/文字コードメモ5, Stringコンストラクタの内部実装, ISO-8859-1とUS-ASCIIの違い, CoderResultのパフォーマンス問題 msakamoto-sf 2014-11-30 21:46:58
日記/2014/11/30/OWASP Day(2014-11-29)関連リンク msakamoto-sf 2014-11-30 18:22:19
Java/DB操作調査メモ(JPA 2.0, JDBI, Connection Pool, 2-way SQL) msakamoto-sf 2014-11-16 22:08:48
技術/運用管理/Vagrant/Vagrantfile書き方メモ msakamoto-sf 2014-11-16 20:58:04
Java/Profile/EclipseでのProfilerツール, 2014-09時点 msakamoto-sf 2014-09-22 22:33:23
技術/Linux/CentOS/CentOS6系でのyum-cronによるパッケージ自動更新 msakamoto-sf 2014-09-22 20:41:44
技術/Linux/CentOS/CentOS6でのcron, anacron msakamoto-sf 2014-09-22 19:58:51
技術/Linux/CentOS/日本語サポート, 日本語入力のインストール msakamoto-sf 2014-09-16 00:00:02
Java/文字コードメモ4 msakamoto-sf 2014-09-15 20:56:07
ソート項目 / ソート順     1ページ 件ずつ表示

Java/SPI(Service Provider Interface)  

所有者: msakamoto-sf    作成日: 2014-11-24 21:04:19
カテゴリ: Java 

Javaではライブラリはjarで配布される場合が多い。その中でもインターフェイスと実装をjar単位で分離して、サードパーティによる実装の拡張が容易になるような仕組みが"SPI"(Service Provider Interface)と呼ばれており、JDK5までは "sun.misc.Service" という非公開クラスとメソッドだったのが、JDK6以降は "java.util.ServiceLoader" クラスとして公開され、利用できるようになった。

SPIの良い例がJDBCの処理で、インターフェイスは定義しておき、それを実装するライブラリを、DBMSごとに用意する。プログラマはSPI経由でJDBCインターフェイスを取得すれば、実際のどのDBMSの実装クラスが使われたのかを意識せずに、すべて同じインターフェイス(クラス名・メソッド名)でDB接続を操作できる。なおアプリを配布する際は、使用するDBMSのJDBC用jarファイルも一緒に配布する。

簡単なユースケースを以下のAntプロジェクトで試してみた:

仕組みとしては、実装側のjarファイルの "META-INF/services/" の下に、実装したいインターフェイスのクラス名でファイルを作成し、その中に実装ファイルのクラスを一行一個で記載する。
今回のサンプルでは、FooProviderが "spidemo.cloud.spi.Cloud" と "spidemo.search.spi.Search" の2つのインターフェイスの実装を提供するため、"META-INF/services/"に以下の2ファイルを配置している。
FooProvider/src/META-INF/services/spidemo.cloud.spi.Cloud:

spidemo.cloud.FooCloud

FooProvider/src/META-INF/services/spidemo.search.spi.Search:

spidemo.search.FooSearch

また、BarProviderでは "spidemo.search.spi.Search" に対して2つの実装クラスを提供するため、 以下のように2行にして2つのクラス名を記述している。
BarProvider/src/META-INF/services/spidemo.search.spi.Search:

spidemo.search.BarSearch
spidemo.search.BarSearch2

mainクラスはDemoAppに配置しているが、DemoAppそれ自身でもCloudとSearchの両インターフェイスを実装して、自分自身の実装をロードできるか確認する。
DemoApp/src/META-INF/services/spidemo.cloud.spi.Cloud:

spidemo.cloud.MyCloud

DemoApp/src/META-INF/services/spidemo.search.spi.Search:

spidemo.search.MySearch

実行時の出力(解説付き):

# CloudService インターフェイスの実装としてFooProvider, BazProviderの2つを用意した。
# また、DemoApp自身が "My Cloud Provider" という名前の実装を含んでいる。
# getProviderName()とgetServiceNames()をprintしている。
Provider Name: My Cloud Provider
My Container
My Tomcat
Provider Name: Foo Cloud Provider
Foo VPC
Foo VPN
Foo Shared Server
Foo Dedicated Server
Provider Name: Baz Cloud Provider
Baz Xen Computing
Baz Security Gateway
Baz Shared Storage

# SearchService インターフェイスの実装としてFooProvider, BarProviderの2つを用意した。
# (なお、FooProviderはCloudとSearchの2つとも実装している)
# また、DemoApp自身が "My Cloud Provider" という名前の実装を含んでいる。
Provider Name: My Search Provider
My Search 1
My Search 2Provider Name: Foo Search Provider
Foo Search 1
Foo Search 2
Foo Search 3
## BarProviderでは、Search SPIに対して2つの実装を定義している。
Provider Name: Bar Search Provider
Bar Search 1
Bar Search 2
Bar Search 3
Provider Name: Bar Search2 Provider
Bar2 Search 1
Bar2 Search 2
Bar2 Search 3

参考:

日本語資料:



プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2014-12-23 13:04:06
md5:a6308ba4ce6736f369a65d52ed0cac48
sha1:452bf8c0a96c93ef6a90314c0c4184f3238370cf

Java/文字コードメモ5, Stringコンストラクタの内部実装, ISO-8859-1とUS-ASCIIの違い, CoderResultのパフォーマンス問題  

所有者: msakamoto-sf    作成日: 2014-11-30 21:38:10
カテゴリ: Java 

Java/文字コードメモ4 に続いたメモ5.

Stringクラスで文字列を保持している実体は何か? → char[]

Oracle JDK 7(jdk7u25)のJDKソースを確認してみる。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

→Stringクラスのコンストラクタは、いずれも最終的にvalueというchar配列に値を設定してる。

参考:

byte[]からStringを生成するコンストラクタは何をしているのか?

"String(byte[], int, int, Charset)"のコンストラクタから追ってみる。
JDK7u25のソースを参考にしている。

    public String(byte bytes[], int offset, int length, Charset charset) {
        // (...)
        this.value =  StringCoding.decode(charset, bytes, offset, length);
    }

StringCodingはpackage privateスコープのクラスのため、未公開。JDKのソースで確認する。細かいエラー処理とかは思い切って省略すると以下の流れになっている。

    static char[] decode(Charset cs, byte[] ba, int off, int len) {
        // Charset#newDecoder()から、CharsetDecoderインスタンスを取得
        CharsetDecoder cd = cs.newDecoder();
        // 1バイト辺りの最大文字数とlenより、最大の文字数を計算
        int en = scale(len, cd.maxCharsPerByte());
        // 最大の文字数でchar配列を作成
        char[] ca = new char[en];

        // CharsetDecoderの準備
        cd.onMalformedInput(CodingErrorAction.REPLACE)
          .onUnmappableCharacter(CodingErrorAction.REPLACE)
          .reset();

        if (cd instanceof ArrayDecoder) {
            // CharsetDecoderがsun.nio.cs.ArrayDecoderの派生クラスならそのままdecode()メソッドを呼ぶ。

            int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
            return safeTrim(ca, clen, cs, isTrusted);

        } else {
            // sun.nio.cs.ArrayDecoderの派生クラスでなければ、
            // ByteBufferとCharBufferにラップしてdecode()メソッドを呼ぶ。

            ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
            CharBuffer cb = CharBuffer.wrap(ca);
            try {
                CoderResult cr = cd.decode(bb, cb, true);
                if (!cr.isUnderflow())
                    cr.throwException();
                cr = cd.flush(cb);
                if (!cr.isUnderflow())
                    cr.throwException();
            } catch (CharacterCodingException x) {
                // Substitution is always enabled,
                // so this shouldn't happen
                throw new Error(x);
            }
            return safeTrim(ca, cb.position(), cs, isTrusted);
        }
    }

CharsetDecoderの実装については後述するが、JDKで提供されているものについては "sun.nio.cs" パッケージ以下で実装されている。
インターフェイスとしては java.nio.charset.CharsetDecoder abstract class として公開されている。

Java 7u6 で行われたString.substring()に関するチューニングとは?

それまでのJavaでは、String.substring()の結果は、元のStringインスタンスの"char[] value"をそのまま参照し、beginとendだけを変更したインスタンスを返していた。
その場合、巨大なテキストデータから文字列を切り出す処理を考えると、元のテキストデータが不要になっても、切りだされたStringインスタンスが巨大な"char[] value"を参照しつづけ、GCで回収されない。
これによるメモリリークが問題視されたらしく、Java 7u6 では、元の"char[] value"から必要な範囲だけをコピーして新規に作成する形式に変更された。これにより、不要になった元の巨大なテキストデータが適切にGCで回収されるようになる。

参考:

実際にJDKのソースを確認してみる。

JDK6のString.substring()の流れを確認する:
http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/String.java/?v=source

    public String substring(int beginIndex, int endIndex) {
        // (...)
        return ((beginIndex == 0) && (endIndex == count)) ? this :
            new String(offset + beginIndex, endIndex - beginIndex, value);
    }

→ String(int, int, char[]) のコンストラクタで生成したのを返している。このコンストラクタは以下のようにpackage privateとなっており、外部には公開されていない。

    String(int offset, int count, char value[]) {
        this.value = value;
        this.offset = offset;
        this.count = count;
    }

このコンストラクタでは、確かに、元の"char[] value"をそのまま引き継ぎ、offsetとcountだけを更新している。このため、元のStringが巨大なテキストデータだった場合、その"char[] value"で本来は使われない領域が参照され続ける。
これにより、元の巨大なテキストデータが不要になっても、substring()されたインスタンスの方で参照が残っているため、不要なデータがGCに回収されない。(substring()された新しいStringインスタンスが不要になってようやくGC対象になる。)

一方、JDK 7u40 のソースを確認してみる。
http://grepcode.com/file_/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/String.java/?v=source

    public String substring(int beginIndex, int endIndex) {
        // (...)
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

→JDK6とは異なり、String(char[], int, int)のコンストラクタを呼んでいる。

    public String(char value[], int offset, int count) {
        // (...)
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

新しく配列をコピーして作ったのを、"this.value"に設定している。

new String(byte bytes[], int offset, int length)はどうやってCharsetを決定しているのか?

JDK7の場合:

  1. Javaのシステムプロパティ:"file.encoding" で指定された名前をデフォルトのCharsetとして使ってみる。
  2. ↑で無効なCharset名だったら、ISO-8859-1を仮定して使ってみる。

Oracle JDK 7(jdk7u25)のJDKソースを確認してみる。
java.lang.Stringのコンストラクタ:

    public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }

→ StringCodingはpackageスコープのクラスのため、未公開。JDKのソースを確認する。

java.lang.StringCoding:

class StringCoding {

    // (...)

    static char[] decode(byte[] ba, int off, int len) {
        String csn = Charset.defaultCharset().name();
        try {
            // use charset name decode() variant which provides caching.
            return decode(csn, ba, off, len);
        } catch (UnsupportedEncodingException x) {
            warnUnsupportedCharset(csn);
        }
        try {
            return decode("ISO-8859-1", ba, off, len);
        } catch (UnsupportedEncodingException x) {
            // If this code is hit during VM initialization, MessageUtils is
            // the only way we will be able to get any kind of error message.
            MessageUtils.err("ISO-8859-1 charset not available: "
                             + x.toString());
            // If we can not find ISO-8859-1 (a required encoding) then things
            // are seriously wrong with the installation.
            System.exit(1);
            return null;
        }
    }

→最初にCharset.defaultCharset()でCharset名を取得し、StringCoding.decode()でデコードを試みてる。それに失敗したら、"ISO-8859-1"でデコードできないか試してみて、ソレでも駄目ならISO-8859-1でエラーになるというのはシステムレベルでおかしいので、JVMを終了(System.exit(1))してる。

Charset.defaultCharset()はどこからCharset名を取り出してるのか?これも、Charset.defaultCharset()の実装をJDKのソースで確認する。

    public static Charset defaultCharset() {
        if (defaultCharset == null) {
            synchronized (Charset.class) {
                String csn = AccessController.doPrivileged(
                    new GetPropertyAction("file.encoding"));
                Charset cs = lookup(csn);
                if (cs != null)
                    defaultCharset = cs;
                else
                    defaultCharset = forName("UTF-8");
            }
        }
        return defaultCharset;
    }

→ "file.encoding" システムプロパティから取得している。"file.encoding"の値がおかしかったら、"UTF-8"を試してる。

"ISO-8859-1"と、"US-ASCII"は何が違うのか?

US-ASCIIは7bitの範囲の文字までしかマッピングしていないことから、US-ASCIIはISO-8859-1のサブセットと考えることができる。

Charsetの実装コードはどこにあるのか?

OpenJDK7だと、sun.nio.cs パッケージ以下にあるぽい。

java.nio.charset.CoderResult クラスでのスレッド間ロックについての再考

Java/文字コードメモ4 で軽く触れた、"java.nio.charset.CoderResult" について再考する。

java.nio.charset.CoderReusltクラスは、java.nio.charset.CharsetDecoder#decode() や java.nio.charset.CharsetEncoder#encode() などの処理結果を表現するクラスになっている。
byte配列をdecodeする、あるいはUnicode文字の配列をbyte配列にencodeする処理はどうしても状態遷移が伴う処理であり、入力バッファ・出力バッファの長さや中途半端なデータ、対応していないデータなど様々な異常処理が発生し得る。
そのため、CharsetDecoder/CharsetEncoderの実装は、内部でCoderResultに適切な異常状態の詳細を設定して、呼び出し元に返す仕組みになっている。
http://docs.oracle.com/javase/jp/7/api/java/nio/charset/CoderResult.html

「長さが中途半端」なパターンが頻用されるのか、専用のstatic factoryが用意されている。

  • CoderResult#malformedForLength(int length) : 指定された長さの不正入力エラーを表した一意のオブジェクトを返す
  • CoderResult#unmappableForLength(int length) : 指定された長さのマップ不可文字エラーを表した一意のオブジェクトを返す

このstatic factoryが、内部で length に対応するCoderResultのインスタンスをstaticにキャッシュしている。これが CoderResultクラスに対するsynchronizedブロックでスレッドセーフティを確保している。
つまりこれが、マルチスレッド(正確にはClassLoaderに対してとなるが、システムクラスなので事実上システム全体)間でのロックにつながるsynchronizedブロックになる。

以下が上記2つのstatic factoryのJDK7u25におけるソース。

    public static CoderResult malformedForLength(int length) {
        return malformedCache.get(length);
    }
    public static CoderResult unmappableForLength(int length) {
        return unmappableCache.get(length);
    }

"malformedCache", "unmappableCache"ともにCoderResultのstaticメンバ。

    private static Cache malformedCache
        = new Cache() {
                public CoderResult create(int len) {
                    return new CoderResult(CR_MALFORMED, len);
                }};

    private static Cache unmappableCache
        = new Cache() {
                public CoderResult create(int len) {
                    return new CoderResult(CR_UNMAPPABLE, len);
                }};

"Cache"はCoderResultクラス内のインナークラスとして宣言されており、"create(int len)"をabstractとしている。


    private static abstract class Cache {

        private Map<Integer,WeakReference<CoderResult>> cache = null;

        protected abstract CoderResult create(int len);

        private synchronized CoderResult get(int len) {
            if (len <= 0)
                throw new IllegalArgumentException("Non-positive length");
            Integer k = new Integer(len);
            WeakReference<CoderResult> w;
            CoderResult e = null;
            if (cache == null) {
                cache = new HashMap<Integer,WeakReference<CoderResult>>();
            } else if ((w = cache.get(k)) != null) {
                e = w.get();
            }
            if (e == null) {
                e = create(len);
                cache.put(k, new WeakReference<CoderResult>(e));
            }
            return e;
        }

    }

これにより、CR_MALFORMED/CR_UNMAPPABLEにそれぞれ対応する、長さ毎のCoderResultインスタンスをstaticかつスレッドセーフにキャッシュしている。

確かにクラスのstaticメンバに対するsynchronizedなのでマルチスレッド間でグローバルにロックされてしまう。しかし、これがチューニングレベルで影響してしまうのはどのような時か?

まず、これらのstatic factoryは長さが不正であったり文字とのマッピングに失敗している状態を表している。つまり、異常処理で呼ばれるのを意図している。
したがって、大抵の時間が正常処理に費やされる一般的なシステムであれば、これらのstatic factoryが呼ばれることはほとんど無いと考えられ、チューニングレベルで影響することも無いと考えられる。

チューニングに影響するレベルとしては、システムが想定している文字コードとは異なるデータを大量に扱う状態が考えられる。
ただその場合、当然decode/encodeが正常に終了していないため、結果として文字化けなどが大量発生してすぐに異常に気づくだろう。
あるいはそもそもどんな文字コードがくるか分からず、アスキー範囲だけを文字として扱いたい場合に、UTF-8などdecode/encodeで状態遷移が必要なCharsetを使ってしまっているケースが考えられる。
バイナリデータを無理やり、アスキー範囲だけでも文字として扱う際に、UTF-8を使ってStringにすると、UTF-8に従わないbyte[]部分でunmappableが発生する可能性がある。
つまり定常的に文字コード処理の異常が発生している状態であり、そのようなユースケースだと体感レベルでパフォーマンスに影響してしまうかもしれない。

解決策としては、システムの特性によっていくつか考えられる。

  • バイナリデータを無理やり、アスキー範囲だけでも文字として扱いたい場合
    • UTF-8などではなく、ISO-8859-1を使う。特にISO-8859-1のCharsetDecoder実装(byte[] -> char[]変換)では、CoderResult.malformedForLength()/unmappableForLength()が一切呼ばれない。
  • 諸事情で文字コードを変更できない場合
    • 対応策不明。
    • 原理的にはCoderResultのクラスを改変する他ない。
      • システムクラスに属してしまうため、ClassLoader#loadClass()でゴニョゴニョする難易度が半端ない。
      • agentの仕組みを使って、CoderResultクラスのロードが発生するタイミングで、synchronized cacheでない実装に改変した独自のCoderResultに挿げ替える仕組みは出来るかもしれないが、システム全体への影響が発生してしまうため、影響度が大きい。
    • CoderResult.malformedForLength()/unmappableForLength()を呼ばない、独自のCharsetProviderを実装するのはアリかもしれない・・・。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-11-30 21:46:58
md5:fcc9a8bb01737230f32f89f0b7105422
sha1:ec2c065a00d273aecc3c31e1a32212a73c6a0734

日記/2014/11/30/OWASP Day(2014-11-29)関連リンク  

所有者: msakamoto-sf    作成日: 2014-11-30 18:21:09
カテゴリ: セキュリティ 

2014-11-29 開催のOWASP Dayで紹介されていたURLやスライド資料のリンクのメモ。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-11-30 18:22:19
md5:78e67c4eb9b13cfc9d05458b1220f1f3
sha1:0a3afc8a0a59f04d72748aa2b7e413e05d9a6207

Java/DB操作調査メモ(JPA 2.0, JDBI, Connection Pool, 2-way SQL)  

所有者: msakamoto-sf    作成日: 2014-11-16 22:07:38
カテゴリ: Java 

参考資料リンク集

Java Persistence API (JPA) 2.0以降

JPA入門

JPQLのパフォーマンス

JDBI

アノテーションにSQLを記述してコード量を減らせる、独特なライブラリ。

Connection Pool

Apache Commons DBCP : バージョン2系が出てる。

Tomcat JDBC Pool

2-way SQL



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-11-16 22:08:48
md5:a147b15b4eb71297ae757386ef022c8f
sha1:0065a6efc175e843cb4d9bfe8dfd2cd4448164b1

技術/運用管理/Vagrant/Vagrantfile書き方メモ  

所有者: msakamoto-sf    作成日: 2014-11-16 20:57:38
カテゴリ: DevOps VMware Vagrant VirtualBox 

CPUやメモリをカスタマイズしたい

ネットワーク設定について

  1. Vagrantでのネットワーク設定はどう抽象化されているか確認。"private"と"public"の二種類がある。
    1. http://docs.vagrantup.com/v2/networking/index.html
    2. "public"はおおよそ、いわゆる「Bridge接続」に相当するらしい。
    3. "private"が、Providerごとにズレがあるらしい。
  2. VirtualBoxでの"private"ネットワークについて。デフォルトはHostOnlyだが、内部ネットワークも利用できる。
    1. http://docs.vagrantup.com/v2/virtualbox/networking.html
    2. https://www.virtualbox.org/manual/ch06.html

1つのVagrantfileで複数のVMを設定して、しかもお互いに通信できるようにする

参考:

ポイント:

  • "config.vm.define" で複数の仮想マシンを定義できる。
  • 仮想マシン間で通信したい場合は、":private_network" を使う。静的IPアドレス設定など。
    • VirtualBox Providerの場合、":private_network"だとHostOnly networkとなる。
      • これはゲストOS間 + ホストOS間の通信が可能になり、ただし外には出れない。
      • ただし、VirtualBox Providerの場合はNATインターフェイスは残してくれてるので、外部へはそちらを使って通信するようになる。
    • 記事によっては "virtualbox__intnet:" を使え、というのもある。ただコレ指定すると、ホストからゲストに直接接続できなかった記憶があるので、NAT側でport forward設定する必要があるかも?

Vagrantfileの例1:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # All Vagrant configuration is done here. The most common configuration
  # options are documented and commented below. For a complete reference,
  # please see the online documentation at vagrantup.com.

  # 共通して使うBOX名を書いておく。
  config.vm.box = "hashicorp/precise64"

  config.vm.define "web" do |node|
    node.vm.hostname = "web"
    # お互いに通信できるよう、VirtualBox でのHostOnly networkを使う。
    node.vm.network :private_network, ip: "192.168.56.51"
  end

  config.vm.define "db" do |node|
    node.vm.hostname = "db"
    # お互いに通信できるよう、VirtualBox でのHostOnly networkを使う。
    node.vm.network :private_network, ip: "192.168.56.52"
  end

end

→ "vagrant ssh web", "vagrant ssh db" でSSH接続できる。

Vagrantfileの例2:

VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "web" do |node|
    # それぞれでBOX名を指定
    node.vm.box = "hashicorp/precise64"
    node.vm.hostname = "web"
    node.vm.network :private_network, ip: "192.168.56.51"
  end

  config.vm.define "db" do |node|
    # それぞれでBOX名を指定
    node.vm.box = "hashicorp/precise64"
    node.vm.hostname = "db"
    node.vm.network :private_network, ip: "192.168.56.52"
  end
end


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-11-16 20:58:04
md5:ef6eda7c9c12280fd49bd504d63c5a57
sha1:4e4a71dd0def12a3fc9363eafab8e23adfadb7ea

Java/Profile/EclipseでのProfilerツール, 2014-09時点  

所有者: msakamoto-sf    作成日: 2014-09-22 22:32:59
カテゴリ: Eclipse Java 

Eclipse上でのJavaプロファイリングツールについてですが、オープンソースや有償製品がいくつかあります。

2014-09時点でのメジャープロファイリングツール

OSS, 無償製品

有償製品

参考:

Helios(3.6)までサポートしていたEclipse TPTP

EclipseのHelios(3.6)までは Eclipse Test & Performance Tools Platform Project がEclipse本体が開発しているプロファイリングツールとして有力でした。

しかし、Eclipse TPTPは2010~2011年頃に開発が停止したため、Indigo(3.7)以降はTPTPは使えません。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-09-22 22:33:23
md5:f63be8bd82f580491e3708549cb5f14d
sha1:96d6304a61298c8264ea78442464d8619a1efc6d

技術/Linux/CentOS/CentOS6系でのyum-cronによるパッケージ自動更新  

所有者: msakamoto-sf    作成日: 2014-09-22 20:41:17
カテゴリ: Linux 

CentOS6系では、yum-cronを使うとパッケージ更新の自動チェック/DL/アップデートを簡単に行える。

インストール:(依存パッケージは yum-plugin-downloadonly)

# yum install yum-cron

構成:

# rpm -ql yum-cron
/etc/cron.daily/0yum.cron
/etc/rc.d/init.d/yum-cron
/etc/sysconfig/yum-cron
/etc/yum/yum-daily.yum
/etc/yum/yum-weekly.yum
/usr/share/doc/yum-cron-3.2.29
/usr/share/doc/yum-cron-3.2.29/COPYING
/usr/share/man/man8/yum-cron.8.gz

技術/Linux/CentOS/CentOS6でのcron, anacron でも紹介しているが、CentOS6系の最新だと、"/etc/cron.daily" 以下は cron ではなく anacron により実行される。

起動:yum-cronはcronジョブであるが、serviceとして起動しておく必要がある。serviceとして起動するとロックファイルが作成され、yum-cronのジョブはそれを見て実際の処理を開始する。

# service yum-cron start
Enabling nightly yum update:                               [  OK  ]
# chkconfig yum-cron on
# chkconfig --list | grep yum-cron
yum-cron        0:off   1:off   2:on    3:on    4:on    5:on    6:off

設定:
/etc/sysconfig/yum-cron の、以下の3項目がメイン。

# Don't install, just check (valid: yes|no)
CHECK_ONLY=no

# Check to see if you can reach the repos before updating (valid: yes|no)
CHECK_FIRST=no

# Don't install, just check and download (valid: yes|no)
# Implies CHECK_ONLY=yes (gotta check first to see what to download)
DOWNLOAD_ONLY=no

上記はデフォルト値で、CHECK_ONLY も DOWNLOAD_ONLY も no なので、自動的にチェック&インストールまで実施される。

DOWNLOAD_ONLY=yesにしておくと、以下のようなメールが届く。

題名:Anacron job 'cron.daily' on (ホスト名)

本文:
/etc/cron.daily/0yum.cron:

New updates available for host (ホスト名)

audit.x86_64                           2.2-4.el6_5                       updates
...
Updates downloaded, use "yum -C update" manually to install them.

"yum -C update" を行うと、プロンプト付きでの更新になる。

# yum -C update
Loaded plugins: downloadonly, fastestmirror, presto
Setting up Update Process
Resolving Dependencies
--> Running transaction check
(...)
 shared-mime-info                         x86_64                 0.70-4.el6                                   base                    209 k

Transaction Summary
============================================================================================================================================
Install       7 Package(s)
Upgrade      89 Package(s)

Total size: 103 M
Is this ok [y/N]: N

"yum -C -y update" で自動的に行員をインストールする。

# yum -C -y update
(...)

Installed:
  kernel.x86_64 0:2.6.32-431.29.2.el6

(...)
Complete!

更新前:

# uname -a
Linux ip-10-120-73-205 2.6.32-358.6.2.el6.x86_64 #1 SMP Thu May 16 20:59:36 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

更新→再起動後:更新に成功している。

# uname -a
Linux ip-10-120-73-205 2.6.32-431.29.2.el6.x86_64 #1 SMP Tue Sep 9 21:36:05 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

除外パッケージや対象パッケージの絞り込みは出来るか?

  • 除外パッケージについては、"/etc/yum.conf" の "exclude" で設定できるようだ。
  • 対象パッケージの絞り込みについては不明。

参考リンク:



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-09-22 20:41:44
md5:d2347b0d52123c28d5dd5f610c56b0ff
sha1:47a901022858b7a0292efaea3be8b7915bb6d723

技術/Linux/CentOS/CentOS6でのcron, anacron  

所有者: msakamoto-sf    作成日: 2014-09-22 19:58:20
カテゴリ: Linux 

以前、ローカルでCentOS 6.3をDVDイメージからセットアプしたときは気づかなかったが、最近AWSのEC2で、Marketplace提供のCentOS 6.4 or 6.5のAMIを使ってみたら気づいた。

cronとanacronの違い

cron
指定された時間と間隔でジョブを実行する。分単位で指定できる。マシンが起動している間のみ、ジョブを実行する。
anacron
指定された日数間隔でジョブを実行する。マシンが停止していたら、その間の日数を計算してジョブを実行する。

実行形態

  • cron : デーモンとして常時起動している。
  • anacron : anacron自体は常時起動せず、cronからcron.hourlyなどで定期的に起動される。

cronとanacronの違いの例として、毎日 03:00 に実行するジョブをcronとanacronとでそれぞれ登録してみる。anacronは毎時5分に "/etc/cron.hourly" ディレクトリ以下のスクリプトにより、cronから実行される。

/etc/crontab

0 3 * * * root /foo/bar/job.sh

/etc/anacrontab

...
# anacronの場合は、ぴったり何時に実行ではなく、実行する時間帯を指定。3時-5時に設定。
START_HOURS_RANGE=3-5
#period in days   delay in minutes   job-identifier   command
1                 5                  foo.job          /foo/bar/job2.sh

メンテナンスのため00:00 - 04:00 までそのマシンが停止するケースだと、以下のような動きになる。

00:00 - マシンシャットダウン

03:00 - シャットダウン中なので、cronもanacronも実行されない。

04:00 - マシン起動

04:05 - cron.hourlyによりanacronが実行される。
        → START_HOURS_RANGE内なので、"foo.job"の前回起動した日時を
        /var/spool/anacron/(job-identifier) ファイルから読み取り、
        "period in days" 経過していれば実行する。

このように、cronではジョブ実行時間帯にマシンが停止していればそのジョブは実行されない。
anacronであれば、日数間隔で大雑把にはなるが、マシンが起動したあとの最初のanacron実行時に、停止している間に実行されるべきだったジョブを実行できる。

最新 CentOS 6 での cron, anacron パッケージ状況

cron が、vixie-cron から Fedoraプロジェクトでforkされた cronie というパッケージに変更されている。

CentOS 6.4 AWS Marketplace AMI (yum update後):

# rpm -qa | grep cron
cronie-1.4.4-12.el6.x86_64
crontabs-1.10-33.el6.noarch
cronie-anacron-1.4.4-12.el6.x86_64

cronie, crontabsパッケージ

crondデーモン本体を cronie が、スケルトンの crontab ファイル・ディレクトリを crontabsパッケージが提供している。

# rpm -ql cronie
/etc/cron.d/0hourly
/etc/cron.deny
/etc/pam.d/crond
/etc/rc.d/init.d/crond
/etc/sysconfig/crond
/usr/bin/crontab
/usr/sbin/crond
...
/var/spool/cron

/etc/cron.d/0hourly:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
01 * * * * root run-parts /etc/cron.hourly

crontabsパッケージの内容:

# rpm -ql crontabs
/etc/cron.daily
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly
/etc/crontab
/usr/bin/run-parts
/usr/share/man/man4/crontabs.4.gz

/etc/crontab:

# more /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed

cronie-anacronパッケージ

anacronの実行ファイルと、デフォルトの、cron.hourlyでanacronを実行するためのcron設定ファイルが cronie-anacronパッケージでインストールされる。

# rpm -ql cronie-anacron
/etc/anacrontab
/etc/cron.hourly/0anacron
/usr/sbin/anacron
/usr/share/man/man5/anacrontab.5.gz
/usr/share/man/man8/anacron.8.gz
/var/spool/anacron
/var/spool/anacron/cron.daily
/var/spool/anacron/cron.monthly
/var/spool/anacron/cron.weekly

/etc/anacrontab:

# more /etc/anacrontab
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7      25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45    cron.monthly            nice run-parts /etc/cron.monthly

デフォルトでは START_HOURS_RANGE が 3時~22時と非常に広いレンジになっている。
考え方としては、CentOSをインストールしたのが 3時~22時の間であればその間のcron.hourlyにより、最初のanacronジョブが実行される。
23時以降も cron.hourly で起動されるが、START_HOURS_RANGE外なのでジョブは実行されない。
3時になって cron.hourly によりanacronが実行されると、START_HOURS_RANGE内に入ったので、ジョブが実行される。
そのさい、"delay in minutes" で遅延した後に、さらにRANDOM_DELAYで指定した分数の間、ランダムの分で遅延してジョブが実行される。

CentOS 6 での cron, anacron 実行順序の整理

整理すると、以下のように事実上、anacronが "/etc/cron.daily", "/etc/cron.weekly", "/etc/cron.monthly" を実行している。

/etc/crontab : 空っぽ
/etc/cron.d/
    0hourly : 毎時1分に "/etc/cron.hourly" 以下を実行
/etc/cron.hourly/
    0anacron : anacron 実行

→ crond自身は上記まで、つまり "/etc/cron.d/0hourly" 経由で "/etc/cron.hourly/" までがcrondの範囲。
"/etc/cron.(daily|weekly|monthly)" は、以下のようにanacron経由で実行される。
/etc/anacrontab:

...
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7      25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45    cron.monthly            nice run-parts /etc/cron.monthly

CentOS5時代のcrondのみによる制御に戻すには

cronie-noanacronをインストールして、代わりにcronie-anacronを削除すれば良いらしい。

yum install cronie-noanacron
yum remove cronie-anacron

参考リンク



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-09-22 19:58:51
md5:cfb9e77deac265ce91694013c0172a83
sha1:1f78e4f3dce2922483e622d50ead4fcb9f1913dc

技術/Linux/CentOS/日本語サポート, 日本語入力のインストール  

所有者: msakamoto-sf    作成日: 2014-09-15 23:57:39
カテゴリ: Linux 

Minimal Desktop でインストールすると日本語入力が入らない。

基本的な流れとしては "Japanese Support" を groupinstall する。IBusも入るので、設定画面からAnty選択。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-09-16 00:00:02
md5:87f9b753b7987a4b5b60b735e0714ef3
sha1:57bba9f5d9d03a3cc28a6857ab791d5c0848f48a

Java/文字コードメモ4  

所有者: msakamoto-sf    作成日: 2014-09-15 20:15:26
カテゴリ: Java 

Java/文字コードメモ3 に続いたメモ4.

Javaでバイナリデータを文字列として処理する、つまり、バイナリデータ中のASCII文字だけでindexOf()や正規表現が動けば良い場合、byte配列をどのエンコーディングでStringにするのが適切か?

個人的にはISO-8859-1が、0x00 - 0xFFまでひと通り1バイト=1文字でマッピングがされているため、一番安全な解に思える。
重要なのが制御文字や0x80 - 0xFFまでに1バイト=1文字でマッピングされている点。これが無いと、0x80-0xFFのバイト配列→文字列→バイト配列→文字列、と何回か変形した場合に、元に戻らない。

サンプルコード:

参考:

トピックその2:String型とbyte配列の変換って、スレッドセーフか?
基本的に大丈夫だと思うが・・・

なんか、ブロッキングでパフォーマンスが~とかいう話が2006年ごろからまれにあるっぽい。



プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2014-09-15 20:56:07
md5:00621369e4094a23e915826e1529bf93
sha1:e8e34365026eb14ac39efe8716002d803e6f2e46