Linux

How to Run Java Programs in Linux Terminal

Run Java Programs in Linux

Running Java programs directly from the Linux terminal offers developers enhanced control, automation capabilities, and a deeper understanding of Java’s execution process. Whether you’re a student learning programming basics or a seasoned developer working on complex applications, mastering command-line Java execution is an invaluable skill that will boost your productivity and versatility in Linux environments.

This comprehensive guide walks you through everything you need to know about compiling and running Java programs in the Linux terminal. You’ll learn how to set up your environment, understand the compilation process, work with packages and libraries, and troubleshoot common issues that arise during development.

Prerequisites for Running Java in Linux

Before diving into Java development on Linux, ensure you have the necessary foundation to work efficiently with the terminal and understand basic programming concepts.

Required Skills and Tools:

The Linux terminal provides powerful functionality once you become familiar with its interface. To get started effectively, you’ll need:

  • Basic familiarity with Linux terminal commands including navigation (cd, ls), file manipulation (cp, mv, rm), and viewing file contents (cat, less)
  • A functioning Linux distribution (Ubuntu, Debian, Fedora, CentOS, or any other distribution)
  • Sufficient system resources (most modern computers easily meet Java’s requirements)
  • Understanding of fundamental programming concepts like variables, conditionals, and loops

For writing your Java code, Linux offers several excellent text editors:

  • Vim or Neovim: Highly efficient editors with extensive customization options
  • Emacs: Another powerful editor with comprehensive programming features
  • Nano: A simpler, more beginner-friendly editor
  • Visual Studio Code: A popular GUI editor with excellent Java support
  • IntelliJ IDEA: A full-featured IDE available in community edition

Remember that while IDEs provide convenience, learning to compile and run programs from the terminal gives you greater control and understanding of the underlying processes.

Installing Java Development Kit (JDK) in Linux

The Java Development Kit (JDK) provides all the tools needed to develop, compile, and run Java applications on your Linux system.

Checking for Existing Java Installation:

Before installing a new JDK, verify whether Java is already installed on your system:

java -version
javac -version

If these commands return version information, you already have Java installed. If not, you’ll need to install the JDK using your distribution’s package manager.

Installation Methods for Different Linux Distributions:

For Ubuntu/Debian-based systems:

# Update package lists
sudo apt update

# Install OpenJDK (version 17 shown here)
sudo apt install openjdk-17-jdk

# Verify installation
java -version
javac -version

For Fedora/RHEL systems:

# Install OpenJDK using dnf
sudo dnf install java-17-openjdk-devel

# Verify installation
java -version
javac -version

For Arch Linux:

# Install using pacman
sudo pacman -S jdk-openjdk

# Verify installation
java -version
javac -version

Using SDKMAN for Version Management:

SDKMAN is a useful tool for managing multiple Java versions on any Linux distribution:

# Install SDKMAN
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

# List available Java versions
sdk list java

# Install desired version
sdk install java 17.0.2-open

# Verify installation
java -version

OpenJDK vs Oracle JDK:

When choosing which JDK to install, you have two main options:

  • OpenJDK: The free, open-source implementation of the Java Platform
  • Oracle JDK: Oracle’s proprietary implementation with some additional features

For most development purposes, OpenJDK is perfectly suitable and avoids licensing complications. However, if you need specific Oracle features or support, you might consider Oracle JDK.

Setting Up Java Environment Variables

Properly configuring environment variables ensures your system can locate and use Java correctly for all your development needs.

Configuring JAVA_HOME:

The JAVA_HOME environment variable points to your Java installation directory and is required by many Java applications and build tools:

# Find your Java installation path
which java
# For symbolic links, find the actual installation
readlink -f $(which java)
# The result will be something like /usr/lib/jvm/java-17-openjdk-amd64/bin/java
# JAVA_HOME should be the directory containing "bin"

Set JAVA_HOME for your current session:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64

Adding Java to PATH:

The PATH variable tells your system where to find executable files:

export PATH=$PATH:$JAVA_HOME/bin

Making Environment Variables Permanent:

To make these settings persist across terminal sessions, add them to your shell profile:

# For bash users (add to ~/.bashrc)
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> ~/.bashrc
echo 'export PATH=$PATH:$JAVA_HOME/bin' >> ~/.bashrc
source ~/.bashrc

# For zsh users (add to ~/.zshrc)
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> ~/.zshrc
echo 'export PATH=$PATH:$JAVA_HOME/bin' >> ~/.zshrc
source ~/.zshrc

