log4j(log4j-1.2.17の場合)は、下記の順に設定ファイルを探し、最初に見つけたファイルを読み込む。 なお設定ファイルはクラスパスの直下に配置しなければならない。
以下は設定ファイルを配置しなかった際のlog4j自身のデバッグログである。設定ファイルを順番に探している様子がわかる。
赤字のエラーメッセージは設定ファイルが見つからなかった際に表示されるログである。
log4j: Trying to find [log4j.xml] using context classloader sun.misc.Launcher$AppClassLoader@1d9f953d.
log4j: Trying to find [log4j.xml] using sun.misc.Launcher$AppClassLoader@1d9f953d class loader.
log4j: Trying to find [log4j.xml] using ClassLoader.getSystemResource().
log4j: Trying to find [log4j.properties] using context classloader sun.misc.Launcher$AppClassLoader@1d9f953d.
log4j: Trying to find [log4j.properties] using sun.misc.Launcher$AppClassLoader@1d9f953d class loader.
log4j: Trying to find [log4j.properties] using ClassLoader.getSystemResource().
log4j: Could not find resource: [null].
log4j:WARN No appenders could be found for logger (test.Sample).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
前述のとおり、log4jは自動で設定ファイルを検索する仕組みがあるが、これにより開発者の意図しない設定ファイルを読み込んでしまうことがある。 そのような問題を回避するには、設定ファイルのファイル名や配置先を明示的に指定すればよい。その方法はいくつかある。
方法1:PropertyConfigurator、DOMConfiguratorを使用する
まず設定ファイルがプロパティ形式(*.properties)の場合、PropertyConfiguratorを使用する。
PropertyConfigurator.configure("resources/mylog4j.properties");
ログを出力するまでの流れは以下のような感じ。
package test;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class Sample {
private static Logger logger = Logger.getLogger(Sample.class);
public static void main(String[] args){
PropertyConfigurator.configure("resources/mylog4j.properties");
logger.debug("sampleのログ");
}
}
設定ファイルがxml形式(*.xml)の場合、PropertyConfiguratorをDOMConfiguratorに変更する。
DOMConfigurator.configure("resources/mylog4j.xml");
但し、PropertyConfigurator/DOMConfiguratorを使うと、クラスパス直下にlog4j.propertiesやlog4j.xmlが存在するとそれも読みこんでしまう(二重にログがでたりする)。 これはgetLogger()を呼んだタイミングでLogManagerがlog4j設定ファイルを読み込んでしまうことが原因。 この問題を回避する方法として、システムプロパティを利用する方法がある。
方法2:システムプロパティを使用する
どの設定ファイルを読み込むかをシステムプロパティに指定することができる。この場合、getLoggerのタイミングはシステムプロパティ設定後でなければならない。
プロパティ形式(*.properties)の場合、下記のように設定する。
package test;
import org.apache.log4j.Logger;
public class Sample {
private static Logger logger;
public static void main(String[] args){
System.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.properties");
logger = Logger.getLogger(Sample.class);
logger.debug("sampleのログ");
}
}
xml形式(*.xml)の場合、さらにlog4j.configuratorClassを指定する。指定しないとデフォルトでPropertyConfiguratorを使ってしまうため。
package test;
import org.apache.log4j.Logger;
public class Sample {
private static Logger logger;
public static void main(String[] args){
System.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.xml");
System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator");
logger = Logger.getLogger(Sample.class);
logger.debug("sampleのログ");
}
}
方法3:起動オプションを使用する
システムプロパティの応用だが、javaの起動オプションで-Dlog4j.configuration=file:/C:/tmp/mylog4j.propertiesのようにすればシンプルになる。getLoggerのタイミングも考慮する必要はない。
xmlの場合は、-Dlog4j.configuration=file:/C:/tmp/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfiguratorのようにする。
package test;
import org.apache.log4j.Logger;
public class Sample {
private static Logger logge = Logger.getLogger(Sample.class);
public static void main(String[] args){
logger.debug("sampleのログ");
}
}
方法1:PropertyConfigurator、DOMConfiguratorを使用する
設定ファイルがプロパティ形式(*.properties)の場合、PropertyConfiguratorを使用するのはクラスパス外のときと同様。 但し、引数にクラスローダから取得したURLクラスを渡す。
URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.properties");
PropertyConfigurator.configure(url);
ログを出力するまでの流れは以下のような感じ。
package test;
import java.net.URL;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class Sample {
private static Logger logger = Logger.getLogger(Sample.class);
public static void main(String[] args){
URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.properties");
PropertyConfigurator.configure(url);
logger.debug("sampleのログ");
}
}
xml形式(*.xml)の場合、PropertyConfiguratorをDOMConfiguratorに書き換える。
URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.xml");
DOMConfigurator.configure(url);
インスタンスメソッド内であれば、下記の記述も可能。
URL url = this.getClass().getClassLoader().getResource("test/mylog4j.properties");
PropertyConfigurator.configure(url);
-------------------------------------------------------------------------------
URL url = this.getClass().getClassLoader().getResource("test/mylog4j.xml");
DOMConfigurator.configure(url);
方法2:システムプロパティを使用する
システムプロパティに設定する方法はクラスパス外のときと同じ記述でよい。なお外部ファイルが見つからない場合、クラスパスから検索する。
package test;
import org.apache.log4j.Logger;
public class Sample {
private static Logger logger;
public static void main(String[] args){
System.setProperty("log4j.configuration", "test/mylog4j.properties");
logger = Logger.getLogger(Sample.class);
logger.debug("sampleのログ");
}
}
xmlの場合は、log4j.configuratorClassも指定する。
System.setProperty("log4j.configuration", "test/mylog4j.xml");
System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator");
logger = Logger.getLogger(Sample.class);
方法3:起動オプションを使用する
プロパティ形式の場合は、-Dlog4j.configuration=test/mylog4j.properties。
xml形式の場合は、-Dlog4j.configuration=test/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator。
package test;
import org.apache.log4j.Logger;
public class Sample {
private static Logger logge = Logger.getLogger(Sample.class);
public static void main(String[] args){
logger.debug("sampleのログ");
}
}
実現方式がたくさんあるので、最後に一覧にまとめておく。
配置先 | 方式 | ファイル形式 | コード | 備考 |
---|---|---|---|---|
クラスパス外 | Configurator | プロパティ | PropertyConfigurator.configure("resources/mylog4j.properties") | クラスパス直下に設定ファイルがあると二重にログがでたりする。 |
XML | DOMConfigurator.configure("resources/mylog4j.xml"); | クラスパス直下に設定ファイルがあると二重にログがでたりする。 | ||
システムプロパティ | プロパティ | System.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.properties") | getLoggerはシステムプロパティ設定後に使う。 | |
XML | System.setProperty("log4j.configuration", "file:/C:/tmp/mylog4j.xml") System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator") | getLoggerはシステムプロパティ設定後に使う。 | ||
起動オプション | プロパティ | -Dlog4j.configuration=file:/C:/tmp/mylog4j.properties | ||
XML | -Dlog4j.configuration=file:/C:/tmp/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator | |||
クラスパス内 | Configurator | プロパティ | URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.properties") PropertyConfigurator.configure(url) | クラスパス直下に設定ファイルがあると二重にログがでたりする。 |
XML | URL url = Thread.currentThread().getContextClassLoader().getResource("test/mylog4j.xml") DOMConfigurator.configure(url); | クラスパス直下に設定ファイルがあると二重にログがでたりする。 | ||
システムプロパティ | プロパティ | System.setProperty("log4j.configuration", "test/mylog4j.properties") | getLoggerはシステムプロパティ設定後に使う。 | |
XML | System.setProperty("log4j.configuration", "test/mylog4j.xml") System.setProperty("log4j.configuratorClass", "org.apache.log4j.xml.DOMConfigurator") | getLoggerはシステムプロパティ設定後に使う。 | ||
起動オプション | プロパティ | -Dlog4j.configuration=test/mylog4j.properties | ||
XML | -Dlog4j.configuration=test/mylog4j.xml -Dlog4j.configuratorClass=org.apache.log4j.xml.DOMConfigurator |