问题
Where I work we have a shell script that allow us to execute arbitrary Java classes with all the necessary libraries and settings, something like:
#!/bin/sh
$JAVA_HOME/bin/java -cp LONG_LIST_OF_JARS -Xmx6g -XX:MaxPermSize=128m "$@"
And used like so:
javacorp.sh com.mycorp.SomeJob
This is obviously better than needing to specify all the java
arguments explicitly every time, but I dislike that it's only manually connected to the jars configured in our Eclipse project for compiling the codebase. I'm working on a personal project and looking to similarly being able to execute arbitrary classes from the command line, and trying to identify how to best provide a consistent java
environment.
Currently I'm using Eclipse to run my applications, but I'd like to be able to run them from the command line directly, or on machines that don't have Eclipse installed. In particular, I'd also like to be able to limit the scope of classes/jars that can be executed. For example, javacorp.sh
lets us run anything in our src/
directory, and only javacorpunit.sh
includes classes in the tests/unit/
directory in the classpath.
- Is there a clean way to use Ant, Maven, or some other build tool to execute a configured
java
command at the command line, with minimal boilerplate? - Is there any way to hook into the
.classpath
file Eclipse creates? This doesn't wholly solve my problem (e.g. consistent memory settings) but it'd be nice to use data that already exists.
Edit:
Another way of phrasing my question would be "What's the cleanest way to replicate Eclipse's easy 'Run the current file's main method' button on the command line?"
回答1:
Have you considered generating the shell scripts from Ant? The <pathconvert> task can create a classpath from a <fileset>
.
You can create an Ant target for each kind of shell script you want. make
can then call these Ant targets to generate the shell scripts.
回答2:
I think the solution to your problem is to create an executable jar. Something that can be run as follows:
java -jar myapp.jar
"look ma, no classpath" :-)
The secret is add the "Main-Class" and "Class-Path" entries into the jar's manifest file. This tells java what to run and which jars should be loaded onto the classpath:
<jar destfile="${jar.file}" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="${jar.main.class}" />
<attribute name="Class-Path" value="${jar.classpath}" />
</manifest>
</jar>
To assist in creating the classpath, ANT has a really useful manifestclasspath task:
<manifestclasspath property="jar.classpath" jarfile="${jar.file}">
<classpath>
<fileset dir="${dist.dir}/lib" includes="*.jar"/>
</classpath>
</manifestclasspath>
So using this example, at run-time java will expect the depedencies to reside in a "lib" subdirectory (the task will generate relative links).
Eclipse integration is tricky. A better approach for managing your classpath is to use a dependency manager like ivy, which has an Eclipse plugin. In this way both ANT and Eclipse use the same mechanism for controlling build dependencies.
Finally for a complete working example take a look at:
- Class not found with Ant, Ivy and JUnit - error in build.xml?
Hope this helps.
回答3:
With Google's Bazel build system, you can easily define as many runnable Java programs as you want, with the java_binary target. You can define as many java_binary
targets as you'd like, and they can all depend on the same set (or overlapping sets) of java_library
targets so you don't need to manually curate the classpath of each binary.
Additionally, with a java_binary
target you can also generate a *_deploy.jar
file, which is a standalone executable Jar you can run anywhere.
来源:https://stackoverflow.com/questions/19442706/execute-java-programs-in-a-consistent-environment