Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
271: Working with System Properties and Runtime Info
Imagine you're a freelance contractor hired to renovate a house. Before you even pick up a hammer, you do two things. First, you look for a "house manual" left on the kitchen counter—this tells you things like where the main water shut-off is, the local trash pickup schedule, and any specific rules the owner has for the property. Second, you check your own gear—do you have enough gas in the truck to get to the hardware store? Do you have enough hands on deck to lift that heavy beam? If you don't have the right resources, the plan changes.
In Java, System.getProperties() is your house manual. It's a collection of key-value pairs that describe the environment your program is living in. The Runtime class, on the other hand, is you checking your own gear. It tells you how much memory the JVM has allocated and how many processors it can actually use.
Reading the Environment's Manual
Most of the time, you'll use System.getProperty(String key) to grab a specific piece of info. Java provides a bunch of these by default. I often find myself checking os.name or user.home when I'm writing code that needs to handle file paths differently on Windows versus Linux.
String os = System.getProperty("os.name");
String userDir = System.getProperty("user.home");
System.out.println("Running on: " + os + " at " + userDir);
It's a simple way to make your app "aware" of where it is without hardcoding paths that will inevitably break the second you push your code to a server.
Passing Your Own "House Rules"
Here is where it gets actually useful for real projects. You aren't stuck with just the defaults. You can pass your own properties into the JVM at startup using the -D flag. I use this constantly to toggle between "development" and "production" modes without recompiling the code.
If you run your app like this: java -Dapp.environment=production -Dapp.cache.size=512 MyApp, those properties become available inside your code immediately.
String env = System.getProperty("app.environment");
if ("production".equals(env)) {
// Connect to the expensive, high-availability database
System.out.println("Connecting to Production DB...");
} else {
// Use the local H2 database for testing
System.out.println("Using local dev environment.");
}
Just a heads-up: getProperty returns null if the key doesn't exist. I usually provide a default value using a simple ternary or a wrapper method to avoid those annoying NullPointerExceptions.
Checking the JVM's Vital Signs
While system properties are about the *environment*, the Runtime class is about the *execution*. Since Runtime uses a Singleton pattern, you can't just call new Runtime(). You have to use Runtime.getRuntime().
I've seen plenty of juniors write loops that crash with OutOfMemoryError because they didn't realize how limited their heap was. You can actually query the JVM to see how much breathing room you have left.
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory(); // Max the JVM will attempt to use
long allocatedMemory = runtime.totalMemory(); // Current size of the heap
long freeMemory = runtime.freeMemory(); // Unused memory within the allocated heap
System.out.println("Max Memory: " + maxMemory / (1024 * 1024) + " MB");
System.out.println("Available Processors: " + runtime.availableProcessors());
Knowing the availableProcessors() is particularly handy if you're setting up a ThreadPoolExecutor`. Why hardcode 4 threads when you can scale your parallelism to the actual hardware the app is running on?
📋 Practical Task
Build a Memory-Aware Environment Logger
Create a Java class that performs a "system health check" upon startup. Your program should do the following:
- Check for a system property named
app.mode. If it is set to"debug", print a detailed report of the OS name and user home directory. If it's not set or set to anything else, print"Standard mode active". - Use the
Runtimeclass to calculate and print the amount of actual free memory available to the JVM (total memory minus free memory) in Megabytes. - Print the number of available CPU cores to determine if the system is "Multi-core" (more than 1) or "Single-core".
Testing your code: To verify the debug logic, run your program from the terminal using: java -Dapp.mode=debug YourClassName
There are no comments for now.