Java Performance Optimization
In this page:
Tuning JVM Flags
Adjusting JVM heap flags like -Xms (initial heap size) and -Xmx (maximum heap size) lets you tune how much memory your application starts with and can grow into, which matters because too small a heap causes frequent GC pauses and too large a heap wastes system memory.
Example: Tuning JVM Flags
public class Main {
public static void main(String[] args) {
// Run with: java -Xms256m -Xmx512m Main
Runtime runtime = Runtime.getRuntime();
System.out.println("Max heap: " + runtime.maxMemory() / (1024 * 1024) + "MB");
}
}
Login to try C/C++/Java/PHP code in the editor
Choosing Efficient Collections
Choosing the right collection type for the job limits unnecessary lookup overhead -- use an ArrayList when you mostly iterate or index sequentially, and a HashMap when you need near O(1) lookups by key, rather than defaulting to whichever collection is most familiar.
Example: Choosing Efficient Collections
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(); // fast sequential iteration/indexing
Map<String, Integer> map = new HashMap<>(); // near O(1) lookup by key
list.add(1);
map.put("key", 1);
System.out.println(list.get(0) + " " + map.get("key"));
}
}
Login to try C/C++/Java/PHP code in the editor
Avoiding Object Allocation
Limiting unnecessary temporary object allocation reduces the workload the garbage collector has to handle, since every short-lived object still has to be scanned and reclaimed eventually -- a pattern especially worth watching inside hot loops that run millions of times.
Example: Avoiding Object Allocation
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(); // reuses one buffer instead of many temporary Strings
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
System.out.println(sb.length());
}
}
Login to try C/C++/Java/PHP code in the editor
Thread Pool Configuration
Using a thread pool via an Executor lets you reuse a fixed set of worker threads across many tasks instead of creating and destroying a new thread for every unit of work, which avoids the real startup and teardown cost that comes with each new OS thread.
Example: Thread Pool Configuration
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(4); // reused workers, not a new thread per task
for (int i = 0; i < 8; i++) pool.submit(() -> {});
pool.shutdown();
System.out.println("8 tasks handled by 4 reused threads");
}
}
Login to try C/C++/Java/PHP code in the editor
Lazy Initialization Pattern
Lazy initialization defers an expensive operation -- a database load, a large object construction -- until the moment it's actually needed, rather than paying that cost unconditionally at startup even for code paths that end up never being used.
Example: Lazy Initialization Pattern
public class Main {
static class ExpensiveResource {
private static ExpensiveResource instance;
static ExpensiveResource get() {
if (instance == null) instance = new ExpensiveResource(); // deferred until first actually needed
return instance;
}
}
public static void main(String[] args) {
System.out.println(ExpensiveResource.get() != null);
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 19 topics to unlock
0/19 topics done
Complete these topics first:
- Java Reflection API
- Java Annotations Advanced
- Java Garbage Collection
- Java Memory Management
- Java Performance Optimization
- Java Advanced Interview Questions
- Java CompletableFuture
- Java Atomic Classes
- Java Locks & Semaphores
- Java Concurrent Collections
- Java Cryptography Basics
- Java Hashing (MD5, SHA)
- Java SSL & HTTPS
- Java Logging (Log4j/SLF4J)
- Java Serialization Advanced
- Java Interview Questions Advanced
- Java Connection Pooling
- Java Test Driven Development
- Java Integration Testing