JavaRush /Java Blog /Random EN /Compiling in Java

Compiling in Java

Published in the Random EN group
Programming in an IDE is great: coherence of code dependencies, convenient debugging, clear testing, dark theme. So, thanks to the IDE, development is developing by leaps and bounds. But she relaxes. Every day, immersing himself in the functionality of the IDE, the developer gets used to committing with one button or building with two clicks. Compiling in Java - 1The situation is much worse with those new to programming who work in the IDE from the very beginning, ignoring work on the command line. For example, in Intellij IDEA, the compilation of a Java application is demonstrated by a loading bar in the bottom panel, and all compilation parameters, classpath processing and other delights of Java life remain behind the scenes. We suggest talking about compiling in Java without an IDE. To run the examples in this article, make sure that JDK 1.7 or later is installed on your machine.

How to compile a program?

Compilation in programming is the reduction of source code into bytecode for the subsequent start of the program. The sequence of actions from source code to program launch looks like this:
  1. There is source code in a file called ClassName.java;
  2. If there are no errors in the code, it is compiled into bytecode (in the file ClassName.class);
  3. The program starts.
Typically, each program is contained in a separate directory. As a simple example, let's take the output to the console:
class Test {
   public static void main(String[] args) {
      System.out.println("Это говорит приложение из командной строки");
   }
}

What is the javac command used for?

Okay, the first point is done. Let's go further to understand: how to compile? :) The javac command will help us with this, the argument of which must specify the required file:

javac Test.java
If there are no errors in the code, a Test.class file will appear next to the Test.java file. This is the compiled bytecode. Now it needs to be launched. Here we use the java command, which runs the bytecode: Compiling in Java - 2The screenshot shows that we get some hieroglyphs in the output: obviously, this is a broken encoding. Typically this happens on a Windows system. To correctly display the Cyrillic alphabet in the console, there are the following commands:

REM change CHCP to UTF-8
CHCP 65001
CLS
They change the current shell code page for the duration of the current window. Let's try again:

D:\Java>java Test
This is what the application says from the command line. Knowing how the javac command works is very useful, since this command is the basis of any project build system.

Compiling and Running Multiple Classes

To work with multiple classes you need a classpath. It is similar to a file system in which classes are contained, and packages act as folders. At this point, it's worth thinking about separating the source code files from the compiled files. As a rule, the sources are located in the src directory, and the compiled classes are in bin. For example, we have a class Boxand a class BoxMachinethat contains a method main. Class Box:
package src;

public class Box {
   private double size;

   public Box(double size) {
       this.size = size;
   }

   public String toString() {
       return "Box have size " + size;
   }
}
It's in the src package and needs to be fixed. Class BoxMachine:
package src;

public class BoxMachine {
   public static void main(String[] args) {
       for(int  i = 0; i < 5; i++) {
           System.out.println(new Box(Math.random()*10));
       }
   }
}
This class is also found in the src package. In the method main, it creates five class objects Boxof different sizes and displays information about them to the console. To compile this group of classes, you must use the javac command from the main directory (which contains the src and bin folders) with the arguments:

