
Command Line Arguments in Java: How to Use Them
Command line arguments are parameters passed to a Java application when it starts, allowing you to customize program behavior without modifying the source code. They’re essential for creating flexible, production-ready applications that can adapt to different environments and configurations. This post will walk you through everything from basic argument handling to advanced parsing techniques, real-world implementation patterns, and troubleshooting common issues that developers encounter when deploying Java applications on servers.
How Command Line Arguments Work in Java
Java applications receive command line arguments through the main method’s String[] args
parameter. When you execute a Java program, the JVM collects everything after the class name and passes it as an array of strings to your application.
public class ArgumentDemo {
public static void main(String[] args) {
System.out.println("Total arguments: " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("Argument " + i + ": " + args[i]);
}
}
}
Running this with java ArgumentDemo hello world 123
produces:
Total arguments: 3
Argument 0: hello
Argument 1: world
Argument 2: 123
Key technical points to understand:
- Arguments are always strings, regardless of input type
- Spaces separate arguments unless enclosed in quotes
- The JVM handles argument parsing before your code runs
- Empty arguments array is valid when no parameters are provided
- Arguments preserve order and can contain special characters
Step-by-Step Implementation Guide
Let's build a practical configuration utility that demonstrates proper argument handling:
import java.util.HashMap;
import java.util.Map;
public class ConfigManager {
private Map config = new HashMap<>();
public static void main(String[] args) {
ConfigManager manager = new ConfigManager();
manager.parseArguments(args);
manager.displayConfiguration();
manager.validateConfiguration();
}
private void parseArguments(String[] args) {
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("--")) {
String key = args[i].substring(2);
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
config.put(key, args[++i]);
} else {
config.put(key, "true"); // Boolean flag
}
} else if (args[i].startsWith("-")) {
String key = args[i].substring(1);
if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
config.put(key, args[++i]);
} else {
config.put(key, "true");
}
}
}
}
private void displayConfiguration() {
System.out.println("Configuration loaded:");
config.forEach((key, value) ->
System.out.println(" " + key + " = " + value));
}
private void validateConfiguration() {
if (config.containsKey("port")) {
try {
int port = Integer.parseInt(config.get("port"));
if (port < 1 || port > 65535) {
System.err.println("Invalid port range: " + port);
System.exit(1);
}
} catch (NumberFormatException e) {
System.err.println("Port must be numeric");
System.exit(1);
}
}
}
}
Usage examples:
java ConfigManager --host localhost --port 8080 --debug
java ConfigManager -h 192.168.1.100 -p 9090 --ssl-enabled
This implementation handles both long-form (--option
) and short-form (-o
) arguments, boolean flags, and includes basic validation.
Real-World Examples and Use Cases
Here are practical scenarios where command line arguments prove invaluable:
Database Connection Manager
public class DatabaseConnector {
private String host = "localhost";
private int port = 5432;
private String database = "production";
private String username;
private String password;
private boolean useSSL = false;
public static void main(String[] args) {
DatabaseConnector connector = new DatabaseConnector();
connector.processArguments(args);
connector.connect();
}
private void processArguments(String[] args) {
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "--host":
host = args[++i];
break;
case "--port":
port = Integer.parseInt(args[++i]);
break;
case "--database":
database = args[++i];
break;
case "--username":
username = args[++i];
break;
case "--password":
password = args[++i];
break;
case "--ssl":
useSSL = true;
break;
case "--help":
printUsage();
System.exit(0);
break;
}
}
}
private void printUsage() {
System.out.println("Usage: java DatabaseConnector [OPTIONS]");
System.out.println("Options:");
System.out.println(" --host HOST Database host (default: localhost)");
System.out.println(" --port PORT Database port (default: 5432)");
System.out.println(" --database DB Database name (default: production)");
System.out.println(" --username USER Database username");
System.out.println(" --password PASS Database password");
System.out.println(" --ssl Enable SSL connection");
System.out.println(" --help Show this help message");
}
}
Log File Processor
public class LogProcessor {
public static void main(String[] args) {
if (args.length < 2) {
System.err.println("Usage: java LogProcessor [options]");
System.exit(1);
}
String inputFile = args[0];
String outputFile = args[1];
String logLevel = "INFO";
String dateFormat = "yyyy-MM-dd";
// Process optional arguments
for (int i = 2; i < args.length; i++) {
if ("--level".equals(args[i]) && i + 1 < args.length) {
logLevel = args[++i];
} else if ("--date-format".equals(args[i]) && i + 1 < args.length) {
dateFormat = args[++i];
}
}
System.out.println("Processing: " + inputFile + " -> " + outputFile);
System.out.println("Log level: " + logLevel);
System.out.println("Date format: " + dateFormat);
}
}
Comparison with Argument Parsing Libraries
While manual argument parsing works for simple cases, libraries offer more robust solutions:
Method | Complexity | Features | Dependencies | Best For |
---|---|---|---|---|
Manual Parsing | Low | Basic | None | Simple applications, learning |
Apache Commons CLI | Medium | Rich validation, help generation | External JAR | Enterprise applications |
JCommander | Medium | Annotation-based, type conversion | External JAR | Complex command structures |
Picocli | Medium-High | ANSI colors, subcommands, completion | External JAR | Modern CLI applications |
Apache Commons CLI Example
import org.apache.commons.cli.*;
public class CommonsCliExample {
public static void main(String[] args) {
Options options = new Options();
options.addOption("h", "host", true, "Database host");
options.addOption("p", "port", true, "Database port");
options.addOption("d", "database", true, "Database name");
options.addOption("v", "verbose", false, "Enable verbose output");
CommandLineParser parser = new DefaultParser();
HelpFormatter formatter = new HelpFormatter();
try {
CommandLine cmd = parser.parse(options, args);
String host = cmd.getOptionValue("host", "localhost");
int port = Integer.parseInt(cmd.getOptionValue("port", "5432"));
String database = cmd.getOptionValue("database", "mydb");
boolean verbose = cmd.hasOption("verbose");
System.out.println("Connecting to: " + host + ":" + port + "/" + database);
if (verbose) {
System.out.println("Verbose mode enabled");
}
} catch (ParseException e) {
System.err.println("Parsing failed: " + e.getMessage());
formatter.printHelp("DatabaseApp", options);
}
}
}
Best Practices and Common Pitfalls
Security Considerations
- Never pass sensitive data like passwords directly as arguments - they appear in process lists
- Use configuration files or environment variables for secrets
- Validate and sanitize all input arguments
- Implement proper error handling to avoid information disclosure
// DON'T DO THIS
java MyApp --password secretpass123
// DO THIS INSTEAD
java MyApp --config-file /secure/config.properties
// or use environment variables
String password = System.getenv("DB_PASSWORD");
Error Handling Best Practices
public class RobustArgumentParser {
public static void parsePort(String portArg) {
try {
int port = Integer.parseInt(portArg);
if (port < 1 || port > 65535) {
throw new IllegalArgumentException("Port must be between 1 and 65535");
}
return port;
} catch (NumberFormatException e) {
System.err.println("Error: Port must be a valid number, got: " + portArg);
System.exit(1);
} catch (IllegalArgumentException e) {
System.err.println("Error: " + e.getMessage());
System.exit(1);
}
return -1; // Never reached
}
}
Performance Considerations
Argument parsing typically has minimal performance impact, but consider these points for high-performance applications:
- Parse arguments once during initialization, not repeatedly
- Use appropriate data structures for lookups (HashMap for key-value pairs)
- Cache parsed values instead of re-parsing strings
- Validate early to fail fast and avoid expensive operations
Advanced Usage Patterns
Configuration Hierarchy
public class ConfigurationManager {
private Properties config = new Properties();
public void loadConfiguration(String[] args) {
// 1. Load default configuration
loadDefaults();
// 2. Load from configuration file
String configFile = findConfigFile(args);
if (configFile != null) {
loadFromFile(configFile);
}
// 3. Override with command line arguments (highest priority)
overrideFromArgs(args);
}
private String findConfigFile(String[] args) {
for (int i = 0; i < args.length - 1; i++) {
if ("--config".equals(args[i])) {
return args[i + 1];
}
}
return null;
}
}
Handling Complex Argument Structures
// Support for: java MyApp server --port 8080 --threads 10
public class SubcommandParser {
public static void main(String[] args) {
if (args.length == 0) {
printUsage();
return;
}
String command = args[0];
String[] commandArgs = Arrays.copyOfRange(args, 1, args.length);
switch (command) {
case "server":
startServer(commandArgs);
break;
case "client":
startClient(commandArgs);
break;
case "migrate":
runMigration(commandArgs);
break;
default:
System.err.println("Unknown command: " + command);
printUsage();
}
}
}
Environment Integration
For applications deployed on VPS or dedicated servers, combine command line arguments with environment variables:
public class EnvironmentAwareConfig {
public static String getConfigValue(String key, String[] args, String defaultValue) {
// Priority: Command line -> Environment -> Default
String cliValue = extractFromArgs(key, args);
if (cliValue != null) return cliValue;
String envValue = System.getenv(key.toUpperCase().replace("-", "_"));
if (envValue != null) return envValue;
return defaultValue;
}
private static String extractFromArgs(String key, String[] args) {
String flag = "--" + key;
for (int i = 0; i < args.length - 1; i++) {
if (flag.equals(args[i])) {
return args[i + 1];
}
}
return null;
}
}
Troubleshooting Common Issues
Argument Parsing Problems
Common issues and solutions:
- Spaces in arguments: Use quotes or escape characters
- Special characters: Properly escape shell metacharacters
- Encoding issues: Ensure consistent character encoding
- Array bounds: Always check array length before accessing elements
// Handle problematic input safely
public class SafeArgumentParser {
public static String getArgumentValue(String[] args, String flag) {
for (int i = 0; i < args.length - 1; i++) {
if (flag.equals(args[i])) {
String value = args[i + 1];
if (value.startsWith("-")) {
throw new IllegalArgumentException("Missing value for " + flag);
}
return value;
}
}
return null;
}
}
Debugging Argument Issues
public class ArgumentDebugger {
public static void debugArguments(String[] args) {
System.out.println("=== Argument Debug Information ===");
System.out.println("Total arguments: " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.printf("args[%d] = '%s' (length: %d)%n",
i, args[i], args[i].length());
// Show non-printable characters
for (char c : args[i].toCharArray()) {
if (c < 32 || c > 126) {
System.out.printf(" Contains non-printable char: %d%n", (int)c);
}
}
}
System.out.println("=== End Debug Information ===");
}
}
Command line arguments are fundamental to creating professional Java applications that integrate well with system administration workflows and deployment pipelines. The techniques covered here provide a solid foundation for building robust, configurable applications whether you're deploying simple utilities or complex enterprise systems. For more advanced command line interface development, consider exploring the Apache Commons CLI documentation or the Picocli framework for modern CLI applications with enhanced features.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.