Testing Your Configuration:

Verify that your environment variables are set correctly:

echo $JAVA_HOME
echo $PATH
java -version
javac -version

If all commands return the expected values, your environment is configured correctly.

Understanding Java Program Structure

To effectively compile and run Java programs, you must understand their basic structure and components.

Basic Components of a Java Program:

A simple Java program contains:

  1. Optional package declaration (namespace)
  2. Optional import statements for external classes
  3. Class declaration
  4. Main method (entry point)

Here’s a basic example:

// Optional package declaration
package com.example.myapp;

// Optional import statements
import java.util.Scanner;

// Class declaration
public class HelloWorld {
    // Main method - the program entry point
    public static void main(String[] args) {
        System.out.println("Hello, Linux world!");
        
        // Using imported classes
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter your name: ");
        String name = scanner.nextLine();
        System.out.println("Hello, " + name + "!");
        scanner.close();
    }
}

The main method is particularly important as it serves as the entry point for your application. Java looks for this method when you execute a class, and its signature must match exactly as shown above.

Compiling Java Programs

The compilation process transforms human-readable Java code (.java files) into bytecode (.class files) that the Java Virtual Machine (JVM) can execute.

Basic Compilation:

To compile a simple Java program:

# Create a file named HelloWorld.java with your code
nano HelloWorld.java

# Compile the file
javac HelloWorld.java

After successful compilation, you’ll see a new file named HelloWorld.class in the same directory. This file contains the bytecode that the JVM will execute.

Understanding the Compilation Process:

When you run javac, the compiler:

  1. Parses your Java code
  2. Checks for syntax errors
  3. Analyzes the code for semantic correctness
  4. Generates bytecode if no errors are found

Common Compilation Errors:

You might encounter various errors during compilation:

  • Syntax errors: Missing semicolons, brackets, or misspelled keywords
  • Type errors: Assigning incompatible data types
  • Reference errors: Using undefined variables, methods, or classes

The Java compiler provides descriptive error messages with line numbers to help you identify and fix these issues.

Compilation Options:

The javac command offers numerous options to customize the compilation process:

# Specify output directory for .class files
javac -d bin HelloWorld.java

# Compile with debugging information
javac -g HelloWorld.java

# Specify source and target Java versions
javac -source 11 -target 11 HelloWorld.java

# Enable additional warnings
javac -Xlint HelloWorld.java

Compiling Multiple Files:

For projects with multiple Java files:

# Compile specific files
javac File1.java File2.java File3.java

# Compile all Java files in the current directory
javac *.java

# Compile all Java files recursively
find . -name "*.java" > sources.txt
javac @sources.txt

Running Java Programs

Once compiled, you can execute your Java programs using the java command.

Basic Execution:

To run a simple Java program:

# Run the program (note: don't include the .class extension)
java HelloWorld

The java command loads the JVM, which then reads the bytecode, performs just-in-time compilation, and executes your program.

Running Programs with Packages:

If your program uses packages, you need to run it from the base directory:

# For a program in package com.example.myapp
# Navigate to the directory above the package root
cd ~/projects/java-demo

# Run the program using the fully qualified class name
java com.example.myapp.HelloWorld

Passing Command-Line Arguments:

You can pass arguments to your Java programs through the command line:

java HelloWorld arg1 arg2 arg3

In your code, access these arguments through the args parameter in the main method:

public static void main(String[] args) {
    // args[0] is "arg1", args[1] is "arg2", etc.
    System.out.println("First argument: " + args[0]);
}

Running with Custom JVM Options:

The java command accepts various options to customize the JVM’s behavior:

# Set maximum heap size
java -Xmx512m HelloWorld

# Enable verbose garbage collection
java -verbose:gc HelloWorld

# Combine multiple options
java -Xms256m -Xmx1g -ea HelloWorld

Working with Java Packages

Packages help organize Java code, prevent naming conflicts, and control access to classes and methods.

Creating Package Structures:

Package names correspond to directory structures:

# For package com.example.myapp
mkdir -p com/example/myapp

# Create a Java file in this package
nano com/example/myapp/HelloWorld.java

Inside HelloWorld.java:

package com.example.myapp;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello from a package!");
    }
}

Compiling and Running Packaged Programs:

Compile from the root directory:

# Compile
javac com/example/myapp/HelloWorld.java

# Run
java com.example.myapp.HelloWorld

Package Naming Conventions:

Follow these standard conventions for package names:

  • Use lowercase letters
  • Use reversed domain name (e.g., com.example.project)
  • Separate logical components with dots
  • Avoid Java reserved keywords

Importing Classes from Other Packages:

Use import statements to use classes from other packages:

// Single class import
import java.util.ArrayList;

// Entire package import
import java.util.*;

Managing Class Paths

The classpath tells Java where to find user-defined classes and packages when compiling and running programs.

Understanding the Classpath:

The classpath is a parameter that specifies the location of user-defined classes and packages. It can include directories, JAR files, and ZIP archives.

Using the -cp Option:

Specify the classpath when compiling or running Java programs:

# Compile with classpath
javac -cp ".:lib/dependency.jar" com/example/myapp/HelloWorld.java

# Run with classpath
java -cp ".:lib/dependency.jar" com.example.myapp.HelloWorld

The colon : separates classpath entries on Linux (use semicolon ; on Windows).

Setting CLASSPATH Environment Variable:

You can set a default classpath through the CLASSPATH environment variable:

export CLASSPATH=.:lib/dependency.jar

However, explicitly using the -cp option is generally preferred for clarity and to avoid unexpected behavior.

Directory Structure Best Practices:

Organize your Java projects with a clear structure:

project/
├── src/             # Source files
│   └── com/
│       └── example/
│           └── myapp/
│               └── HelloWorld.java
├── bin/             # Compiled classes
├── lib/             # External libraries
└── docs/            # Documentation

Working with External Libraries

Most real-world Java applications use external libraries to extend functionality without reinventing the wheel.

Adding JAR Files to Your Project:

Place JAR files in a dedicated directory (e.g., lib/):

mkdir -p lib
# Download or copy JAR files to this directory

Compiling with External Dependencies:

Include JAR files in the classpath when compiling:

javac -cp ".:lib/*" com/example/myapp/HelloWorld.java

Running with External Dependencies:

Similarly, include JAR files in the classpath when running:

java -cp ".:lib/*" com.example.myapp.HelloWorld

Using Build Tools from Terminal:

For complex projects with many dependencies, consider using build tools:

Maven:

# Create a new Maven project
mvn archetype:generate -DgroupId=com.example -DartifactId=myapp

# Compile and package
cd myapp
mvn compile
mvn package

# Run the packaged JAR
java -jar target/myapp-1.0-SNAPSHOT.jar

Gradle:

# Create a new Gradle project
mkdir gradle-demo && cd gradle-demo
gradle init --type java-application

# Build and run
./gradlew build
./gradlew run

These build tools automatically manage dependencies, compilation, and packaging, greatly simplifying the development process for larger projects.

Running JAR Files

JAR (Java ARchive) files bundle Java classes and resources into a single file, making distribution and execution more convenient.

Creating Executable JAR Files:

Create a manifest file (manifest.txt) that specifies the main class:

Main-Class: com.example.myapp.HelloWorld

Create the JAR file:

jar cvfm HelloWorld.jar manifest.txt com/example/myapp/HelloWorld.class

Running JAR Files:

Execute the JAR file:

java -jar HelloWorld.jar

Setting Executable Permissions:

Make the JAR file executable:

chmod +x HelloWorld.jar

This allows you to run it directly (if your system is configured to use the Java launcher for .jar files).

Creating JAR Files with Dependencies:

For JAR files that depend on external libraries:

# Create a directory for all classes
mkdir -p classes