javac -d bin ./src/*
-d— a flag after which you should indicate the location where the compiled classes will go. This is very convenient, since transferring, for example, 1000 classes is a very labor-intensive process. bin— folder name. ./src/*— location of source files. *indicates that all files must be compiled. Now the compiled classes appear in the bin folder. To run them, use the java command from the same directory, also with arguments:

java -classpath ./bin BoxMachine
-classpath— a flag after which you should indicate the location of the compiled classes. Java will look for the main class and all related ones in this directory. ./bin— the name of the folder in which the compiled classes are located. BoxMachine— name of the main class. As in the first case, should not be specified .class, since this is the name of a class, not a file. Conclusion:

D:\Java>java -classpath ./bin src.BoxMachine
Box have size 4.085985295359718
Box have size 8.63682158248986
Box have size 6.027448124299726
Box have size 7.288317703877914
Box have size 1.106181659384694

Creating JAR Files

To make the program easy to port and run, you can collect the compiled classes into a jar file - a class archive. The main difference from zip or rar archives is the presence of a manifest file. This manifest specifies the main class that will be run when the jar file is executed, the classpath, and a lot of additional information. Let's create a manifest.mf file in the main directory. Its contents will be as follows:

main-class: src.BoxMachine
class-path: bin/
main-classspecifies the class that contains the method mainand will be executed on startup. class-path— path to compiled classes or additional libraries. Now it's time to build a real program without an IDE using the jar command:

jar -cmf manifest.mf box-machine.jar  -C bin .
-cmf— a flag after which you should specify the path to the manifest file. manifest.mf— path to the manifest. box-machine.jar— name of the output jar file. — a flag after which the path to the compiled classes is indicated. .— the path where the jar file will be placed. In our case, this is the main directory. Now you can launch. Launching jar files is also done using the java command, but then you need to specify the flag -jar: it indicates that the Jar file is being launched, and the second argument is the path to jarthe file, including the extension :

java -jar box-machine.jar
Conclusion:

Box have size 5.5495235762547965
Box have size 9.695870044165662
Box have size 2.3408385788129227
Box have size 7.2790741216674135
Box have size 2.3620854470160513

Compiling in Java without an IDE: An Overview of Build Systems

Despite the relative ease of use of the command line, it is very difficult to build medium and large projects using it. This takes a lot of time and is fraught with errors of varying degrees. Fortunately, there are assembly systems that make the work process much easier. With several teams, this system can assemble a project of any complexity, and the abundance of plugins created during the existence of such systems can eliminate almost any headache.

How to compile Java?

The most famous Java build systems are Ant, Maven and Gradle. There is no good or bad: each of them is created to solve certain problems. Let's look at each of them in more detail.

Ant

Ant is a build tool that uses a script described using an xml file. xml file structure:
<?xml version="1.0"?>
<project name="NameПроекта" default="сценарийПоУмолчанию">
    <target name="NameСценария">
  //  Действия сценария
        <echo>Hello, World!</echo>
    </target>
  //  Второй сценарий
  //  И тд
</project>
Let's create a build.xml file in the main directory with the following contents:
<?xml version="1.0"?>
<project name="BoxMachine" default="test">
   <target name="test">
       <echo>First build in Ant!</echo>
   </target>
</project>
In the same directory, call the ant command:

D:\Java>D:\Temp\ant\bin\ant
Buildfile: D:\Java\build.xml

test:
     [echo] First build in Ant!

BUILD SUCCESSFUL
Total time: 0 seconds
The tag <target>can specify various tasks that allow you to manage the assembly and file system. Ant has over 150 commands available, which are listed in the documentation. In the example below we use only 5:
  • mkdir - creating directories
  • delete- deleting files and directories
  • javac- Java code compilation
  • java- running compiled code
This is what a simple compile, build, or cleanup script looks like:
<?xml version="1.0"?>
<project name="BoxMachine" default="compile">
   <target name="compile">
       <mkdir dir="result/classes"/>
       <javac destdir="result/classes" includeantruntime="false">
           <src path="src"/>
       </javac>
   </target>
   <target name="run" depends="compile">
       <java classname="BoxMachine" classpath="result/classes"/>
   </target>
   <target name="clean">
       <delete dir="result"/>
   </target>
</project>
The script describes three actions - compile, ,code>run and clean. compilecreates a result directory with classes in it, then uses javac to compile the classes into the created directory. runruns the compiled classes with the java command. cleandeletes the result directory. If you run the ant command without arguments in the main directory, the compile action will run. If a specific action needs to be performed, it is specified in the argument.

D:\Java>D:/Temp/ant/bin/ant compile
Buildfile: D:\Java\build.xml

compile:
    [mkdir] Created dir: D:\Java\result\classes
    [javac] Compiling 2 source files to D:\Java\result\classes

BUILD SUCCESSFUL
Total time: 1 second

Maven

Maven offers a slightly different approach to building projects. Here, the developer rather describes his project and the additional tools he uses, unlike Ant, where the build is a sequence of actions. Maven is popular among developers due to its easy dependency management and convenient integration with all development environments. When working with Maven, we adhere to the following project structure: Compiling in Java - 3Build rules, dependencies, etc. are described in the pom.xml file. Typically it is located in the main project folder. On startup, Maven checks the file structure and syntax, warning you about errors. In the main directory, next to the bin and src folders, create a pom.xml file, add inside:
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>ru.javarush.testmaven</groupId>
  <artifactId>testMavenWithoutIde</artifactId>
  <version>1.0.0</version>

  <build>
     <defaultGoal>compile</defaultGoal>
     <sourceDirectory>src</sourceDirectory>
     <outputDirectory>bin</outputDirectory>
     <finalName>${project.artifactId}-${project.version}</finalName>
  </build>
</project>
Next, run the mvn command on the command line:

D:\Java>mvn
[INFO] Scanning for projects...
[INFO]
[INFO] -------------< ru.javarush.testmaven:testMavenWithoutIde >--------------
[INFO] Building testMavenWithoutIde 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ testMavenWithoutIde ---
[WARNING] Using platform encoding (Cp1251 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\Java\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ testMavenWithoutIde ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding Cp1251, i.e. build is platform dependent!
[INFO] Compiling 2 source files to D:\Java\bin
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 15.521 s
[INFO] Finished at: 2019-06-25T20:18:05+03:00
[INFO] ------------------------------------------------------------------------
Now there is a src folder in the bin folder which contains the compiled classes. In pom.xml, the build tag defines the purpose of the build - compilation, the directories of the source code and compilation result files, as well as the project name. Maven has a variety of build targets and plugins for running tests, creating Jar files, building distributions, and other tasks.

Gradle

This is the youngest build system, which is based on Ant and Maven. The main difference is that it works on the basis of an acyclic graph to determine the order of tasks. This is very useful for more complex tasks, such as incremental and multi-project builds. When building with Gradle, it is also recommended to stick to the Maven project folder structure. By the way, the file for building in Gradle is called build.gradle and looks much smaller than that of Maven. Example for our classes:
apply plugin: 'java'
apply plugin: 'application'

sourceSets {
   main {
       java {
           srcDirs 'src'
       }
   }
}
sourceSets.main.output.classesDir = file("bin")

mainClassName = "src.BoxMachine"

defaultTasks 'compileJava', 'run'
The file includes plugins, defines the directory of source code files (if the Maven project structure is not used), the directory of build results, the name of the main class, and default tasks. The gradle command in the directory where the build.gradle file is located is responsible for starting the build:

d:\Java>D:\Temp\gradle\bin\gradle

Welcome to Gradle 5.4.1!

Here are the highlights of this release:
 - Run builds with JDK12
 - New API for Incremental Tasks
 - Updates to native projects, including Swift 5 support

For more details see https://docs.gradle.org/5.4.1/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)

> Task :help

Welcome to Gradle 5.4.1.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

To see more detail about a task, run gradle help --task <task>

For troubleshooting, visit https://help.gradle.org

BUILD SUCCESSFUL in 52s
1 actionable task: 1 executed

Conclusion

At first glance, the ability to compile and assemble code without an IDE seems useless. Indeed, why bother with command lines and Google all the commands when there is a cozy IDE with plugins, auto-checking of everything possible (modern IDEs don’t check IQ level) and integration with popular systems. However, practice shows that the ability to assemble code without a development environment and understanding every step of this process is a dire necessity. This skill will save a lot of nerve cells and time for you and your company. You can learn how to use the IDE, practice writing code, and, of course, get the fundamentals of Java programming here - at JavaRush. Time to get back to learning :)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION