Write a batch file that starts a java program - java

So I have a java project with multiple java files.
I know that is almost straight forward to start a java application using batch file. But that is for a pretty simple java program with a single class.
However I am wondering if it is possible to do that with in a scale of a project that you usually create using eclipse. A large project with multiple packages, classes and multiple java files.
My try was to write a script and apply on the main class as following
set path = C:\Program Files\Java\jdk1.7.0_25\bin
javac -classpath twitter/twitter4j-stream-3.0.5.jar;twitter4j-core-3.0.5.jar" sourcepath="lib/twitter4j-core-4.0.1.jar;lib/twitter4j-core-4.0.1.jar;lib/twitter4j-stream-4.0.1.jar;svm_light_lib Program.java
java Program
However when I start the .bat file it automatically closes.
Any Ideas ?
Thanks in advance

First, never overwrite the environment variable path, not even
temporarily. Append your folder instead: set "path=%path%;%mypath%" or set "path=%mypath%;%path%".
(There exists a particular path command but I'm not sure about right syntax: path=%path%;%mypath% with = assignment or path %path%;%mypath% without it).
Use full path to a program if you know it, e.g. "%mypath%\javac".
For better readability, values for -classpath and -sourcepath options are stored to the environment variables mycpth and mysrcp, respectively. Note and use proper " quotation and no spacing around = to avoid any leading and trailing spaces in all set commands.
pause to see all the javac output. Displays the message Press any key to continue . . .
Next code should be (syntax) error-free. However, success depends (among others) on classpath and sourcepath entries visibility as well...
set "mypath=C:\Program Files\Java\jdk1.7.0_25\bin"
set "path=%path%;%mypath%"
set "mycpth=twitter/twitter4j-stream-3.0.5.jar;twitter4j-core-3.0.5.jar"
set "mysrcp=lib/twitter4j-core-4.0.1.jar;lib/twitter4j-core-4.0.1.jar;lib/twitter4j-stream-4.0.1.jar;svm_light_lib"
"%mypath%\javac" -classpath "%mycpth%" -sourcepath "%mysrcp%" Program.java
pause
java Program

However I am wondering if it is possible to do that with in a scale of a project that you usually create using eclipse. A large project with multiple packages, classes and multiple java files.
Of course it is possible!
In this case, I suspect the problem is that you java command doesn't have a "-cp" argument. The java command is probably failing because it can't find twitter classes ... at runtime.
Remember to include "." on the classpath ... or else java won't find the file that you just compiled.
#JB Nizet's suggestion is also very important advice for finding out what is actually happening.

Related

How to compile with a bash script a multipackaged java project that uses jar file

I am developing a project for my Computer Network course.
Actually I ended it, now I need to write a script to compile it, so the teacher will be able to run it
I developed with Netbeans and now I am struggling to compile it by command line.
I have 3 folders (packages)
client: classes of the client process
server: classes of the server process
sharedClasses: classes usefull to both client and server (like User.java)
Also I am using the Gson as a jar file which is needed in the sharedClasses package
for example in sharedClasses there is a class called Message that uses Gson to be transformed in a json string
I tried a lot to create a script that compile it all but every time I get "ClassNotFoundException" or stuff like that: the online guides to understand classpath and so on are pretty bad.
Can someone tell me how to do my script and explain why things are done the way they are? Thanks
Path variables are a concept in all Unix and Windows operating systems. They are not a Java invention, but Java bases its own classpath and module path concepts on them.
A path variable’s value is simply a string which contains a list of file locations, separated by a colon (:) in Unix or a semicolon (;) in Windows.
The most common path variable is simply PATH. (I believe that in Windows, the variable’s canonical name is Path, but environment variables are case-insensitive in Windows, so it can be referred to as PATH in most cases.)
When you try to execute a program on the command line, by specifying a command name with no directory components, the operating system checks each file location in PATH, in order, and for each location which is a directory, the system will look for a match there. The first match is the one the operating system uses.
Java borrows this concept for the classpath. In the very early days of Java, it was exactly the same: If your classpath were /home/giulio:/opt/libraries, and you were looking for a class named com.example.ConnectionFactory, Java would look for a compiled file named com/example/ConnectionFactory.class in /home/giulio and then in /opt/libraries.
It wasn’t long before the classpath was allowed to contain files which are compressed archives of classes, in addition to directories. Your classpath might contain /home/giulio:/opt/libraries/foolib.jar, in which case Java would first check for a requested class in /home/giulio, since that is a directory, and if that failed, it would look for a matching entry in the /opt/libraries/foolib.jar archive file. (Zip files are also acceptable, and in fact a .jar file is really just a zip file with a few special Java-specific entries.)
So, when you want to tell Java to look in certain places for libraries, specify them in the classpath.
For instance, when compiling your client code:
projectroot=`dirname "$0"`
javac -classpath "$projectroot"/sharedClasses/classes \
-d "$projectroot"/client/classes \
"$projectroot"/client/src/*.java
When you run your code:
java -classpath "$projectroot"/sharedClasses/classes:"$projectroot"/client/classes \
edu.acme.giulio.client.Main

How to debug error "NoClassDefFoundError caused by ClassNotFound Exception" coming at runtime? [duplicate]

I was just reading this line:
The first thing the format() method does is load a Velocity template from the classpath named output.vm
Please explain what was meant by classpath in this context, and how I should set the classpath.
When programming in Java, you make other classes available to the class you are writing by putting something like this at the top of your source file:
import org.javaguy.coolframework.MyClass;
Or sometimes you 'bulk import' stuff by saying:
import org.javaguy.coolframework.*;
So later in your program when you say:
MyClass mine = new MyClass();
The Java Virtual Machine will know where to find your compiled class.
It would be impractical to have the VM look through every folder on your machine, so you have to provide the VM a list of places to look. This is done by putting folder and jar files on your classpath.
Before we talk about how the classpath is set, let's talk about .class files, packages, and .jar files.
First, let's suppose that MyClass is something you built as part of your project, and it is in a directory in your project called output. The .class file would be at output/org/javaguy/coolframework/MyClass.class (along with every other file in that package). In order to get to that file, your path would simply need to contain the folder 'output', not the whole package structure, since your import statement provides all that information to the VM.
Now let's suppose that you bundle CoolFramework up into a .jar file, and put that CoolFramework.jar into a lib directory in your project. You would now need to put lib/CoolFramework.jar into your classpath. The VM will look inside the jar file for the org/javaguy/coolframework part, and find your class.
So, classpaths contain:
JAR files, and
Paths to the top of package hierarchies.
How do you set your classpath?
The first way everyone seems to learn is with environment variables. On a unix machine, you can say something like:
export CLASSPATH=/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output/
On a Windows machine you have to go to your environment settings and either add or modify the value that is already there.
The second way is to use the -cp parameter when starting Java, like this:
java -cp "/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output/" MyMainClass
A variant of this is the third way which is often done with a .sh or .bat file that calculates the classpath and passes it to Java via the -cp parameter.
There is a "gotcha" with all of the above. On most systems (Linux, Mac OS, UNIX, etc) the colon character (':') is the classpath separator. In windowsm the separator is the semicolon (';')
So what's the best way to do it?
Setting stuff globally via environment variables is bad, generally for the same kinds of reasons that global variables are bad. You change the CLASSPATH environment variable so one program works, and you end up breaking another program.
The -cp is the way to go. I generally make sure my CLASSPATH environment variable is an empty string where I develop, whenever possible, so that I avoid global classpath issues (some tools aren't happy when the global classpath is empty though - I know of two common, mega-thousand dollar licensed J2EE and Java servers that have this kind of issue with their command-line tools).
Think of it as Java's answer to the PATH environment variable - OSes search for EXEs on the PATH, Java searches for classes and packages on the classpath.
The classpath is one of the fundamental concepts in the Java world and it's often misunderstood or not understood at all by java programmes, especially beginners.
Simply put, the classpath is just a set of paths where the java compiler and the JVM must find needed classes to compile or execute other classes.
Let's start with an example, suppose we have a Main.java file thats under C:\Users\HP\Desktop\org\example,
package org.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
And Now, suppose we are under C:\ directory and we want to compile our class, Its easy right, just run:
javac .\Users\HP\Desktop\org\example\Main.java
Now for the hard question, we are in the same folder C:\ and we want to run the compiled class.
Despite of what you might think of to be the answer, the right one is:
java -cp .\Users\HP\Desktop org.example.Main
I'll explain why, first of all, the name of the class that we want ro tun is org.exmaple.Main not Main, or Main.class or .\users\hp\desktop\org\example\Main.class ! This is how things works with classes declared under packages.
Now, we provided the name of the class to the JVM (java command in this case), But how it (JVM) will know where to find the .class file for the Main class? Thats where the classpath comes into picture. Using -cp flag (shortcut for -classpath), we tell the JVM that our Main.class file will be located at C:\users\hp\Desktop.. In fact, not really, we tell it to just go to the Desktop directory, and, because of the name of the class org.example.Main, the JVM is smart and it will go from Desktop to org directory, and from org to example directory, searching for Main.class file, and it will find it and it will kill it, I mean, it will run it :D .
Now lets suppose that inside the Main class we want to work with another class named org.apache.commons.lang3.StringUtils and the latter is located in a jar file named commons-lang3-3.10.jar thats inside C:\Users\HP\Downloads. So Main.java will look like this now:
package org.example;
import org.apache.commons.lang3.StringUtils;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
System.out.println(StringUtils.equals("java", "java")); //true
}
}
How to compile the Main.java if we are always inside C:\ ? The answer is:
javac -cp .\Users\HP\Downloads\commons-lang3-3.10.jar .\Users\HP\Desktop\org\example\Main.java
.\Users\HP\Desktop\org\example\Main.java is because our .java file is there in the filesystem.
-cp .\Users\HP\Downloads\commons-lang3-3.10.jar is because the java compiler (javac in this case) need to know the location of the class org.apache.commons.lang3.StringUtils, so we provided the path of the jar file, and the compiler will then go inside the jar file and try to find a file StringUtils.class inside a directory org\apache\commons\lang3.
And if we want to run the Main.class file, we will execute:
java -cp ".\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar" org.example.Main
org.example.Main is the name of the class.
".\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar" are the paths (separated by ; in Windows) to the Main and StringUtils classes.
The classpath is the path where the Java Virtual Machine look for user-defined classes, packages and resources in Java programs.
In this context, the format() method load a template file from this path.
The classpath in this context is exactly what it is in the general context: anywhere the VM knows it can find classes to be loaded, and resources as well (such as output.vm in your case).
I'd understand Velocity expects to find a file named output.vm anywhere in "no package". This can be a JAR, regular folder, ... The root of any of the locations in the application's classpath.
Setting the CLASSPATH System Variable
To display the current CLASSPATH variable, use these commands in Windows and UNIX (Bourne shell):
In Windows: C:\> set CLASSPATH
In UNIX: % echo $CLASSPATH
To delete the current contents of the CLASSPATH variable, use these commands:
In Windows: C:\> set CLASSPATH=
In UNIX: % unset CLASSPATH; export CLASSPATH
To set the CLASSPATH variable, use these commands (for example):
In Windows: C:\> set CLASSPATH=C:\users\george\java\classes
In UNIX: % CLASSPATH=/home/george/java/classes; export CLASSPATH
Classpath is an environment variable of system. The setting of this variable is used to provide the root of any package hierarchy to java compiler.
CLASSPATH is an environment variable (i.e., global variables of the operating system available to all the processes) needed for the Java compiler and runtime to locate the Java packages used in a Java program. (Why not call PACKAGEPATH?) This is similar to another environment variable PATH, which is used by the CMD shell to find the executable programs.
CLASSPATH can be set in one of the following ways:
CLASSPATH can be set permanently in the environment: In Windows, choose control panel ⇒ System ⇒ Advanced ⇒ Environment Variables ⇒ choose "System Variables" (for all the users) or "User Variables" (only the currently login user) ⇒ choose "Edit" (if CLASSPATH already exists) or "New" ⇒ Enter "CLASSPATH" as the variable name ⇒ Enter the required directories and JAR files (separated by semicolons) as the value (e.g., ".;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar"). Take note that you need to include the current working directory (denoted by '.') in the CLASSPATH.
To check the current setting of the CLASSPATH, issue the following command:
> SET CLASSPATH
CLASSPATH can be set temporarily for that particular CMD shell session by issuing the following command:
> SET CLASSPATH=.;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar
Instead of using the CLASSPATH environment variable, you can also use the command-line option -classpath or -cp of the javac and java commands, for example,
> java –classpath c:\javaproject\classes com.abc.project1.subproject2.MyClass3
For linux users, and to sum up and add to what others have said here, you should know the following:
$CLASSPATH is what Java uses to look through multiple directories to find all the different classes it needs for your script (unless you explicitly tell it otherwise with the -cp override). Using -cp requires that you keep track of all the directories manually and copy-paste that line every time you run the program (not preferable IMO).
The colon (":") character separates the different directories. There is only one $CLASSPATH and it has all the directories in it. So, when you run "export CLASSPATH=...." you want to include the current value "$CLASSPATH" in order to append to it. For example:
export CLASSPATH=.
export CLASSPATH=$CLASSPATH:/usr/share/java/mysql-connector-java-5.1.12.jar
In the first line above, you start CLASSPATH out with just a simple 'dot' which is the path to your current working directory. With that, whenever you run java it will look in the current working directory (the one you're in) for classes. In the second line above, $CLASSPATH grabs the value that you previously entered (.) and appends the path to a mysql dirver. Now, java will look for the driver AND for your classes.
echo $CLASSPATH
is super handy, and what it returns should read like a colon-separated list of all the directories, and .jar files, you want java looking in for the classes it needs.
Tomcat does not use CLASSPATH. Read what to do about that here: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html
Static member of a class can be called directly without creating object instance.
Since the main method is static Java virtual Machine can call it without creating any instance of a class which contains the main method, which is start point of program.

How many Classpath can be specified on Java command line?

I have to run a java task, with a very large number of classpath (1000, totaling 150k characters if concatenated).
The problem is that java returns an error when I try to execute this class:
/jdk/JAVA8/bin/java: Argument list too long
The error code is 7
I've tried to put the classpaths using "export CLASSPATH=CLASSPATH:....." and so I shouldn't specify them through the -cp java parameter, but it returned the same error.
I'm pretty sure that the problem revolves round a classpath's limit, because if I delete some of the classpath, the error disappears (but then I will have logical errors in the execution, because I need all the classpaths)
You could use classpath wildcards. Especially if many of your jars/class files are in the same directory, this would help a lot.
It could be environment variable size limit or command-line size limit as well rather than javac classpath arg limit.
javac takes arguments from file input as well. You can add all your arguments to this file and pass this file argument to command. Refer this for more.
You didn’t hit a java-specific limitation, but a system dependent limit. This is best illustrated by the fact, that the attempt to set the CLASSPATH variable fails as well, but setting an environment variable via export name=value in the shell isn’t related to Java.
As said by others, you could try to use wildcards for jar files within the same directory, but you have to care that Java does the expansion rather than the shell, as in the latter case, it would again yield a too long command line. So you have to escape the * character to ensure it will not be processed by the shell.
javac supports reading the command line arguments from an external file specified via #filename, but unfortunately, the java launcher doesn’t support this option.
An alternative would be to create symbolic links pointing to the jar files, having shorter paths and specifying these. You could even combine the approaches by creating one directory full of symbolic links and specifying that/directory/* as class path.
But there seems to be a logical error in the requirement. In a comment, you are mentioning “code analysis” and an analyzing tool should not require having the code to analyze in its own application class path. You can access class files via ordinary I/O, if you want to read and parse them. In case you want to load them, e.g. for using the builtin Reflection, you can create new ClassLoader instances pointing to the locations. So the tool doesn’t depend on the application class path and could read the locations from a configuration file, for example.
Using distinct class loaders has the additional advantage that you can close them when you’re done.
JVM does not limit classpath length. However, there is a hard OS limit on command line length and environment variables size.
On Linux check getconf ARG_MAX to see the limit.
On older kernel versions it is only 128KB. On newer kernels it is somewhere around 2MB.
If you want to set really long classpaths, you may need a JAR-Manifest trick. See this question for details.

Running a java program, having external jar dependency in a batch file

I tried googling a lot but couldnt get a proper working solution ..
directory consists of all java files and external jarfile(google.guava.jar).. i want to execute it in a batch file.. i have tried a lot of things...but still says deffclasserror.. can anyone help me out on how to make it work...(Windows)..
Structure looks like this:
Folder
--------jar file
--------java file
--------bat file
set path="C:\Program Files (x86)\Java\jdk1.8.0_73\bin"
javac -cp google.guava.jar convertohash
javac FinalOutput.java
java convertohash
java FinalOutput
pause
Try this:
"C:\Program Files (x86)\Java\jdk1.8.0_73\bin\java" -cp %YOUR_CLASSPATH%;%YOUR_CLASSPATH_REPORTS%;%EXTRA_LIB% -Djava.library.path=./dll your.main.class
Before this line you need to set up your YOUR_CLASSPATH your YOUR_CLASSPATH_REPORTS and EXTRA_LIB with = and separating the concurrences with ";" (without the ""). For example:
SET EXTRA_LIB=.\lib\mysql-connector-java.jar;.\lib\anotherlibrary.jar; etc
Being the "lib" folder the one were you store your libraries, the route doesn't stricly needs to be the one shown on the example just put the one were you store your libraries (if you are using some ofc).
Also keep in mind that if you are going to use this bat in several machines they must have the same jdk installed and on the same route specified or you'll need to change it manually because the application wont launch.

How do I run .class files on windows from command line?

I'm trying to run .class file from command line. It works when I manually move to the directory it's stored in, but when I try something like this:
java C:\Peter\Michael\Lazarus\Main
it says it can't find the main class. Is there any solution to this other than making a .jar file (I know that .jar is the best solution, but at this moment isn't the one I'm looking for)?
The Java application launcher (a.k.a java.exe or simply java) supports up to four different ways to specify what to launch (depending on which Java version you use).
Specifying a class name is the most basic way. Note that the class name is different from the file name.
java -cp path/to/classFiles/ mypackage.Main
Here we start the class mypackage.Main and use the -cp switch to specify the classpath which is used to find the class (the full path to the class mypackage.Main will be path/to/classFiles/mypackage/Main.class.
Starting a jar file.
java -jar myJar.jar
This puts the jar itself and anything specified on its Class-Path entry on the class path and starts the class indicated via the Main-Class entry. Note that in this case you can not specify any additional class path entries (they will be silently ignored).
Java 9 introduced modules and with that it introduce a way to launch a specific module in a way similar to how option #2 works (either by starting that modules dedicated main class or by starting a user-specified class within that module):
java --module my.module
Java 11 introduces support for Single-File Source Code Programs, which makes it very easy to execute Java programs that fit into a single source file. It even does the compile step for you:
java MyMain.java
This option can be useful for experimenting with Java for the first time, but quickly reaches its limits as it will not allow you to access classes that are defined in another source file (unless you compile them separately and put them on the classpath, which defeats the ease of use of this method and means you should probably switch back to option #1 in that case).
This feature was developed as JEP 330 and is still sometimes referred to as such.
For your specific case you'd use option #1 and tell java where to look for that class by using the -classpath option (or its short form -cp):
java -classpath C:\Peter\Michael\Lazarus\ Main
If your Main.java contains the entirety of your source code (and it is in the same directory), then you can use option #4, skip the compile step and directly compile-and-execute it:
java c:\Peter\Michael\Lazarus\Main.java
Assuming that Main.class does not have a package declaration:
java -cp C:\Peter\Michael\Lazarus\ Main
Java looks for classes in a "classpath", which can be set on the command line via the -cp option.
I just had the same issue, I tried running java hello.class, this is wrong.
The command should be java hello.
Do not include the file extension. It is looking for a class file, and will add the name on its own.
So running 'java hello.class' will tell it to go looking for 'hello.class.class' file.
Try this:
java -cp C:\Peter\Michael\Lazarus Main
You need to define the classpath.

Categories

Resources