【问题标题】:Shorten classpath (-cp) for command line缩短命令行的类路径 (-cp)
【发布时间】:2019-08-03 01:22:45
【问题描述】:

我的 maven 构建在 jdeps 插件上失败(我们需要它升级到 jdk11)。

命令行对于 Windows 来说太长了。 这是我得到的错误:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jdeps-plugin:3.1.1:jdkinternals (default) on project myproject:
[ERROR] Exit code: 1 - La ligne de commande est trop longue.
[ERROR]
[ERROR] Command line was: cmd.exe /X /C 
"
    "C:\Program Files\Java\jdk-11.0.2\bin\jdeps.exe"
    -cp "
        C:\Users\Me\.m2\repository\com\something\firstJar.jar;
        C:\Users\Me\.m2\repository\com\somethingElse\secondJar.jar;
        C:\Users\Me\.m2\repository\com\somethingDifferent\someOtherJar.jar;
        ... and one more
        ... and another one
        ... I think you get the idea......."
    --multi-release 9 D:\git\myworkspace\myproject\target\classes
"

例如,我只放了 3 个罐子,但我有很多依赖项......

如何缩短此命令行?(并确保它不依赖于用户)

限制:这是一个共享项目,仅在我的计算机上更改任何内容都不是解决方案。

【问题讨论】:

标签: java maven command-line classpath manifest.mf


【解决方案1】:

maven-jdeps-plugin 正在使用 plexus-utils 派生出一个子进程来运行 jdeps 可执行文件。 plexus-utils 通过构建命令行并将其传递给 cmd.exe 来实现这一点。这是错误的方法,因为它将受到 cmd.exe 施加的 8192 字符限制。正确的方法是使用 Java ProcessBuilder API。这本身使用 ProcessImpl.create API 方法,在 Windows 上,该方法是通过对 CreateProcess 的 Win32 API 调用实现的。后一个 API 有 32k 字符的限制,对于大多数用例来说应该足够了。

为此有一个 plexus-utils bug report。您可能还想使用 maven-jdeps-plugin 来提升一个 - Java ProcessBuilder API 非常有用,因此无需使用 plexus-utils 来运行 jdeps。

【讨论】:

  • 感谢您的回答。不幸的是,在我的情况下这还不够,我克隆了 jdeps 存储库并将其修改为使用 ProcessBuilder API 而不是 plexus-utils 但我仍然遇到同样的错误。
  • @Fundhor 你的意思是你修改了 maven-jdeps-plugin 吗?您确定您的构建使用的是您的插件构建,而不是仍在使用原始版本吗?
  • @Fundhor 你能贴出一些你使用 ProcessBuilder API 的代码吗?
  • 作为记录,@jon-hanson 是对的,我没有正确进行更改。这是正确的解决方案。
【解决方案2】:

如果您使用的是 Windows 10 周年更新或 Windows Server 2016 或更高版本,您可以将最大路径长度增加到超过 260 个字符的默认值。

您可以将以下两行复制到具有.reg 扩展名的文件中并打开它,

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001

或者,打开注册表编辑器并浏览到该位置,然后将值从 0 更改为 1。

【讨论】:

  • 感谢Strom,这是一种绕过限制的方法,但它是用于共享项目,我不能要求所有人更改其注册。
【解决方案3】:

最好的方法是创建 empty jar 文件,并在清单中配置类路径。

oracle 官方文档在Adding Classes to the JAR File's Classpath

maven-jar 插件确实支持更新清单类路径属性:How to add Class-Path to the manifest file with maven

【讨论】:

    【解决方案4】:

    也许有点厚颜无耻,但是……

    使用环境变量怎么样?

    set MR=C:\Users\Me\.m2\repository\
    
    "C:\Program Files\Java\jdk-11.0.2\bin\jdeps.exe"
        -cp "
            %MR%\com\something\firstJar.jar;
            %MR%\com\somethingElse\secondJar.jar;
    

    没有测试,希望它有效...

    【讨论】:

      【解决方案5】:

      这就是 Maven 旨在管理大量依赖项的原因,因为您可以简单地将它们全部放在 .pom 文件中。集中依赖列表的使用使 Maven 能够查看运行程序所需的几乎所有内容。看看这篇文章,它做了你正在尝试的事情,尽管添加了你的每个 jar 以供 Maven 看到它们。 How do I package and run a simple command-line application with dependencies using maven?

      另外,一个很好的 .pom 基础指南 阅读 www.maven.apache.org 上的 pom 指南。

      由于 Manifest 规范,Maven 不会按照您尝试的方式使用 cmdline 参数。这就是包括我自己在内的程序员喜欢 Maven 的根本原因,因此它确实可以让生活变得更加简单,因为它完全可以满足您的需求。随着文件的变化,您有一个文件来制作您的更新版本。

      【讨论】:

        【解决方案6】:

        所以我确实为这个问题苦苦挣扎了很长时间,最后在进行 maven 构建时找到了解决这个问题的方法,即类路径太长。 这是一种解决方法,但效果很好。

        从 linux 运行构建 - 这不是开玩笑(原文如此!)

        • 在 Windows 上打开 WSL(适用于 Linux 的 Windows 子系统),如下所示 https://docs.microsoft.com/en-us/windows/wsl/install-win10
        • 完成后,只需在 Windows 上运行您的 Linux 子系统
        • 编辑 linux maven settings.xml /usr/share/maven/conf/settings.xml
        • 添加或覆盖<localRepository>/mnt/c/.m2</localRepository> (/mnt/c/.m2) - 是从 WSL 看到的我的 windows maven repo 路径
        • cd /path/to/your/project
        • mvn 构建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-27
          • 1970-01-01
          • 2018-09-22
          相关资源
          最近更新 更多