如何解决java.lang.NoClassDefFoundError?
我已经在Oracle的Java教程中尝试了这个例子。 他们都编译好,但在运行时,都提出了这个错误:
Exception in thread "main" java.lang.NoClassDefFoundError: graphics/shapes/Square at Main.main(Main.java:7) Caused by: java.lang.ClassNotFoundException: graphics.shapes.Square at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 1 more
我想我可能有错误的文件夹中的Main.java
文件。 这是目录层次结构:
graphics ├ Main.java ├ shapes | ├ Square.java | ├ Triangle.java ├ linepoint | ├ Line.java | ├ Point.java ├ spaceobjects | ├ Cube.java | ├ RectPrism.java
这里是Main.java
:
import graphics.shapes.*; import graphics.linepoint.* import graphics.spaceobjects.*; public class Main { public static void main(String args[]) { Square s = new Square(2,3,15); Line l = new Line(1,5,2,3); Cube c = new Cube(13,32,22); } }
我在这里做错了什么?
UPDATE
在我把把Main
类放到graphics
包(我添加了package graphics;
把它),设置类path为“_test”(包含graphics的文件夹),编译它,并运行它使用java graphics.Main
(从命令行), 有效。
真的晚了更新#2
我没有使用Eclipse(只是Notepad ++和JDK),上述更新解决了我的问题。 然而,似乎很多答案都是针对Eclipse和IntelliJ的,但它们有相似的概念。
编译完代码后,最终会在程序中为每个类添加.class
文件。 这些二进制文件是Java解释执行你的程序的字节码。 NoClassDefFoundError
指示负责dynamic加载类的类加载器(本例中为java.net.URLClassLoader
)找不到要尝试使用的类的.class
文件。
如果所需的类不存在,则代码将无法编译(除非类使用reflection进行加载),所以通常此exception意味着您的类path不包含所需的类。 请记住,类加载器(特别是java.net.URLClassLoader
)将在类path的每个条目中的文件夹a / b / c /中的程序包abc中查找类。 NoClassDefFoundError
也可以表明你错过了一个.jar文件的传递依赖关系,这个依赖关系是你编译的,你正在尝试使用。
例如,如果您有一个类com.example.Foo
,编译后您将有一个类文件Foo.class
。 比如说你的工作目录是.../project/
。 该类文件必须放置在.../project/com/example
,并且将类path设置为.../project/
。
附注:我build议您利用Java和JVM语言中的惊人工具。 像Eclipse和IDEA这样的现代IDE,以及像Maven或Gradle这样的构buildpipe理工具将帮助您不必担心类path(尽可能多的)并关注代码! 也就是说, 这个链接解释了如何在命令行上执行时设置类path。
我想在NoClassDefFoundError
上更正其他人的观点。
NoClassDefFoundError
可能由于多种原因而发生
- ClassNotFoundException – 找不到该引用类的.class,而不pipe它在编译时是否可用(即基类/子类)。
- find类文件,但在初始化静态variables时引发exception
- 类文件位于,初始化静态块时引发exception
在原始问题中,可以通过将CLASSPATH设置为引用的类jar文件或其包文件夹来纠正这种情况。
说“在编译时可用”是什么意思?
- 引用的类用于代码中。
例如:两个类,A和B(延伸到A)。 如果B在代码中被直接引用,它在编译时可用,即A a = new B();
说“在编译时不可用”是什么意思?
- 编译时间类和运行时间类是不同的,例如,基类是使用子类的类名加载的,例如Class.forName(“classname”)
例如:两个类,A和B(延伸到A)。 代码有
A = Class.forName(“B”)。newInstance();
NoClassDefFoundError
表示该类在Compile time
存在于类path中,但在Runtime
的类path中不存在。
如果您使用的是Eclipse,请确保在.classpath
文件中包含shapes
, linepoints
和spaceobjects
作为条目。
如果对于添加到项目中的某个外部jar文件获取了NoClassDefFoundError,请尝试在lib文件夹中添加该jar文件,并通过属性>> Java Build Path >>添加variables>>configurationvariables>> New将其添加到类path中variablesinput。 并重build。
如果在编译和运行时遇到以下错误之一:
-
的NoClassDefFoundError
-
错误:无法find或加载主类hello
-
java.lang.ClassLoader.defineClass1(Native Method)java.lang.ClassLoader.defineClass(Unknown Source)在线程“main”中的exceptionjava.lang.NoClassDefFoundError:javaTest / test / hello(错误名称:test / hello)at java.net.URLClassLoader.access上的java.net.URLClassLoader.defineClass(Unknown Source)上的java.security.SecureClassLoader.defineClass(Unknown Source)在java.net.URLClassLoader $ 1.run(Unknown Source)上的$ 100 java.net.URLClassLoader在java.lang.ClassLoader.loadClass(Unknown Source)处于java.net.URLClassLoader.findClass(Unknown Source)处的java.security.AccessController.doPrivileged(Native方法)处获得$ 1.run(Unknown Source) .misc.Launcher $ AppClassLoader.loadClass(Unknown Source)at java.lang.ClassLoader.loadClass(Unknown Source)at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
————————– SOLUTIION ———————–
问题主要在软件包组织方面。 您应该根据源代码中的包类别妥善安排文件夹中的类。
On Compiling process use this command: javac -d . [FileName.java] To Run the class please use this command: java [Package].[ClassName]
java.lang.NoClassDefFoundError
表示在编译 时发现了某些东西,但在运行 时却没有。 也许你只需要将它添加到类path。
在重大重构之后,这有时会发生在IntelliJ IDEA中。
右键单击您的项目,然后select – >编译模块 ,然后重新启动项目,它应该再次工作。
在类path中找不到预期的类时,不会发生类定义exception 。 在编译时间类:类是从Java编译器生成的,但不知何故在运行时找不到从属类。
让我们通过一个简单的例子:
public class ClassA{ public static void main(String args[]){ //Some gibberish Code... String text = ClassB.getString(); System.out.println("Text is :" + text); }
}
public class ClassB{ public static String getString(){ return "Testing Some Exception"; } }
现在让我们假设上面的两个Java源代码放在一些文件夹让我们说“NoClassDefinationFoundExceptionDemo”
现在打开一个shell(假设Java已经正确安装)
- 转到文件夹“NoClassDefinationFoundExceptionDemo”
- 编译Java源文件javac ClassB javac ClassA
- 两个文件都编译成功,并生成与ClassA.class和ClassB.class相同的文件夹中的Class文件
- 现在,由于我们将ClassPath过滤为当前工作目录,因此我们执行以下命令java -cp。 ClassA和它成功地工作,你会看到屏幕上的输出
- 现在让我们说,你从现在的目录中删除了ClassB.class文件。 现在再次执行该命令。 java -cp。 ClassA现在,它会用NoClassDefFoundException来迎接你。 因为ClassB是ClassA的依赖关系,在类path(即当前工作目录)中找不到。
Java中的NoClassDefFoundError:
定义:
NoClassDefFoundError将在编译期间出现,但在运行时在java classpath中不可用。 通常情况下,当你得到NoClassDefFoundError时,你会在日志中看到下面一行:线程“main”中的exceptionjava.lang.NoClassDefFoundError
可能的原因:
-
该类在Java Classpath中不可用。
-
您可能正在使用jar命令运行您的程序,并且未在清单文件的ClassPath属性中定义类。
-
任何启动脚本都将重写Classpath环境variables。
-
因为NoClassDefFoundError是java.lang.LinkageError的一个子类,所以如果像本地库这样的依赖项之一可能不可用的话,它也会出现。
-
检查日志文件中的java.lang.ExceptionInInitializerError。 由于静态初始化失败而导致的NoClassDefFoundError非常普遍。
-
如果你在J2EE环境下工作的可见性比Class中的多个Classloader还可能导致java.lang.NoClassDefFoundError,请参阅示例和场景部分进行详细讨论。
可能的决议:
-
validation所有必需的Java类都包含在应用程序的类path中。 在开始执行依赖于某些外部库的Java应用程序之前,最常见的错误是不包括所有必需的类。
-
应用程序的类path是正确的,但Classpath环境variables在应用程序执行之前被覆盖。
-
validation前面提到的ExceptionInInitializerError没有出现在应用程序的堆栈跟踪中。
资源:
在Java J2EE中解决java.lang.NoClassDefFoundError的3种方法
java.lang.NoClassDefFoundError – 如何解决找不到类Def错误
如果你的项目是像com.blahcode
这样的包,而你的类叫做Main
,编译后的文件可能会以./out/com/blahcode/Main.class
这样的目录结构输出。 IntelliJ IDEA尤其如此。
当试图从一个shell或者cmd运行的时候,你需要cd
到那个包含com
的子目录。
cd out java -classpath . com.blahcode.Main
确保您正确键入类名称。 我得到这个错误,因为我没有用大写字母开始类名
在NetBeans项目上工作了好几个月之后,我突然收到一个“Low Memory”警告后很快就收到了NoClassDefFoundError消息。 做一个干净的重build没有帮助,但closuresNetbeans完全重新开放项目没有错误报告。
这个答案是特定于在服务中发生的java.lang.NoClassDefFoundError:
我的团队最近在升级提供服务的rpm后看到了这个错误。 rpm和它里面的软件都是用Maven编译的,所以看起来我们有一个编译时间的依赖关系,但是没有包含在rpm中。
但是,在调查时,找不到的类与堆栈跟踪中的几个类位于同一个模块中。 而且,这不是最近才被添加到构build中的模块。 这些事实表明它可能不是一个Maven依赖性问题。
最终的解决scheme: 重新启动服务!
看起来rpm升级使底层jar文件上的服务文件句柄失效。 然后服务看到一个没有被加载到内存中的类,在它的jar文件句柄列表中find它,并且因为它可以加载类的文件句柄已经失效而找不到它。 重新启动服务,迫使它重新加载所有的文件句柄,然后允许它加载在rpm升级之后在内存中找不到的那个类。
希望具体案件帮助某人。
呃..join类path后,我有相同的错误。 我find的解决scheme是删除我的项目的bin文件夹。 之后,该文件夹是只有清单文件自动创build…然后错误消失。
我希望它有帮助。
我在这条链上的两分钱:
确保类path包含完整path( /home/user/lib/some_lib.jar
而不是~/lib/some_lib.jar
),否则您仍然可能会遇到NoClassDefFoundError
错误。
当由运行时类加载器加载的类不能访问java根加载器已经加载的类时,我得到NoClassFoundError。 因为不同的类加载器处于不同的安全域(根据java),所以jvm将不允许已经由根加载器加载的类在运行时加载器地址空间中被parsing。
用'java -javaagent:tracer.jar [你的JAVA ARGS]'运行你的程序
它产生显示加载类的输出,以及加载该类的加载器env。 这是非常有用的追查为什么一个类不能解决。
// ClassLoaderTracer.java // From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5 import java.lang.instrument.*; import java.security.*; // manifest.mf // Premain-Class: ClassLoadTracer // jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class // java -javaagent:tracer.jar [...] public class ClassLoadTracer { public static void premain(String agentArgs, Instrumentation inst) { final java.io.PrintStream out = System.out; inst.addTransformer(new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString(); out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd); // dump stack trace of the thread loading class Thread.dumpStack(); // we just want the original .class bytes to be loaded! // we are not instrumenting it... return null; } }); } }
我的genymotion设备发生了很多事情。 确保安装Genymotion的驱动器上有足够的可用内存。
这发生在Android Studio中。
为我工作的解决scheme:只需重新启动工作室。
我使用Android studio时遇到了与我的Android开发相同的问题。 提供的解决scheme是一般的,并没有帮助我(至less对我而言)。 经过数小时的研究,我发现了以下解决scheme,并可能有助于Android开发人员使用android studio进行开发。 修改设置如下Preferences – > Build,Execution,Deployment – > Instant Run – >取消选中第一个选项。
有了这个变化,我正在运行。 希望这会帮助我的开发者朋友。
检查你的类中是否有静态处理程序,如果是,请删除它或更改你的代码,导致静态处理程序只能在主线程中启动,崩溃可能以这种方式触发:
1.首先在非主线程中创build类的实例并捕获崩溃。
2.然后在主线程中调用Class的字段方法,会得到NoClassDefFoundError。
这里是testing代码:
public class MyClass{ private static Handler mHandler = new Handler(); public static int num = 0;
}
在你主要活动的onCrete方法中,添加testing代码部分:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //test code start new Thread(new Runnable() { @Override public void run() { try { MyClass myClass = new MyClass(); } catch (Throwable e) { e.printStackTrace(); } } }).start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } MyClass.num = 3; // end of test code }
有一个简单的方法来解决它使用handlerThread init处理程序:
private static Handler mHandler; private static HandlerThread handlerThread = new HandlerThread("newthread"); static { handlerThread.start(); mHandler = new Handler(handlerThread.getLooper(), mHandlerCB); }
如果你使用多个模块,你应该有
dexOptions { preDexLibraries = false }
在你的构build文件中。
我在使用Apache Axis时遇到了这个问题。 花费了几个小时,根据大部分的反馈和类似的线程来处理classpath / buildconfiguration。 事实certificate,我错过了某些Web服务事务所必需的支持XML库。 把它们添加到项目中,一切都变好了
(1)第一种方法:我解决了这个问题通过删除一些Dependencies类从下面的代码中删除这个问题,我遇到了4.2.2
compile 'com.google.android.gms:play-services-gcm:11.0.4' compile 'com.google.android.gms:play-services:11.0.4'
这些额外的我的代码,我删除了他们
dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile files('libs/ypylibs.jar') compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.google.android.gms:play-services-gcm:11.0.4' compile 'com.google.android.gms:play-services:11.0.4' compile 'com.google.android.gms:play-services-ads:11.0.4' compile 'com.dailymotion.dailymotion-sdk-android:sdk:0.1.12' compile 'org.apache.httpcomponents:httpcore:4.4.1' compile 'commons-io:commons-io:1.3.2' compile 'com.oguzdev:CircularFloatingActionMenu:1.0.2' compile 'com.android.support:multidex:1.0.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12'
}
(2)方法:解决这个问题的另一种方法是创build一个新的类MyApplication
public class MyApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); }
}
然后将其添加到mainfest文件和应用程序标记中
<application android:allowBackup="true" android:name=".gps.navigation.map.MyApplication" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"></application>
在你的主要活动之后,如果需要删除appcompactactivity,并扩展你的课程活动,那么将起作用。
这个exception的一个错误来源可能是由于Proguard的定义不一致造成的,例如缺失
-libraryJars“path.to.a.missing.jar.library”。
这解释了为什么编译和运行正常,因为jar在那里,而清洁和生成失败。 记得在proguard setup中定义新添加的jar库!
请注意,来自Proguard的错误消息实际上不符合标准,因为当jar完全不在时,它们很容易与类似的ant消息混淆。 只有在最底层才会有一点麻烦的进步。 因此,开始寻找传统的类path错误等是相当逻辑的,但是这将是徒劳的。
很显然,NoClassDefFoundexception将是运行时的结果,例如生成的可执行jar文件,并且缺乏一致性。 有人把它叫做“地狱”