EatSmartシステム部ブログ

ウェブサイトの開発や運営に関する情報です。

JAVAのマーカーインターフェースとアノテーション

非キャッシュの仕組み

弊社のシステムはJAVA + strutsで実装されている所が多いのですが、サイト上のページはアクセスの負荷に耐えられるように、WEBサーバーやAPPサーバーから、キャッシュされた情報を返すようにシステムを構築しています。
ただ、ページによっては毎回Actionを実行して、リアルタイムなデータを表示する必要があります。そのために、Actionが特定のマーカーインターフェースかアノテーションを実装していたら、HTTPレスポンスヘッダに

Cache-Control: no-store
Pragma: no-cache

を出力するようにしようと考えました。

疑問点

やりたい事はマーカーインターフェースでもアノテーションでも可能なのですが、実装するにはリフレクション的な事を行うので、どのやり方が一番処理が軽いのか、疑問が浮かびました。
interfaceを実装しているかどうかを調べる方法も、instanceofを使う方法とClass.isAssignableFromを使う方法があるので、それに関しても検証してみたいと思います。

やってみる

で、疑問点を解消するために、実際に実験をしてみました。

  • interface

マーカーインターフェースなので、中身は無いです。

public interface NoCacheInterface {
}
  • annotation

リフレクションするので、RetentionPolicyはRUNTIMEです。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface NoCache {
}
  • Actionクラス

マーカーインターフェースとアノテーションを実装します。
BaseActionはstrutsのActionを継承して、前/後処理(そこでHTTPレスポンスヘッダの出力も行う)等を行います。
この実験では特に意味は無いですが…。

@NoCache
public class TestAction extends BaseAction implements NoCacheInterface {
  • 検証コード

それぞれのやり方でぐるぐるループさせます。
処理の前にgcをして、後に残っているメモリ量も見てみます。

TestAction action = new TestAction();
int count = 100000000;
long start = 0;

-- インターフェース(instanceof)
System.gc();
start =System.currentTimeMillis();
for(int i=0;i<count;i++){
	if(action instanceof NoCacheInterface){
	}
}
System.out.println((System.currentTimeMillis()-start)+"msec");
System.out.println(Runtime.getRuntime().freeMemory());

-- インターフェース(isAssignableFrom)
System.gc();
start =System.currentTimeMillis();
for(int i=0;i<count;i++){
	if(NoCacheInterface.class.isAssignableFrom(action.getClass())){
	}
}
System.out.println((System.currentTimeMillis()-start)+"msec");
System.out.println(Runtime.getRuntime().freeMemory());

-- アノテーション
System.gc();
start =System.currentTimeMillis();
for(int i=0;i<count;i++){
	if(action.getClass().getAnnotation(NoCache.class)!=null){
	}
}
System.out.println((System.currentTimeMillis()-start)+"msec");
System.out.println(Runtime.getRuntime().freeMemory());

結果

以下のようになりました。

4msec
13829000
8msec
13661280
3674msec
13468800

結果は

  1. マーカーインターフェース(instanceof)
  2. マーカーインターフェース(isAssignableFrom)
  3. アノテーション

の順で、処理速度が速く使用メモリが少ないという事になりました。
なので、マーカーインターフェースで実装してinstanceofで確認することにします。
ただ、1億回もループしてこの程度ですけどね。