ローカルリポジトリへの追加
忘れるのでメモ。
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;