Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > ClassNotFoundException


Автор: Proger89 14.10.2010, 00:19
Доброго времени суток.
У меня довольно избитая проблема. Но я в упор не понимаю, что я делаю не так.
У меня есть приложение которое использует библиотелку log4j.
Перед её запуском я устанавливаю CLASSPATH командой
Код

export CLASSPATH=/home/proger/Soft/Programming/Languages/Java/apache-log4j-1.2.16/log4j-1.2.16.jar



Вот код программы:
Код

package com.mycompany.hellolog4j;

import org.apache.log4j.*;

public class SimpleLogging
{
    public SimpleLogging() {}

    public static void main( String[] args )
    {
        Logger logger = Logger.getLogger(SimpleLogging.class.getPackage().getName());
        logger.info("Hello this is an info message");
        System.out.println("Have you seen it?");
    }
}


В pom.xml я устанавливаю Main-Class для генерации манифеста
Код

 ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <archive>
                                                
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathLayoutType>repository</classpathLayoutType>
                            <classpathMavenRepositoryLayout>true</classpathMavenRepositoryLayout>
                            <mainClass>com.mycompany.hellolog4j.SimpleLogging</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
...


После этого запуская свой jar файл
Код

proger@progerlaptop:~/Documents/Programming/Java/Book/ProLog4J/Chapter02/HelloLog4J/target> java -jar HelloLog4J-1.0-SNAPSHOT.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at com.mycompany.hellolog4j.SimpleLogging.main(SimpleLogging.java:11)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
    at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:334)
    ... 1 more




Почему так получается, если CLASSPATH установлен и содержит нужный jar файл и все от чего данный файл зависит написано в MANIFEST?
Заранее благодарен



Автор: jk1 14.10.2010, 08:01
А в pom.xml у Вас log4j описан как зависимость (dependency)?

Автор: Proger89 14.10.2010, 09:27
Да описан. Вот:
Код

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
    </dependencies>


А вот что генерирует Maven в манифесте
Код

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: proger
Build-Jdk: 1.6.0_18
Main-Class: com.mycompany.hellolog4j.SimpleLogging
Class-Path: log4j/log4j/1.2.16/log4j-1.2.16.jar


Автор: Alexandr87 14.10.2010, 09:35
в начале функции main вызовете следующую команду
System.out.println(System.getProperty("java.class.path"));

убедитесь, что java действительно подцепила classpath

Автор: Skipy 14.10.2010, 09:36
Команда java -jar игнорирует любые установки classpath - что через командную строку, что через переменную окружения CLASSPATH. 

http://download.oracle.com/javase/6/docs/technotes/tools/windows/java.html - опция -jar:
Цитата
When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.


В этом случае все зависимости должны быть прописаны в манифесте, в разделе Class-Path, и только в относительных путях. Вот тут расписано, как работать с jar-файлами: http://download.oracle.com/javase/tutorial/deployment/jar/index.html

P.S. Использование CLASSPATH - вообще не лучшее решение.


Автор: Proger89 14.10.2010, 09:36
Все. Проблема решилась.
Дело в том, что при запуске jar файла java не ищет другие jar-ники в установленном в системе CLASSPATH она проверяет только то что написано в манифесте. А в манифесте написано:
Код

Class-Path: log4j/log4j/1.2.16/log4j-1.2.16.jar


то есть оно будет в текущей директории искать папку log4j и дальше по пути, а так как её не было, оно выбрасывало исключение.
Но все таки... Почему если я указал зависимости мавену, почему он сам не скопировал нужные библиотеки?

Добавлено через 2 минуты и 16 секунд
Цитата(Skipy @ 14.10.2010,  09:36)
Команда java -jar игнорирует любые установки classpath - что через командную строку, что через переменную окружения CLASSPATH. [/URL]

Спасибо за ответ и за ссылки. smile
Но разве Maven не должен делать эту работу? То есть устанавливать Class-Path в jar-нике и складывать нужные ему библиотеки?

Автор: Skipy 14.10.2010, 09:48
Цитата(Proger89 @ 14.10.2010,  09:36)
Но разве Maven не должен делать эту работу? То есть устанавливать Class-Path в jar-нике и складывать нужные ему библиотеки?

Сложно сказать. Maven - это вообще вещь в себе. При создании war - да, он все копирует. А вот с простым приложением - боюсь, надо дополнительные телодвижения делать, типа создания binary-with-dependencies артефакта.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)