この人頭いいなと思ったエピソード

お世話になります。Javaでプログラミングの勉強をしています。

mavenなど、Jarの依存関係を解決してくれるツールがありますが、
バージョンが違うlog4jなどが複数の依存ライブラリで利用されていて、
実行時にエラーが出てしまうことがあります。(コンパイル時にはエラーは出ない)

例)
dev_project ->log4j v1.2.4に依存
+-depend_project_a -> log4j v1.1.3に依存
+-depend_project_b -> log4j v1.1.4に依存
+-depend_project_c -> log4j v0.9.1に依存

こういった場合、mavenを利用していれば、依存関係階層を調べて
適宜excludeしていけばよいと思います。

しかしそのようなツールを使っていない(純粋なjavaプロジェクト)場合、
どのようにバージョン違いの重複するjarを調べたら良いかわかりません。

私が試してみたのは、jarのクラスパスをひとつずつチェックして
log4j-****.jarの定義をひとつずつ探すという方法です。
これは大変手間がかかります。

テストケースなどJavaコード内で調べる方法はありますでしょうか。
どうぞ宜しくお願い致します。

■参考環境
OS:windows8.1
Java:oracle-java1.8
eclipse: 4.4
maven: 3.2

A 回答 (1件)

各Jarに含まれる代表的なクラスを


下記のコードに読み込ませる…かなぁ。

http://blogs.wankuma.com/kacchan6/archive/2007/0 …

この回答への補足

解決しました。

クラスパスを取得し、jar内のクラスを取得していけば
実際にクラスがロードされているかどうかに関わらず、
重複するパッケージ・クラスを調査することができました。

サンプルプロジェクト構成ここから

testprj
│ .classpath
│ .project

├─.settings
│ org.eclipse.jdt.core.prefs
├─lib
│ log4j-1.2.14.jar
│ log4j-1.2.15.jar
│ log4j-1.2.16.jar
│ log4j-1.2.17.jar

└─src
└─jp
└─co
└─testprj
DependJarDetectTest.java

サンプルプロジェクト構成ここまで

サンプルコード(DependJarDetectTest.java)ここから

package jp.co.testprj;

import java.io.File;
import java.util.Enumeration;
import java.util.Properties;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class DependJarDetectTest {

private TreeSet<String> resultSet = new TreeSet<String>();

public static void main(String[] args) {
try {
new DependJarDetectTest().execDetect();
} catch (Exception e) {
e.printStackTrace();
}
}

private void execDetect() throws Exception {
Properties prop = System.getProperties();
String javaclasspath = prop.getProperty("java.class.path", null);

String[] classPathArray = javaclasspath.split(";");
for (int i = 0; i < classPathArray.length; i++) {
System.out.println("java.class.path [" + i + "] = " + classPathArray[i]);
getJarFileClassListFromClassPath(classPathArray[i]);
}
}

private void getJarFileClassListFromClassPath(String classPath) throws Exception {
File file = new File(classPath);
if (file.isDirectory()) return;

JarFile jarFile = new JarFile(file);
for (Enumeration<?> e = jarFile.entries(); e.hasMoreElements();) {
JarEntry entry = (JarEntry) e.nextElement();
if(entry.isDirectory() || entry.getName().indexOf(".class") < 0) continue;

if(resultSet.contains(entry.getName())) {
System.out.println("\t[競合]: " + entry.getName());
} else {
System.out.println("\t" + entry.getName());
resultSet.add(entry.getName());
}
}
jarFile.close();
}
}

サンプルコードここまで

ご協力頂きましてありがとうございました。

補足日時:2014/11/29 11:24
    • good
    • 0
この回答へのお礼

回答頂きましてありがとうございます。

私の質問の仕方が悪かったのですが、
どのjarのどのクラスが重複しているかわからない状態から調べる方法を知りたかったのです。
質問内の例ではlog4jが競合していることがわかってる風にとれるので、
その場合はteketonさんの方法で代表的なクラスからどのjarが読み込まれているか調べることが可能ですね。

お礼日時:2014/11/29 10:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報