如何从jar文件动态运行java类

如何从jar文件动态运行java类,java,jar,classloader,Java,Jar,Classloader,我正在从事一个java项目,该项目需要一个作为服务器运行的第三方java程序 通常,我会: java -cp jarfile1.jar:jarfile2.jar className arg1 arg2 然后我会运行我的java代码。这样就行了 我想知道是否有任何方法可以直接从我的代码运行这个类,而不必手动启动它,包括在我的项目中需要的两个.jar 正如我在一些示例中看到的那样,我尝试使用URLClassLoader,但要么我做得不对,要么没有涉及这个特定用例 URLClassLoader cl

我正在从事一个java项目,该项目需要一个作为服务器运行的第三方java程序

通常,我会:

java -cp jarfile1.jar:jarfile2.jar className arg1 arg2
然后我会运行我的java代码。这样就行了

我想知道是否有任何方法可以直接从我的代码运行这个类,而不必手动启动它,包括在我的项目中需要的两个.jar

正如我在一些示例中看到的那样,我尝试使用
URLClassLoader
,但要么我做得不对,要么没有涉及这个特定用例

URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:///tmp/jarfile1.jar"),new URL("file:///tmp/jarfile2.jar")});
Class<?> cls = classLoader.loadClass("className");
Method method = cls.getDeclaredMethod ("main");
Object instance = cls.newInstance();
Object result = method.invoke (instance);
请注意,我将.jars复制到/tmp以隔离故障原因。这些文件存在并且可以访问

如何让它在java代码中运行上面指定的类


谢谢

如果该类存在于不同的类加载器中,则需要使用反射来访问它:

ClassLoader classLoader = new URLClassLoader(
    new URL[] { firstJarURL, secondJarURL });

String[] args = { arg1, arg2 };

try {
    Class<?> mainClass = classLoader.loadClass("com.somepackage.ClassName");
    mainClass.getMethod("main", String[].class).invoke(null, args);
} catch (ReflectiveOperationException e) {
    throw new RuntimeException(e);
}
ClassLoader ClassLoader=新的URLClassLoader(
新URL[]{firstJarURL,secondJarURL});
字符串[]args={arg1,arg2};
试一试{
Class mainClass=classLoader.loadClass(“com.somepackage.ClassName”);
getMethod(“main”,String[].class).invoke(null,args);
}捕捉(反射操作异常e){
抛出新的运行时异常(e);
}

我终于修好了!所做的事情:

  • 我忘了将第二个jar添加到项目的类路径中(duh!)
  • 因为所有内容都在项目类路径上,所以我只是重用了当前的类加载器
  • 最终工作代码:

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Class<?> cls = classLoader.loadClass("className");
    Method method = cls.getDeclaredMethod("main", String[].class);
    Object instance = cls.newInstance();
    Object result = method.invoke(null, (Object)args);
    

    你已经做完了

    对不起,我不明白。将代码保存为可运行的.jar文件如何避免我运行第三方类?你能详细介绍一下吗?
    ClassName.main(“arg1”、“arg2”)?向我们展示带有
    URLClassLoader
    的代码以及您遇到的错误哦,很好。这会在一个单独的线程上工作吗(这样主线程就不会被阻塞)?如果是这样,请发布一个答案,这样我就可以接受:)不,它不会在单独的线程中执行。但是没有什么可以阻止你启动一个线程来调用它。如果包含类名的jar文件位于类路径中,则不需要单独的类加载器(除非您特别想要隔离),我担心它不起作用,它生成了与我问题中的编辑相同的错误:(您是否验证了“alice/tuprolog/lib/InvalidObjectIdException.class”存在于一个jar文件中?这至少解决了对
    main
    的正确调用。但是,首先尝试查找类
    alice.tuprolog.lib.invalidobjectIndexception
    ,并使用类似代码。首先使用jar中的zip工具查看。您还可以将当前类加载器/
    类作为第二个参数添加到URLClassLoaderLoader.getSystemClassLoader()
    。是的,它在第二行,因为类名在Java代码中是硬编码的,为什么要使用反射。为什么不简单地用
    className.main(args)
    替换您的5行代码?另外,您不应该创建className的实例来调用main().main()是一个静态方法。请将null作为method.invoke()的第一个参数传递。如果为True,我将把它添加到答案中
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Class<?> cls = classLoader.loadClass("className");
    Method method = cls.getDeclaredMethod("main", String[].class);
    Object instance = cls.newInstance();
    Object result = method.invoke(null, (Object)args);
    
    className.main(args);