【问题标题】:Exporting Jar file with Manifest attribute in Android Studio?在 Android Studio 中导出带有 Manifest 属性的 Jar 文件?
【发布时间】:2016-04-05 16:27:00
【问题描述】:

我正在尝试从 Android 工作室运行一个 jar。经过长时间的解决方法,jar 文件运行完美。

现在我需要从 android studio 中导出 jar 文件。我从 build/libs 文件夹中获取了 Jar 文件。

但问题是jar文件显示错误。

没有主清单属性,在“app.jar”中

所以我找到了这个解决方案。 Can't execute jar- file: "no main manifest attribute"

然后我阅读了 MANIFEST.MF 并将邮件类添加到该文件中。

jar {
    manifest.attributes(
            'Main-Class': "com.Remo.server.RemoServerApp"
    )
}

在我的 gradle 中添加这些之后。我的 MANIFEST.MF 包含 MainClass。

但我仍然遇到同样的错误?我该如何解决这个问题?

注意:目标是我想从项目中导出一个 Runnable Jar 文件。

更新:

在 MANIFEST.MF 中添加 MainClass 之后。我遇到了以下错误。

Exception in thread "main" java.lang.NoClassDefFoundError: com/Remo/protocol/RemoConnection
    at com.Remo.server.RemoServerApp.<init>(RemoServerApp.java:33)
    at com.Remo.server.RemoServerApp.main(RemoServerApp.java:97)
Caused by: java.lang.ClassNotFoundException: com.Remo.protocol.RemoConnection
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 2 more

MANIFEST.MF

清单版本:1.0
主类:com.Remo.server.RemoServerApp

更新 2

从您的解决方案中,我了解到我们需要将 remoprotocol jar 文件复制到 remoserver。

remoserver 项目 gradle 文件

apply plugin: 'java'

sourceSets {
    main {
        resources.srcDirs = ['src/main/resources']
    }
}

dependencies {
    compile project(':remoprotocol')
    compile files('libs/bluecove-2.1.1.jar')
}

jar {
    manifest.attributes(
            'Main-Class': "com.remo.server.remoServerApp"
    )
    manifest.attributes(
            'Class-Path': configurations.runtime.files.collect { it.getName() }.join(' '))
}

task copyRTDependenciesToLib(type: Copy) {
    into "$buildDir/output/lib"
    from configurations.runtime
}

运行 gradle 任务后,我也遇到了同样的错误。

【问题讨论】:

  • 听起来您还需要将类路径添加到清单中。你能发布你的完整 manifest.mf 吗?
  • 这个 jar 中是否包含 com/Remo/protocol/RemoConnection 类?还是有任何外部依赖jar?
  • @RaGe 我已将 build.gradle 文件中的协议模块作为依赖项引用。但它们不包含在我的 jar 文件中。如何添加它们?
  • 您不必将协议模块捆绑在您的 jar 中。只要您的可运行 jar manifest.mf 中有一个类路径条目,您就可以将协议 jar 放在与可运行 jar 相同的文件夹中

标签: java android-studio intellij-idea gradle jar


【解决方案1】:

我没有使用 Android Studio(或 Gradle)的经验,但我使用过 Java。你不是想设置主类吗?

因此我建议将Class-Path 属性更改为Main-Class,因为清单应该包含 Main-Class 以便能够在“运行”JAR 时调用某些东西。

【讨论】:

  • 这是作为答案发布的,但它不会尝试回答问题。它可能应该是编辑、评论、另一个问题或完全删除。
  • 恕我直言,如果您正确阅读了我的回复,您可以在那里看到一个建议,这可能会导致(或很可能是)答案。所以我会改写它并删除问号。
【解决方案2】:

首先,您要将所有运行时依赖项复制到 builddir/libs 文件夹(或其他分发文件夹,如果您愿意的话)。这是一个可以实现此目的的自定义任务:

task copyRTDependenciesToLib(type: Copy) {
    into "$buildDir/libs"
    from configurations.runtime
}

在清单文件中将运行时依赖项 jar 作为 Class-Path 属性添加。 jar 需要与您的可运行 jar 位于同一目录中 - 上面的复制任务实现了这一点。 (或者,您可以为依赖项 jar 位置提供完整的相对路径)

jar {
    manifest {
        attributes(
           "Main-Class": "com.Remo.server.RemoServerApp",
           "Class-Path": configurations.runtime.files.collect { it.getName() }.join(' '))
         )
    }
}

还有一些需要考虑的事情:

  • application 插件做同样的事情;它添加了一个任务installDist,该任务会生成一组可运行的 jar 以及您想要包含的任何依赖项、任何自述文件和文档。

  • 如果您想生成一个可运行的 jar 而不必捆绑依赖项,您应该考虑创建一个“fatjar”,例如:

    task fatJar(type: Jar) {
        manifest {
            attributes 'Implementation-Title': 'Gradle Jar File Example',  
                'Implementation-Version': version,
                'Main-Class': "com.Remo.server.RemoServerApp"
        }
        baseName = project.name
    
        //collect all dependencies
        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
        with jar
    }
    

【讨论】:

  • 这些子项目是否在父项目下?还是独立项目?
  • 在任何一种情况下,也因为可能存在其他外部依赖项,创建自定义复制任务将所有运行时依赖项复制到可运行 jar 项目的 build/lib 文件夹中可能是最简单的。
  • 您可能还希望将所有依赖 jar 收集到与可运行 jar 相同的文件夹中。对我的答案进行了更改以反映这一点。
  • 您在尝试执行 jar 之前是否运行了任务 copyRTDependenciesToLib
  • 刚刚又看到了你的项目结构,貌似复制路径应该是$buildDir/libs
猜你喜欢
  • 1970-01-01
  • 2015-02-09
  • 2020-05-18
  • 1970-01-01
  • 2013-05-13
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
相关资源
最近更新 更多