在 Bash 脚本中覆盖 ClassPath 以运行 Java 应用程序。

huangapple go评论102阅读模式
英文:

Override ClassPath in Bash script to run Java application

问题

我正在尝试在Unix系统中运行一个简单的Java应用程序。我的Java应用程序会在运行时从目录中读取配置文件。我将这些文件放在/tmp/paddy/目录下。我创建了一个简单的bash脚本来运行这个应用程序。

我尝试了以下方式,但出现了**“no main manifest attribute, in app.jar”**错误:

#!/bin/bash    
java -cp ".:./config/*.*" -jar "app.jar" com.test.MainClass

然后我尝试了以下命令,这次我的应用程序运行起来了,但无法找到配置文件,因此抛出了NullPointerException错误 -(因为无法加载配置文件):

#!/bin/bash
java -cp app.jar com.test.MainClass

Java -cp命令中,覆盖类路径的正确方法是什么?我在互联网上搜索过,但没有找到令人满意的答案。我在Windows系统中没有任何问题。只有在Linux系统中出现问题,而我对Linux环境非常新手。

英文:

I am trying to run a simple Java application in Unix. My Java application read a config file from a directory at run-time. I placed the files in /tmp/paddy/. I created a simple bash script to run a application.

I tried like below and it gives me "no main manifest attribute, in app.jar" error

#!/bin/bash    
java -cp ".:./config/*.*" -jar "app.jar" com.test.MainClass

And tried with below command This time my application is running but couldnt find the aconfig file so it throw me NullPointerException - (since it couldnt load the config file)

#!/bin/bash
java -cp app.jar com.test.MainClass

What is the correct way to override classpath in Java -cp command ? I was searching over the internet, but couldnt get any good answers. I dont have any issues running in windows. Only in linux and I am pretty new to the linux environment.

答案1

得分: 3

你这里有四个不同的问题。

-jar 和 -cp 不能一起使用

如果你使用 -jar 开关,类路径会从JAR文件的清单(manifest)中的 Class-Path 条目获取,而且 只会执行这个 - -cp 开关(以及CLASSPATH环境变量)会被完全忽略。解决方案是修复你的JAR文件,它应该有那个类路径条目。

这不是 bash 的工作方式。

与那个问题分开,你的 -cp 参数有问题。

*.* 在... linux...?那是90年代末的DOS时代的写法,伙计!

是 Java 解析这个 *,这很独特,因为在 Linux 上通常是 bash 在做这个,但在这里不适用,因为 bash 会添加空格,而 Java 需要使用冒号/分号,这就是 Java 自己来处理的原因。重点是,Java 相当有限,只能理解一个 *。而 bash 会弄乱它。所以,只有一种方法来做。

  • 单引号。
  • 一个星号。

例如:

java -cp '.:./config/*' com.test.MainClass

你似乎不理解类路径是怎么工作的

类路径中的每个单独条目必须是:

  • 包含类文件的目录。
  • 一个 JAR 文件。

注意,它明确不能是“包含 JAR 文件的目录”,也不能是“一个类文件”;这不是一个有效的情况。通常对待的是 *:它会将你使用 /* 填充的目录中的每个文件都视为类路径的一部分。

因此,如果你写:java -cp .,那不会包括 app.jar。如果你写 java -cp './config/*',那不会包括位于 ./config 下的任何类或配置文件(只包括位于那里的 JAR 文件)。

这不是配置文件的使用方式

将配置文件包含在类路径中不是正确的做法。当然你可以这么做。但这实际上没有任何作用,除非你在使用 SomeClass.class.getResource 或其他 getResource 的变种(这些方法不太好,你应该使用 SomeClass.class.getResourceSomeClass.class.getResourceAsStream,但我偏离了主题),如果是这样,不要这么做。这些方法并不适用于配置文件,而适用于静态文件(永不改变的文件,比如你的 Swing 用户界面应用的“保存到云端”图标)。如果你在做那种事情,你需要在类路径中包含 ./config(而不是 './config/*'),但更好的做法是修复你的代码。

配置文件应该位于用户的主目录下 - System.getProperty("user.home")。你应该将包含 JAR 文件的目录视为可执行文件所在的地方,而这些文件不一定可以由用户编辑,当然配置文件的意义在于你可以编辑它们。因此,使用类路径来处理配置文件不是正确的方法。

英文:

You have four separate issues here.

-jar and -cp don't work together

If you use the -jar switch, the classpath is taken from the Class-Path manifest entry in the jar's manifest, and that is all that will happen - the -cp switch (and the CLASSPATH environment variable) are completely ignored. The solution is to fix your jarfile, which ought to have that classpath entry.

That's not how bash works.

Separate from that issue, your -cp parameter is broken.

*.* in.. linux...? That's late 90s DOS, mate!

It's java doing the parsing of that *, which is unique, because in linux it's normally bash doing it, but that doesn't work here, because bash will be adding spaces, and java needs colons/semicolons, which is why java does it itself. The point is, java is rather limited and only understands a single *. Which bash will mess up. So, there is really only one way to do this.

  • Single quotes.
  • One star.

For example:

java -cp '.:./config/*' com.test.MainClass

You don't seem to understand how classpaths work

Each individual entry in a classpath must be either:

  • A directory which contains classfiles.
  • A jar file

Note how it specifically cannot be 'a directory that contains jar files', and also cannot be 'a class file'; that is not a thing. The * is the usual treatment: It takes every file in the directory you padded with /* and considers them all to be part of the classpath.

So, if you write: java -cp ., that will not include app.jar. If you write java -cp './config/*', that will not include any class or config files hanging off of ./config (only jar files located there).

That's not how config files work

Including config files on the classpath is not how its done. You can, of course. This doesn't do anything whatsoever, unless you are using SomeClass.class.getResource or some other variant of getResource (those are no good, you should be using SomeClass.class.getResource or SomeClass.class.getResourceAsStream, but I digress), in which case, don't do that. Those aren't intended for config files, those are for static files (files that never change, such as, say, a 'save to cloud' icon for your swing user interface application). If you are doing that, you'd need to include ./config (and not './config/*') in your classpath, but it would be a better idea to fix your code.

config files should be in the user's home directory - System.getProperty("user.home"). You should consider the directory that contains the jar file(s) as the place where the executables live, and those are not necessarily editable by the user, and surely the point of a config file is that you can edit them. Hence why using the classpath for these is not how it is done.

huangapple
  • 本文由 发表于 2020年9月14日 15:21:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63879756.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定