I have my java source files in src/net/... folders and .jar files in lib folder. How to compile and run this files with command line without writing build script ?
Lets say you have your code files in
[someDirectory]
|
+-[lib]
| |
| +-someLib.jar
| +-someOtherLib.jar
| +-...
|
+--[src]
|
+-[net]
|
+-[name]
|
+-[one]
|
+-[two]
|
+-[main]
|
+-Main.java <- code you want to compile
and execute
then if your console is in
someDirectory>
you can compile it with
someDirectory>javac -cp "lib\*" src\net\name\one\two\main\Main.java
but this will produce Main.class file in same directory as Main.java so to execute code from net.name.one.two.main.Main class you would need to include src directory to classPath because this directory contains package that Main class is placed, so you would need to use command
someDirectory>java -cp "src;lib\*" net.name.one.two.main.Main
But it is good practice to separate class files from source files. To do this you can add -d (directory) parameter while compiling pass directory which should have compiled class files. So first create your classes directory at the same level as src directory and execute
someDirectory>javac -d "classes" -cp "lib\*" src\net\name\one\two\main\Main.java
and now to be able to execute your Main class instead creating confusion by src directory to classPath you will have to add classes directory which is more intuitive.
someDirectory>java -cp "classes;lib\*" net.name.one.two.main.Main.java
Try this
javac -cp .;lib/lib1.jar;lib/lib2.jar src/net/*.java
lib1 and lib2 are your libraries. It assume your libraries are in lib folder. You may also need to change the destination folder for .class files.
To run the application use
java -cp bin;lib/lib1.jar;lib/lib2.jar net.mypackage.MyMainclass
net...
It assume your .class files are in bin folder.
Related
I am working on a Java project that contains many properties files and the structure looks like this:
src
|
-main
|
-java
|
-ui
|
-many directories with property file in each directory.
I want to build fat jar using Gradle build that will contain those files in the same directories.
Something like:
build
|
-classes
|
-java
|
-main
|
-ui.... and all the files like above.
How can I to do it?
By convention gradle will package all the properties (and other resource) files placed under src/main/resources into the final jar artifact.
If you are sure that you still want to place your properties file under src/main/java then you can configure resources source sets location using the following snippet in your build.gradle
sourceSets {
main {
resources {
srcDirs = ["src/main/java"]
include "**/*.properties"
}
}
}
The properties files will not end up in build/classes but will be part of you jar. You you want them to be build/classes/java as well (not recommended), then you need to configure the output dir for resources as well. See this answer.
I have a program written in java using Eclipse. For some reason that I won't write here, I decided to move to VS Code. If I run my code in debug mode, all works, but, when I want to export as jar file some errors comes out.
Some information:
- The program is composed by several classes.
- I use 3 external jars included via Eclipse.
- If I run the code with the extension 'Java extension pack - microsoft' all works. Compiling via terminal with
javac MyApp.java
it doesn't compile. (It doesn't find some classes belonging to external jars)
- If I use
jar -cvfm MyApp.jar manifest.txt *.class
where *.class are created by compiling via 'Java extension pack' the error is 'Unable to find or load the main class'
- I'm using a MacBook Pro and the last version of VS Code
What do I do wrong? Which more information you need to help me?
Let's say your project has app package. Under that a App.java class resides which has the main method. Now after building the class files let's assume the class file folder structure is
bin
|app
|App.class
Now go to the bin folder and copy the manifest.txt file in bin folder. manifest.txt file must contain Main-Class . here app.App is the name of the Main-Class.
Main-Class: app.App
Note manifest.txt file must be ended with a new line or carriage return . After Main-Class: app.App put a new line at least.Now run this command from the bin folder
jar cfmv App.jar manifest.txt app/
then test the Jar with
java -jar App.jar
First of all I want to say that I do not want to use Maven, Ant, Gradle, any IDE or similar for this task.
I want to make a runnable jar using a bash script. The jar should includes all jar-content from my "libs" folder.
I have started this script and it "almost" works(until the jar creattion):
#!/bin/bash
#Setup
libs=$(find libs -name "*.jar" -print0 | xargs -0 | sed -e 's/ /:/g')
tmp2=$(sed -e 's/:/\n ..\//g' <<< $libs)
tmp2=../$tmp2
libs=$libs:src
mkdir tmp
#Compile
javac -d tmp -classpath "$libs" src/main/PublishData.java
#Create manifest
cd tmp
echo "Main-Class: main.PublishData" >> m.mf
echo "Class-Path: $tmp2" >> m.mf
#Build jar
jar cvfm thejar.jar m.mf *
An m.mf example file would look like this:
Main-Class: MyMain
Class-Path: ../libs/1.jar
../libs/2.jar
The file structure looks like this:
├── src
├── tmp (created by the script, jar cvfm thejar.jar m.mf * is run here)
├── libs
│ ├── jar1
│ ├── jar2
The jar file is created and can be executed but the referenced jars are not found.
(E.g: Exception in thread "main" java.lang.NoClassDefFoundError: com/mongodb/MongoClient
)
It seams to me like the jar program could not find the jars.
How can I successfully "include" my jars from the libs dir?
UPDATE:
Every line in the "Class-Path:" section of a manifest file needs to start and end with a white space this caused the class-path to break.
Your approach looks good in general.
Relative paths work in the manifest but you need to make sure that the paths are available at runtime. So if you say "load ../libs/foo.jar", then for the classloading to work, you need to be in the src/, tmp/ or libs/ when you start the application.
The main problem is that Java silently ignores JARs which it can't find. I hesitate to call this a feature, especially since so many people run into problems starting a Java application. So you will have to painstakingly find out what works and what doesn't.
To make things more simple, I suggest that you JAR all the classes of your project as well and then create a pure "classpath" JAR (i.e. no classes, just a manifest file with the classpath + the main class). That way, all your dependencies work the same.
Another thing you should try is to write a small project (just the hello world kind) where you can test your "create manifest JAR" script.
That said, my approach is to create a main class which accepts a path as arguments (the absolute path to the libs folder). It then lists all the JAR files in the folder (plus some debug output so I can see what it finds) and creates a new URLClassLoader with those URLs. That way, I can debug classpath issues easily plus my "start" script work like this:
BASE=$(cd $( dirname "$0" ) > /dev/null ; pwd )
java -jar $BASE/starter.jar $BASE/libs
I've always used an IDE when working with Java so my knowledge on the javac command isn't that great. I want to know this: Does java generate the directories where the .class files should be placed in as specified in the .java files package declarations? Let me clarify, say you have a simple .java file like this on your Desktop:
package com.deangrobler.test
public class Test {
// ...
}
When running the following from your Desktop:
javac Test.java
Will it then automatically go and create the com/deangrobler/test directories and place the Test.class file therein?
From the docs --> http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html
See the option section.
-d directory
Set the destination directory for class files. The directory must already exist; javac will not create it. If a class is part of a package, javac puts the class file in a subdirectory reflecting the package name, creating directories as needed. For example, if you specify -d C:\myclasses and the class is called com.mypackage.MyClass, then the class file is called C:\myclasses\com\mypackage\MyClass.class.
If -d is not specified, javac puts each class files in the same directory as the source file from which it was generated.
Note: The directory specified by -d is not automatically added to your user class path.
Will it then automatically go and create the com/deangrobler/test
directories and place the Test.class file therein?
No. Even if you can use -d to specify where you want to place your class file created after compilation but java won't create package structure for you.
So,Unless you specify the -d option the compiler places each class file in the same directory as the corresponding source file was located.
Even if you have specified package name but you hadn't created that structure don't expect that from javac all the things you have to do manually.
For Example:
javac -d C:/tempFolder MyProgram.java//Will place .class file in to C:/tempFolder
//Only if C:/tempFolder is available
com
|
|---deangrobler
|
|-------test
|
|---Test.class//Places class file here after compilation
//Default place
If we use below command , it will create package structure from current directory.
javac -d . YourClassName.java
If we want to put your class files and its packages some other folder, use below command.
javac -d "d:/java_eg/" YourClassName.java
it will create package directories and class files inside java_eg folder inside the D drive.
I'm a beginner in java and this is not actually a program question, but I would like to get some advice from you guys on how to get the number of files in a .jar java file? Is there any metric tools that I can use for this (consider its a .jar file)?
As .jar files are just .zip files, you can use the same tools to work with them. On *nix, if you want to list all of the files in a JAR:
$ unzip -l filename.jar
Will produce output similar to the following:
Archive: filename.jar
Length Date Time Name
-------- ---- ---- ----
1211 03-03-14 13:06 bar/foo/swing/window/FrameOperatorFactory.class
2344 03-03-14 13:06 bar/foo/swing/window/FrameOperator.class
1509 06-30-07 14:03 LICENSE.txt
-------- -------
5184390 3 files
(The above output is only an example.)
If you want just *.class files:
$ unzip -l filename.jar | grep \.class | wc -l
If you want more control, you're likely better off just unzipping it and working with the files that way.
You should just be able to use a zip tool (with caveats, see below) or jar. From wikipedia:
In software, JAR (Java ARchive) is a package file format typically used to aggregate many Java class files and associated metadata and resources (text, images, etc.) into one file to distribute application software or libraries on the Java platform.[3]
JAR files are fundamental archive files, built on the ZIP file format and have the .jar file extension. Computer users can create or extract JAR files using the jar command that comes with a JDK. They can also use zip tools to do so; however, the order of entries in the zip file headers is important when compressing, as the manifest often needs to be first. Inside a JAR, file names are unicode text.[4]
You can use following command for find the number of class in specific jar file
jar tvf {jar location with jar name} | grep .class | wc -l
For Example :
jar tvf launcher/target/user.jar | grep .class | wc -l