The first one: put aside IDE, find out how to build javac

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 javacand javaunarmed 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.javaand then executed in the current directory javaccompiler 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 javacagain 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 javathe 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 javaccompiler, see the current directory under HelloWorld.classgeneration, and very smooth.

Still the same with the javacommand, 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 HelloWorldthe new name com.imshuai.javalinux.HelloWorld, then passed javanaturally 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/javalinuxdirectory, and then HelloWorld.classput 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:

  1. 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).
  2. 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.HelloWorldmust be stored in./com/imshuai/javalinux/HelloWorld.class

Of course, each package that you create a directory path too much trouble. -dThe 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!
复制代码

-dSpecifies 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.javacall HelloServiceto 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.javaand HelloWorld.javathe 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.javait? 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 javacommand 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.javabrought 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 javacto 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 -dparameter 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 targetoutside 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 -cpsetting the class path. The following further study the class path.

Classpath, JRE search is user-level class file path or other resources, javacor javaother 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 CLASSPATHor -cpparameter settings, which will be over the former. Recommended by -cpsetting, it will only affect the current process.

Class path similar to the operating system in the pathconcept, 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 pathis similar.

The classpath wildcard *matching jar or zip, but

  1. Jar or zip wildcard matches only, such as path / * just below the jar or zip classpath added, but without the addition classpath path itself.
  2. Wildcard search is not recursive, meaning that in the jar or zip match in the first directory.
  3. 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.
  4. Wildcard apply to CLASSPATHvariables or -cpparameters, 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, javathe 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 findcommand complete:

javac -cp "lib/*" -d target $(find src -name "*.java")
复制代码

javacAlso 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.txtrepresentatives passed javaca list of file names:

javac -cp "lib/*" -d target @javaFiles.txt
复制代码

Not only that, the parameters can also be placed in the file (note: -cpcan not go into). For example, javaFiles.txtin 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 targetalone 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 javacas 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.javacan 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 javacbasic usage is summarized as follows:

  1. -cpClasspath parameter setting, the basic usage is dependent on the compile-time class path jar package added. And may be *wild jar package.
  2. -d Parameters used to set the class files compiled into a separate directory and create subdirectories according to package name.
  3. Theoretically java file path to pass all the javaccan, but the operation, the file list can be output through the find command to a file, passing through @argfiles parameter.

reference

  1. docs.oracle.com/javase/8/do…
  2. docs.oracle.com/javase/8/do…
  3. docs.oracle.com/javase/8/do…
  4. docs.oracle.com/javase/tuto…
  5. docs.oracle.com/javase/8/do…

github.com/maoshuai/ja…


"Java and Linux Learning Week" every Friday release, synchronization update on: Github , know almost , Denver

Guess you like

Origin juejin.im/post/5d4cf0d46fb9a06b2f5f9e93