# Compile with dependencies to the classes directory
javac -cp "lib/*" -d classes src/com/example/myapp/*.java

# Create the JAR with the manifest
jar cvfm app.jar manifest.txt -C classes .

Advanced Java Execution Options

The JVM offers numerous options to fine-tune execution for performance, debugging, and monitoring.

Memory Allocation:

Control memory allocation for your Java applications:

# Set maximum heap size
java -Xmx512m HelloWorld

# Set initial heap size
java -Xms128m HelloWorld

# Combine options
java -Xms128m -Xmx512m HelloWorld

Debugging Options:

Enable remote debugging for connection with debugging tools:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 HelloWorld

Performance Monitoring:

Monitor JVM performance during execution:

# Print garbage collection details
java -verbose:gc HelloWorld

# JIT compiler statistics
java -XX:+PrintCompilation HelloWorld

Logging and Output Redirection:

Direct standard output and error streams to files:

java HelloWorld > output.log
java HelloWorld > output.log 2> error.log

These advanced options give you fine-grained control over how your Java applications run and help diagnose issues that arise during execution.

Troubleshooting Common Issues

Even experienced developers encounter issues when working with Java in the terminal. Here are solutions for common problems.

ClassNotFoundException and NoClassDefFoundError:

These common errors occur when Java cannot find a class:

  • ClassNotFoundException: Thrown when trying to load a class through its string name
  • NoClassDefFoundError: Thrown when a class was available during compilation but not found during runtime

Solutions:

  1. Check your classpath to ensure it includes all necessary directories and JAR files
  2. Verify that the class exists and is properly compiled
  3. Confirm that package names match directory structure exactly

Classpath Configuration Problems:

Symptoms of classpath issues include classes not found despite being present or wrong versions of classes being loaded.

Solutions:

  1. Explicitly specify the classpath with -cp rather than relying on the CLASSPATH environment variable
  2. Use absolute paths if relative paths aren’t working
  3. Check for classpath conflicts where multiple versions of the same class exist

Package Structure Mismatches:

The package declaration must match the directory structure exactly:

// File: com/example/myapp/HelloWorld.java
package com.example.myapp; // Must match directory structure

Permission and File Access Issues:

If encountering permission issues:

# Check file permissions
ls -l HelloWorld.java HelloWorld.class

# Set appropriate permissions
chmod 644 HelloWorld.java
chmod 755 HelloWorld.class

JDK Version Compatibility Problems:

Different Java versions have different features and syntax:

# Check your Java version
java -version

# Compile for specific version compatibility
javac -source 11 -target 11 HelloWorld.java

Automating Java Compilation and Execution

Automate repetitive tasks to improve efficiency during development.

Creating Shell Scripts:

Create a build script (build.sh):

#!/bin/bash
# Simple build script for Java projects

# Clean previous build
rm -rf bin
mkdir -p bin

# Compile
javac -d bin src/com/example/myapp/*.java

# Run
java -cp bin com.example.myapp.HelloWorld

echo "Build and run complete."

Make it executable:

chmod +x build.sh

Using Makefiles:

Create a Makefile for more advanced automation:

JAVAC = javac
JAVA = java
SRC_DIR = src
BIN_DIR = bin
PACKAGE = com/example/myapp
MAIN_CLASS = com.example.myapp.HelloWorld

.PHONY: all clean run

all: $(BIN_DIR)
	$(JAVAC) -d $(BIN_DIR) $(SRC_DIR)/$(PACKAGE)/*.java

$(BIN_DIR):
	mkdir -p $(BIN_DIR)

clean:
	rm -rf $(BIN_DIR)

run: all
	$(JAVA) -cp $(BIN_DIR) $(MAIN_CLASS)

Use with:

make        # Compile
make run    # Compile and run
make clean  # Clean build files

These automation tools significantly reduce the amount of manual work required during development and help ensure consistency in your build process.

Best Practices for Terminal-Based Java Development

Follow these practices to develop efficiently in the terminal.

Directory Organization:

Maintain a clean project structure:

  • Keep source files in src/
  • Output compiled classes to bin/
  • Store libraries in lib/
  • Document your code in docs/

Version Control Integration:

Use Git with your terminal workflow:

# Initialize repository
git init

# Create .gitignore for Java
echo "bin/\n*.class\n.classpath\n.project" > .gitignore

# Standard Git workflow
git add .
git commit -m "Initial commit"

Documentation Approaches:

Document your code using Javadoc:

/**
 * This class demonstrates a simple Java program.
 * 
 * @author Your Name
 * @version 1.0
 */
public class HelloWorld {
    /**
     * Program entry point.
     * 
     * @param args command-line arguments
     */
    public static void main(String[] args) {
        System.out.println("Hello, documented world!");
    }
}

Generate documentation:

javadoc -d docs src/com/example/myapp/*.java

Testing from the Command Line:

Run JUnit tests from the terminal:

# Compile tests with JUnit in classpath
javac -cp ".:lib/junit-4.13.2.jar:lib/hamcrest-core-1.3.jar" test/com/example/myapp/HelloWorldTest.java

# Run tests
java -cp ".:bin:lib/junit-4.13.2.jar:lib/hamcrest-core-1.3.jar" org.junit.runner.JUnitCore com.example.myapp.HelloWorldTest

Following these best practices will help you maintain clean, well-organized projects and streamline your development workflow.

VPS Manage Service Offer
If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal!

r00t

r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.
Back to top button