IDE or maven compiler and other tools do you have a Java program. But the more advanced tools, the more hidden details, if there are problems on the ignorant force, the final analysis, the basic concept is not secure. Back to nature, back to the original place javac
, the problem will become clear. Here's a step by step demonstration javac
and java
unarmed compile and run a conventional project.
Hello World practicing a hand
To a simple first, we resorted ancestral HelloWorld program. (Interested, you can try to write it by hand if ~)
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello, World!");
}
}
复制代码
After writing, save it as: HelloWorld.java
and then executed in the current directory javac
compiler command:
javac HelloWorld.java
复制代码
View the current directory (more accurate to say that the same level java file directory), and she generated HelloWorld.class
:
maoshuai@ms:~/javaLinux/w1$ ls
HelloWorld.class HelloWorld.java
复制代码
Continue in the current directory, runjava
commands, printed out correctly Hello, World!
maoshuai@ms:~/javaLinux/w1$ java HelloWorld
Hello, World!
复制代码
Old driver, steady! It looks very simple thing: first javac
again java
.
Although simple, but a novice mistake often committed: imagine to perform.class
file, such as written so, naturally given:
maoshuai@ms:~/javaLinux/w1$ java HelloWorld.class
Error: Could not find or load main class HelloWorld.class
复制代码
Need to understand that java
the parameters passed in the name of the class where the main function, rather than a class file; java class name will automatically go to class files .
Take a package name
Everything is going well, but there is no package name is not professional, so we added a fast hardware package com.imshuai.javalinux
:
package com.imshuai.javalinux;
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello, World!");
}
}
复制代码
Still the same with the javac
compiler, see the current directory under HelloWorld.class
generation, and very smooth.
Still the same with the java
command, instantly hit the face:
maoshuai@ms:~/javaLinux/w1$ java HelloWorld
Error: Could not find or load main class HelloWorld
复制代码
I thought, the HelloWorld already have their own package name, so its name is not no last name of HelloWorld
the new name com.imshuai.javalinux.HelloWorld
, then passed java
naturally with a new name, try again:
maoshuai@ms:~/javaLinux/w1$ java com.imshuai.javalinux.HelloWorld
Error: Could not find or load main class com.imshuai.javalinux.HelloWorld
复制代码
Or beaten face, this time the old driver told you, create a com/imshuai/javalinux
directory, and then HelloWorld.class
put to execution:
maoshuai@ms:~/javaLinux/w1$ mkdir -p com/imshuai/javalinux
maoshuai@ms:~/javaLinux/w1$ mv HelloWorld.class com/imshuai/javalinux
maoshuai@ms:~/javaLinux/w1$ java com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
Sure enough, out of the normal printing Hello, World!
The above steps for two points:
- Increased the package name, the class name is also changed, the line does not renamed never change, to bring the natural name (i.e., a so-called fully qualified name).
- Java will correspond to the directory structure according to the package name and class path from search to find class files in the directory . Since the default class path is the current directory, it
com.imshuai.javalinux.HelloWorld
must be stored in./com/imshuai/javalinux/HelloWorld.class
Of course, each package that you create a directory path too much trouble. -d
The above parameters can do it work :
maoshuai@ms:~/javaLinux/w1$ javac -d . HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ ls
com HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ java com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
-d
Specifies the root directory of the generated class file (here it is the current directory), and creates a subdirectory path package according to the class.
There are two compilation dependency class
Package name is resolved, we'll complex, put forward a dependent calls. First, we extract a HelloService
:
package com.imshuai.javalinux;
public class HelloService{
public void printHello(String name){
System.out.println("Hello, " + name + "!");
}
}
复制代码
Then modify the HelloWorld.java
call HelloService
to complete say hello:
package com.imshuai.javalinux;
public class HelloWorld{
public static void main(String[] args){
HelloService service = new HelloService();
service.printHello("World");
}
}
复制代码
Then we turn to compile: HelloService.java
and HelloWorld.java
the last run:
maoshuai@ms:~/javaLinux/w1$ javac -d . HelloService.java
maoshuai@ms:~/javaLinux/w1$ javac -d . HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ ls
com HelloService.java HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ java com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
Intuitively, first compiled HelloService.java
, this is right. What if compile HelloWorld.java
it? Of course her face:
maoshuai@ms:~/javaLinux/w1$ javac -d . HelloWorld.java
HelloWorld.java:4: error: cannot find symbol
HelloService service = new HelloService();
^
symbol: class HelloService
location: class HelloWorld
HelloWorld.java:4: error: cannot find symbol
HelloService service = new HelloService();
^
symbol: class HelloService
location: class HelloWorld
2 errors
复制代码
If the compile time, but also to determine the order based on dependencies, the bar too low. I think the java
command should be able to automatically resolve it, the two-time java file passed it a try:
maoshuai@ms:~/javaLinux/w1$ javac -d . HelloWorld.java HelloService.java
maoshuai@ms:~/javaLinux/w1$ ls
com HelloService.java HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ java com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
Fast hardware, it automatically solve the problem of the order, like this one (though I am ill will HelloWorld.java
brought to the front)!
Using the src directory and target
As it can be seen from the above example, although the class files must be placed in the same directory where the package name, but java source files and do not have this requirement . However, in order to facilitate the management, we will java source files in the package directory structure:
maoshuai@ms:~/javaLinux/w1$ mkdir -p com/imshuai/javalinux
maoshuai@ms:~/javaLinux/w1$ mv *.java com/imshuai/javalinux/
maoshuai@ms:~/javaLinux/w1$ ls com/imshuai/javalinux/
HelloService.java HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ javac -d . com/imshuai/javalinux/*.java
maoshuai@ms:~/javaLinux/w1$ ls com/imshuai/javalinux/
HelloService.class HelloService.java HelloWorld.class HelloWorld.java
maoshuai@ms:~/javaLinux/w1$ java com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
Compile time javac
to pass a new java file path (here with a wildcard), the other is no different. You can see the class files generated java files to the same directory . java class files and source files together, very fresh, whether as like the IDE: java files into the src directory, class files into the target directory? Now I try.
Create src and target directory, and the original java files are moved to the src directory:
maoshuai@ms:~/javaLinux/w1$ mkdir src
maoshuai@ms:~/javaLinux/w1$ mkdir target
maoshuai@ms:~/javaLinux/w1$ mv com src
maoshuai@ms:~/javaLinux/w1$ ls
src target
复制代码
Then compile -d
parameter specifies the target directory:
maoshuai@ms:~/javaLinux/w1$ javac -d target src/com/imshuai/javalinux/*.java
maoshuai@ms:~/javaLinux/w1$ ls target/com/imshuai/javalinux/
HelloService.class HelloWorld.class
复制代码
How to run it? Running directly on the current directory is to die, after all, more than one target directory, run into the target directory, properly properly:
maoshuai@ms:~/javaLinux/w1/target$ java com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
In addition to entering the target
outside directory, more commonly used method is by -classpath
(or for short -cp
) option class path :
maoshuai@ms:~/javaLinux/w1$ java -cp target com.imshuai.javalinux.HelloWorld
Hello, World!
复制代码
The CLASSPATH
The above demonstrates by -cp
setting the class path. The following further study the class path.
Classpath, JRE search is user-level class file path or other resources, javac
or java
other tools can be designated classpath. If not set, the default class path is the current directory. But if you set the class path, the default value is overwritten, so if you want to keep your current directory path for the class, you need to be .
added , a bit like the default constructor feeling.
Class path, through the environment variable CLASSPATH
or -cp
parameter settings, which will be over the former. Recommended by -cp
setting, it will only affect the current process.
Class path similar to the operating system in the path
concept, but it is a java class file search tool path. Similarly, the path may be a plurality of classes, and separated by a semicolon:
export CLASSPATH=path1:path2:...
复制代码
or:
sdkTool -classpath path1:path2:...
复制代码
sdkTool can be java, javac, javadoc and so on.
Class path may be not only a directory, but also may be a jar or the zip bag.
Path setting is in order, java will first search in the class path in front of. This and operating systems path
is similar.
The classpath wildcard *
matching jar or zip, but
- Jar or zip wildcard matches only, such as path / * just below the jar or zip classpath added, but without the addition classpath path itself.
- Wildcard search is not recursive, meaning that in the jar or zip match in the first directory.
- Wildcard matching to the jar or zip, the order of addition to the classpath is uncertain. Therefore, a more prudent approach is to enumerate all jar or zip displayed.
- Wildcard apply to
CLASSPATH
variables or-cp
parameters, but not for manifest file a jar.
A more realistic scenario
The following java package structure more projects, 还有jar包依赖
and how to compile it? (Project code download: github.com/maoshuai/ja... )
├── lib
│ ├── logback-classic-1.2.3.jar
│ ├── logback-core-1.2.3.jar
│ └── slf4j-api-1.7.26.jar
├── resources
│ └── logback.xml
├── src
│ └── com
│ └── imshuai
│ └── javalinux
│ ├── HelloWorld.java
│ └── service
│ ├── IGreetingService.java
│ └── impl
│ ├── AlienGreetingService.java
│ ├── CatGreetingService.java
│ ├── DogGreetingService.java
│ └── HumanGreetingService.java
└── target
复制代码
The most direct way, with just the same, but a little more manual labor, to enumerate all the java files, use wildcards in the lib jar your classpath:
javac \
-cp "lib/*" \
-d target \
src/com/imshuai/javalinux/HelloWorld.java \
src/com/imshuai/javalinux/service/IGreetingService.java \
src/com/imshuai/javalinux/service/impl/*.java
复制代码
Compilation is successful, java
the command to run it (Note: target and jar in the lib will need to add the classpath):
maoshuai@ms:~/javaLinux/w1$ java -cp "target:lib/*" com.imshuai.javalinux.HelloWorld XiaoMing
22:16:15.887 [main] INFO HumanGreetingService - XiaoMing is saying hello: Ni Chou Sha!
复制代码
If many documents, these documents are listed in the manual is not realistic, you can find
command complete:
javac -cp "lib/*" -d target $(find src -name "*.java")
复制代码
javac
Also provided is a list of files that way, the list compiled java files about to be written to a text file, we are done with the find command:
maoshuai@ms:~/javaLinux/w1$ find src -name "*.java" >javaFiles.txt
复制代码
JavaFiles.txt generated as follows:
src/com/imshuai/javalinux/service/IGreetingService.java
src/com/imshuai/javalinux/service/impl/HumanGreetingService.java
src/com/imshuai/javalinux/service/impl/CatGreetingService.java
src/com/imshuai/javalinux/service/impl/DogGreetingService.java
src/com/imshuai/javalinux/service/impl/AlienGreetingService.java
src/com/imshuai/javalinux/HelloWorld.java
复制代码
Then @
at the beginning of @javaFiles.txt
representatives passed javac
a list of file names:
javac -cp "lib/*" -d target @javaFiles.txt
复制代码
Not only that, the parameters can also be placed in the file (note: -cp
can not go into). For example, javaFiles.txt
in adding-d target
-d target
src/com/imshuai/javalinux/service/IGreetingService.java
src/com/imshuai/javalinux/service/impl/HumanGreetingService.java
src/com/imshuai/javalinux/service/impl/CatGreetingService.java
src/com/imshuai/javalinux/service/impl/DogGreetingService.java
src/com/imshuai/javalinux/service/impl/AlienGreetingService.java
src/com/imshuai/javalinux/HelloWorld.java
复制代码
In this way only execute:
javac -cp "lib/*" @javaFiles.txt
复制代码
But for clarity, we can put parameters -d target
alone into a file javaOptions.txt
, then transfer files @ two:
javac -cp "lib/*" @javaOptions.txt @javaFiles.txt
复制代码
The advantage of using a list of files that circumvent the restrictions command-line parameter length, and can run on any operating system .
With the above preparations, we can write a script to automate the compilation:
PROJECT_DIR=/home/maoshuai/javaLinux/w1
# clean target directory
rm -rf $PROJECT_DIR/target/*
# prepare arg files
find $PROJECT_DIR/src -name "*.java">$PROJECT_DIR/target/javaFiles.txt
echo "-d $PROJECT_DIR/target" >$PROJECT_DIR/target/javaOptions.txt
# compile
javac -cp "$PROJECT_DIR/lib/*" @$PROJECT_DIR/target/javaOptions.txt @$PROJECT_DIR/target/javaFiles.txt
# copy resources to target
cp -rf $PROJECT_DIR/resources/* $PROJECT_DIR/target
# clean temp files
rm -rf $PROJECT_DIR/target/javaOptions.txt $PROJECT_DIR/target/javaFiles.txt
复制代码
It's time to take a closer look the javac
Oracle's official documentation describes javac
as follows :
Reads Java class and interface definitions and compiles them into bytecode and class files.
javac syntax is as follows:
javac [ options ] [ sourcefiles ] [ classes] [ @argfiles ]
复制代码
- options: some parameters, such as -cp, -d
- sourcefiles: is compiled java files, such as
HelloWorld.java
can be multiple, separated by a space - classes: for processing annotations. Temporarily not get to know how to use
- @argfiles, or file path option is to include java file list, beginning with the @ symbol, like the above @ javaOptions.txt and @ javaFiles.txt
to sum up
The javac
basic usage is summarized as follows:
-cp
Classpath parameter setting, the basic usage is dependent on the compile-time class path jar package added. And may be*
wild jar package.-d
Parameters used to set the class files compiled into a separate directory and create subdirectories according to package name.- Theoretically java file path to pass all the
javac
can, but the operation, the file list can be output through the find command to a file, passing through @argfiles parameter.
reference
- docs.oracle.com/javase/8/do…
- docs.oracle.com/javase/8/do…
- docs.oracle.com/javase/8/do…
- docs.oracle.com/javase/tuto…
- docs.oracle.com/javase/8/do…
"Java and Linux Learning Week" every Friday release, synchronization update on: Github , know almost , Denver