ローカルリポジトリへの追加
忘れるのでメモ。
mvn install:install-file -Dfile=
-DgroupId=
-DartifactId=
-Dversion=
-Dpackaging=
参考
http://www.techscore.com/tech/Java/ApacheJakarta/Maven/7/
JVMのパラメーター
参考にしたサイト
http://blog.ik.am/entry/view/id/85/title/JVM%E3%81%AE%E3%83%92%E3%83%BC%E3%83%97%E3%83%BBGC%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%BE%E3%81%A8%E3%82%81/
http://www.whitemark.co.jp/tec/java/javagc.html
抜粋---
■ 運用環境で是非設定しておくべきJava起動オプション
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-server サーバーモードを有効化
-Xms Javaヒープ初期サイズ。一般的に、-Xmxと同値にする
-Xmx Javaヒープ最大サイズ
-Xmn(-XX:NewSize) New領域初期サイズ。一般的に、-XX:MaxNewSizeと同値にする
-XX:MaxNewSize New領域最大サイズ
-XX:PermSize Permanent領域初期サイズ。一般的に、-XX:MaxPermSizeと同値にする
-XX:MaxPermSize Permanent領域最大サイズ
-verbose:gc(-Xloggc:path_to_file) GCログ出力を有効化
-XX:+PrintGCTimeStamps GCログにタイムスタンプ(Java起動時からの経過時間)を出力
-XX:+PrintGCDetails GCログを詳細に出力(New領域とJavaヒープそれぞれが
どれだけ減ったか出力される)
-XX:+PrintClassHistogram*1 SIGQUITシグナル受信時にヒープ統計情報を出力
(出力時に強制的にフル GCが発生)。-verbose:gc(-Xloggc:path_to_file)と併用必須。
なお、SIGQUITシグナルを送信するには、kill -3 を実行すればよい
-XX:+HeapDumpOnOutOfMemoryError OutOfMemoryError発生時にヒープダンプを出力
(Sun Java 1.4.2_12以上、1.5.0_07以上、1.6以上)
-
- -
アプリケーションサーバーにおいて、Java Heapに4GBを割り当てる場合の参考値。
- server
■メモリ設定系--------------------------------------------------------
- Xms 4096M
- Xms 4096M
- Xmn 1024M
- XX:MaxNewSize 1024M
- XX:PermSize 256M
- XX:MaxPermSize 256M
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
NewSizeは、SunVM場合、Heapの25%。
PermSizeは、Applicationによるが、AOPでリフレクションが多い場合は大きく積む。ASで64MB、Applicationで128MBの計算。
■GCダンプ系-----------------------------------------------------------
- verbose:gc
- Xloggc:filename
- XX:+PrintGCTimeStamps
- XX:+PrintGCDetails
- XX:+PrintClassHistogram
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
■GC系-----------------------------------------------------------------
- XX:SurvivorRatio=16
- XX:MaxTenuringThreshold=32
- XX:TargetSurvivorRatio=90
- XX:+UseParNewGC
- XX:+UseConcMarkSweepGC
- XX:+CMSIncrementalMode
- XX:+CMSIncrementalPacing
- XX:CMSIncrementalDutyCycleMin=0
- XX:CMSIncrementalDutyCycle=10
- XX:+UseTLAB
- XX:+CMSParallelRemarkEnabled
- XX:+CMSClassUnloadingEnabled
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
UserTLABは、スレッド ローカルのオブジェクト割り当てブロックを使用します。これにより、共有ヒープ ロックに対する競合の発生が減少して、同時実行性が向上します。
Java reflectionとpermメモリ
http://www.ibm.com/developerworks/jp/java/library/j-nativememory-aix/
まとめ
・reflectionは、-Dsun.reflect.inflationThreshold=N(default 15)以上の呼び出しが行われると、クラスが自動生成されて高速なバイトコードアクセスとなる。
それ以前は、低速なJNIアクセス。
・自動生成されたクラスは、Permメモリにロードされるので、reflectionにて大量のクラスが生成される場合、Permメモリを圧迫することになる(大量のPermが必要)。
・これを防ぐためには、「-Dsun.reflect.inflationThreshold=0」。
・PermのGCが行われると、「Unloading class sun.reflect.GeneratedMethodAccessor」が頻発することになる。
・”「-Dsun.reflect.noInflation=true」を指定すると、リフレクション・アクセサーはまったく拡張されなくなりますが、代わりに、バイトコード・アクセサーが何に対しても使用されます。”
つまり、「-Dsun.reflect.noInflation=true」は、常にクラスが自動生成されるってことか・・・。
・JSPは、リフレクションを使用する。
JUNITからDataSourceを利用するためには
やることは、
1. 自前でinitialcontextを作成して、JNDIにbindしてあげる。
JNDIへのbindingには、TomcatのNamingを利用するので、いつもの通り、pom.xmlに記述して取得する。
DataSourceの取得といったらconnectionの取得なので、ついでにcommons-dbcpを利用してconnection poolingするようなつくりにする。
pom.xml
<dependency> <groupId>tomcat</groupId> <artifactId>naming-java</artifactId> <version>5.0.28</version> <scope>test</scope> </dependency> <dependency> <groupId>tomcat</groupId> <artifactId>naming-factory</artifactId> <version>5.5.23</version> <scope>test</scope> </dependency> <dependency> <groupId>tomcat</groupId> <artifactId>naming-resources</artifactId> <version>5.5.23</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>[1.,)</version> <scope>test</scope> </dependency>
そうしたら、Google-guiceでDataSourceにBindするようにAbstractModuleを記述する。
ここでは、test用として自前でJNDIにbindするconfigureTestを追加で作成している。
public abstract class AbstractDataSourceModule extends AbstractModule { /** * commons-dbcpのプロパティを取得します。 * * @return */ abstract protected Properties getProperties(); /** * JNDI名称を取得します。 * * @return */ abstract protected String getJndiName(); protected void configureTest() { final String jndiNamePrefix = "java:/comp/env/"; String absoluteJndiName = jndiNamePrefix + getJndiName(); try { // commons-dbcpによるdataSourceの生成 DataSource dataSource = BasicDataSourceFactory.createDataSource(getProperties()); // Contextの生成 System.setProperty( Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory"); System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming"); InitialContext ic = new InitialContext(); ic.createSubcontext("java:"); ic.createSubcontext("java:/comp"); ic.createSubcontext("java:/comp/env"); ic.createSubcontext("java:/comp/env/jdbc"); ic.bind(absoluteJndiName, dataSource); // Bind IntialContext bind(Context.class).toInstance(ic); // Bind DataSource bind(DataSource.class) .annotatedWith(Names.named(getJndiName())) .toProvider( JndiIntegration .fromJndi(DataSource.class, absoluteJndiName)); bind(DataSource.class).toProvider( JndiIntegration.fromJndi(DataSource.class, absoluteJndiName)); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NamingException e) { throw new RuntimeException(e); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void configure() { final String jndiNamePrefix = "java:/comp/env/"; String absoluteJndiName = jndiNamePrefix + getJndiName(); try { InitialContext ic = new InitialContext(); // Bind IntialContext bind(Context.class).toInstance(ic); // Bind DataSource bind(DataSource.class) .annotatedWith(Names.named(getJndiName())) .toProvider( JndiIntegration .fromJndi(DataSource.class, absoluteJndiName)); bind(DataSource.class).toProvider( JndiIntegration.fromJndi(DataSource.class, absoluteJndiName)); } catch (NamingException e) { throw new RuntimeException(e); } catch (Exception e) { throw new RuntimeException(e); } } }
AbstractDataSourceModuleを継承してOracle用のパラメーター設定をサブクラスに定義する。
public class OracleDataSourceModule extends AbstractDataSourceModule { Object[][] dbcpProperties = { { "driverClassName", "oracle.jdbc.pool.OracleConnectionPoolDataSource" }, { "url", "jdbc:oracle:thin:@127.0.0.1:1521:orcl" }, { "username", "ELLECTRA" }, { "password", "PASSWORD" }, { "initialSize", "30" }, { "maxActive", "100" }, { "maxIdel", "30" }, { "maxWait", "500" } }; String jndiName = "jdbc/hoge"; @Override protected String getJndiName() { return jndiName; } @Override protected Properties getProperties() { Properties properties = new Properties(); for (Object[] prop : dbcpProperties) { properties.put(prop[0], prop[1]); } return properties; } }
さらにテスト用でconfigureTest()でconfigureするように書き換える。
public class OracleDataSourceModuleTest extends OracleDataSourceModule { @Override protected void configure() { configureTest(); } }
これで、前回のTestRunnerを利用すれば、ModuleにOracleDataSourceModuleを指定していも、JUnit時は、OracleDataSourceModuleTestが呼ばれる。
こういう暗黙的ルールは良いのか悩みどころです。
Google Guiceを利用したJUnit試験用のRunnerとAnnotation 改造
前回作成したTestRunnerに対して、Moduleのクラス名のsafixにTestが付いているものを優先して読み込むように改造した。
#テスト時は、xxxxを利用したいといった場合用です。
public class GuiceJunitRunner extends BlockJUnit4ClassRunner { protected final static Log _log = LogFactory.getLog(GuiceJunitRunner.class); public GuiceJunitRunner(Class<?> klass) throws InitializationError { super(klass); } @Override protected void validateZeroArgConstructor(List<Throwable> errors) { // nothing } @Override protected Object createTest() throws Exception { Class<?> cls = getTestClass().getJavaClass(); GuiceStage guiceStage = cls.getAnnotation(GuiceStage.class); GuiceModule guiceModule = cls.getAnnotation(GuiceModule.class); Injector injector = null; List<Module> modules = new ArrayList<Module>(); if (guiceModule != null) for (Class<?> moduleClass : guiceModule.value()) { try { String testModule = moduleClass.getName() + "Test"; try { moduleClass = Class.forName(testModule); } catch (Exception e) { ; // nothing } modules.add((Module) moduleClass.newInstance()); } catch (InstantiationException e) { if (_log.isErrorEnabled()) { _log.error(MessageFormat.format( "InstantiationException Module is {1}", moduleClass.toString()), e); } throw e; } catch (IllegalAccessException e) { if (_log.isErrorEnabled()) { _log.error(MessageFormat.format( "IllegalAccessException Module is {1}", moduleClass.toString()), e); } throw e; } } if (guiceStage != null && guiceModule != null) { injector = Guice.createInjector(guiceStage.value(), modules); } else if (guiceStage != null) { injector = Guice.createInjector(guiceStage.value()); } else if (guiceModule != null) { injector = Guice.createInjector(modules); } else { injector = Guice.createInjector(Stage.DEVELOPMENT); } return injector.getInstance(getTestClass().getJavaClass()); } }
Google Guiceでservlet
GuiceでServeletを利用するには、guice-servlet.jarが必要になります。
mavenのglobal repositoryにないので、ローカルリポジトリに登録します。
%maven install:install-file -Dfile=guice-servlet-3.0.jar -DgoupdId=com.google.guice -DartifactId=guice-servlet -Dversion=3.0 -Dpackaging=jar
webapp用のプロジェクトを作成する。
%mvn archetype:generate
maven3.0ですと対話型でできます。
最初のChoose a numberを112を指定します。
そして必要な項目をpom.xmlに設定します。
最低限だとこんな感じかな。
ポイントは、WEBコンテナがもっているjarは、scopeにprovidedを指定してdeployする対象から外す。
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.3</version> <scope>provided</scope> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>[2.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>[1.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>[0.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>[0.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>[4.,)</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>[3.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.google.inject</groupId> <artifactId>guice-servlet</artifactId> <version>[3.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>[0.,)</version> <scope>runtime</scope> </dependency> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils-core</artifactId> <version>[1.,)</version> <scope>runtime</scope> </dependency> </dependencies> <build> <finalName>pae-web</finalName> <sourceDirectory>src/main/java</sourceDirectory> <testSourceDirectory>src/test/java</testSourceDirectory> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-eclipse-plugin</artifactId> <version>2.8</version> <configuration> <downloadSources>true</downloadSources> <downloadJavadocs>true</downloadJavadocs> </configuration> </plugin> </plugins> </pluginManagement> </build>
いつも通り、eclipseのプロジェクトに変換しますが、ついで、WTP対応にしておくと便利なので、WTPの指定をします。
% mvn eclipse:clean eclipse:eclipse -Dwtpversion=2.0
web.xmlにguiceのフィルターの設定をします。
guiceのサーブレットの動作は、listenerでinitializeしたservletやfilterのマッピングをGuiceFilterでキャッチしてDispatchしてくれるというものらしい。
<filter> <filter-name>GuiceFilter</filter-name> <filter-class> com.google.inject.servlet.GuiceFilter </filter-class> </filter> <filter-mapping> <filter-name>GuiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>jp.co.sandbox.GuiceServletConfig</listener-class> </listener>
public class GuiceServletConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { serve("*.do2").with(MyServlet.class); } }); } }
サンプルの何もしないサーブレット
public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("enter doGet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("enter d oPost"); } }
Google GuiceのProviderによるInjection
factory系で生成したオブジェクトをDIしましょうという機能らしい。
やり方は2通りで、Providerを実装するか、@Providesインスタンスで指定するか。
ただのhogeを返すProvider.
public class SampleProvider implements Provider<String> { public String get() { return "hoge"; } }
こちらは、上の"hoge"を返すプロバイダーを"sample"という名前付きでStringにbindする例と、@Providesを利用して、"Checkout"という名前付きでbindする例。
@Providesを利用した場合は、メソッドの戻り値のクラスにbindする。
public class SampleProviderModule extends AbstractModule { @Override protected void configure() { bind(String.class).annotatedWith(Names.named("Sample")).toProvider(SampleProvider.class); } /** * Provider * * @return */ @Provides @Named("Checkout") public String provideJiji() { return "jiji"; } }
利用する側はいつもの通り。
@Inject @Named("Sample") String sample; @Inject @Named("Checkout") String jiji;