我有一个jar文件,我可以使用java -jar my-jar-file.jar
运行。
但是现在我必须使用反射从另一个java程序加载主类,当我这样做时,我得到一个ClassNotFoundException: javax.mail.MessagingException
。
我使用的代码:
URLClassLoader loader = URLClassLoader.newInstance(new URL[]{new File("my-jar-file.jar").toURI().toURL()});
Class<?> serverClass = loader.loadClass("com.foo.bar.application.MyMain");
Method main = serverClass.getMethod("main", String[].class);
String[] params = new String[]{"-flag", "value"};
main.invoke(null, (Object) params);
stacktrace就像这样(删除了细节):
Exception in thread "main" java.lang.reflect.InvocationTargetException
Caused by: java.lang.NoClassDefFoundError: javax/mail/MessagingException
Caused by: java.lang.ClassNotFoundException: javax.mail.MessagingException
我还尝试将System.getProperty("java.class.path")
中的条目添加到我传递给类加载器的URL
数组中,但也没有运气。
这个错误对我来说似乎是合理的,因为jar文件不包含javax.mail.MessagingException
(实际上不包含javax.mail
包)但是当我执行java -jar my-jar-file.jar
时它是如何工作的?
如何解决此问题?感谢
编辑:
添加了MANIFEST.MF内容:
Manifest-Version: 1.0
Main-Class: com.foo.bar.application.MyMain
Implementation-Version: 1.5.4
编辑2:
值得一提的是,jar文件在javamail.providers
目录中包含META-INF
文件。假设这个以某种方式使该jar工作,但我怎么能以编程方式做同样的事情?
javamail.providers
内容:
# AWS Mail Provider
protocol=aws; type=transport; class=com.amazonaws.services.simpleemail.AWSJavaMailTransport; vendor=Amazon Web Services LLC;
答案 0 :(得分:0)
好的,我通过添加Thread.currentThread().setContextClassLoader(loader);
:
URLClassLoader loader = URLClassLoader.newInstance(new URL[]{new File("my-jar-file.jar").toURI().toURL()});
Thread.currentThread().setContextClassLoader(loader);
Class<?> serverClass = loader.loadClass("com.foo.bar.application.MyMain");
Method main = serverClass.getMethod("main", String[].class);
String[] params = new String[]{"-flag", "value"};
main.invoke(null, (Object) params);
现在一切都按预期工作,我不再获得ClassNotFoundException
,但我仍然不太明白为什么会这样。在我看来,它试图使用不同的ClassLoader
加载其他类/资源,因此未能这样做,并且通过调用setContextClassLoader
我明确表示要使用提供的{ {1}}。