如何在Java中加载外部.class文件?跨项目加载遇ClassNotFoundException求解
没问题,Java完全支持加载当前项目外的类,你遇到的java.lang.ClassNotFoundException大概率是路径问题或者缺少Android相关依赖导致的,咱们一步步来排查解决:
问题原因分析
你前面两个普通Java类(Account和StackTest)能成功加载,是因为它们不依赖特殊第三方库,只要指定的classes目录路径正确就能找到。但GPSActivity是Android项目里的Activity类,它依赖Android SDK的核心类(比如android.app.Activity),而你的URLClassLoader只添加了Android项目的classes目录,没有包含Android SDK的依赖jar,导致加载时找不到这些基础依赖类,最终抛出异常。另外也需要确认类的全限定名和文件路径是否完全匹配。
具体解决步骤
1. 确认类文件存在且路径匹配
- 打开
C:/android/workspace/AllTest/app/build/intermediates/classes/debug/目录,检查是否存在edu/test/activity/GPSActivity.class文件,包名必须和目录结构完全对应(比如包名edu.test.activity对应目录edu/test/activity/)。 - 如果你的Activity是用Kotlin编写的,类文件可能会放在
kotlin/edu/test/activity/目录下,这时候需要把file3指向这个子目录,或者把上级目录加入类加载路径。
2. 添加Android SDK核心依赖到类加载器
Android的Activity类必须依赖android.jar才能被正确加载,你需要找到你本地Android SDK中的这个jar包,将其加入到URLClassLoader的路径中:
private void test() { File file = new File("C:/jworkspace/all_java/bin/edu/test/annotate/"); File file2 = new File("C:/jworkspace/all_java/bin/edu/test/collections/"); File file3 = new File("C:/android/workspace/AllTest/app/build/intermediates/classes/debug/"); // 替换为你本地Android SDK的实际路径和对应版本 File androidJar = new File("C:/Users/YourUsername/AppData/Local/Android/Sdk/platforms/android-33/android.jar"); try { URLClassLoader loader = URLClassLoader .newInstance(new URL[] { file.toURI().toURL(), file2.toURI().toURL(), file3.toURI().toURL(), androidJar.toURI().toURL() }); Class c = loader.loadClass("edu.test.annotate.Account"); Class c2 = loader.loadClass("edu.test.collections.StackTest"); Class c3 = loader.loadClass("edu.test.activity.GPSActivity"); System.out.println(c.getName()); System.out.println(c2.getName()); System.out.println(c3.getName()); loader.close(); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } }
注意:android-33要替换成你Android项目中指定的compileSdkVersion,路径也要对应你本地SDK的安装位置。
3. 处理额外依赖
如果GPSActivity还依赖其他第三方库(比如OkHttp、Glide等)或者项目内的其他类,需要把这些依赖的jar包或者classes目录也加入到URLClassLoader的路径中,否则依然会出现依赖类找不到的异常。
4. 关于类加载器的双亲委派
默认的URLClassLoader会遵循双亲委派机制,先委托父类加载器(比如系统类加载器)加载类。如果遇到类冲突的情况,你可以自定义类加载器,重写loadClass方法来调整委派顺序,但一般普通场景下不需要这么做。
内容的提问来源于stack exchange,提问作者Nyein Chan

