Skip to main content

Java Performance Tips

This guide covers Java performance optimization techniques, best practices, and tools for writing efficient Java applications.

🎯 Core Performance Principles

JVM Understanding

  • Garbage Collection: Understand GC algorithms and tuning
  • Memory Management: Heap vs. stack, object lifecycle
  • JIT Compilation: HotSpot optimization and warm-up
  • Class Loading: Impact on startup performance

Measurement First

  • Profile Before Optimizing: Use profilers to identify bottlenecks
  • Benchmark Properly: Use JMH for microbenchmarks
  • Monitor Production: Use APM tools for real-world performance
  • Set Performance Goals: Define measurable performance targets

🔧 Memory Optimization

Object Creation

// Bad: Creating many temporary objects
public String concatenateBad(List<String> items) {
String result = "";
for (String item : items) {
result += item; // Creates new String each iteration
}
return result;
}

// Good: Use StringBuilder
public String concatenateGood(List<String> items) {
StringBuilder sb = new StringBuilder();
for (String item : items) {
sb.append(item);
}
return sb.toString();
}

// Better: Use String.join (Java 8+)
public String concatenateBest(List<String> items) {
return String.join("", items);
}

Collection Usage

// Bad: Using wrong collection type
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
numbers.add(0, i); // O(n) operation - very slow!
}

// Good: Use appropriate collection
List<Integer> numbers = new LinkedList<>();
for (int i = 0; i < 1000000; i++) {
numbers.add(0, i); // O(1) operation
}

// Better: Use ArrayList and add at end
List<Integer> numbers = new ArrayList<>(1000000);
for (int i = 0; i < 1000000; i++) {
numbers.add(i); // O(1) amortized
}

Memory Leaks Prevention

// Bad: Static references to objects
public class MemoryLeak {
private static List<Object> cache = new ArrayList<>();

public void addToCache(Object obj) {
cache.add(obj); // Objects never garbage collected!
}
}

// Good: Use weak references for caches
public class GoodCache {
private static Map<String, WeakReference<Object>> cache = new HashMap<>();

public void addToCache(String key, Object obj) {
cache.put(key, new WeakReference<>(obj));
}

public Object getFromCache(String key) {
WeakReference<Object> ref = cache.get(key);
return ref != null ? ref.get() : null;
}
}

🚀 Algorithm Optimization

Loop Optimization

// Bad: Inefficient loop
public int findMax(int[] array) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}

// Good: Enhanced for-loop (cleaner, similar performance)
public int findMaxEnhanced(int[] array) {
int max = Integer.MIN_VALUE;
for (int value : array) {
if (value > max) {
max = value;
}
}
return max;
}

// Better: Use streams (Java 8+)
public int findMaxStream(int[] array) {
return Arrays.stream(array).max().orElse(Integer.MIN_VALUE);
}

String Operations

// Bad: Repeated string operations
public boolean containsKeywords(String text, List<String> keywords) {
for (String keyword : keywords) {
if (text.toLowerCase().contains(keyword.toLowerCase())) {
return true;
}
}
return false;
}

// Good: Compile patterns once
public class KeywordMatcher {
private final List<Pattern> patterns;

public KeywordMatcher(List<String> keywords) {
this.patterns = keywords.stream()
.map(keyword -> Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE))
.collect(Collectors.toList());
}

public boolean containsKeywords(String text) {
return patterns.stream().anyMatch(pattern -> pattern.matcher(text).find());
}
}

📊 Concurrency Performance

Thread Pool Usage

// Bad: Creating threads manually
public void processTasks(List<Runnable> tasks) {
for (Runnable task : tasks) {
new Thread(task).start(); // Creates unlimited threads!
}
}

// Good: Use thread pool
public void processTasksGood(List<Runnable> tasks) {
ExecutorService executor = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors()
);

for (Runnable task : tasks) {
executor.submit(task);
}

executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

// Better: Use parallel streams (Java 8+)
public void processTasksParallel(List<Runnable> tasks) {
tasks.parallelStream().forEach(Runnable::run);
}

Synchronization

// Bad: Excessive synchronization
public class SynchronizedCounter {
private int count = 0;

public synchronized void increment() {
count++; // Synchronized even for single-threaded use
}

public synchronized int getCount() {
return count;
}
}

// Good: Use atomic classes for simple operations
public class AtomicCounter {
private final AtomicInteger count = new AtomicInteger(0);

public void increment() {
count.incrementAndGet(); // Lock-free operation
}

public int getCount() {
return count.get();
}
}

// Better: Use LongAdder for high contention
public class HighPerformanceCounter {
private final LongAdder count = new LongAdder();

public void increment() {
count.increment(); // Better under high contention
}

public long getCount() {
return count.sum();
}
}

🛠️ I/O Performance

File Operations

// Bad: Reading file byte by byte
public String readFileBad(String filename) throws IOException {
FileInputStream fis = new FileInputStream(filename);
String content = "";
int byteRead;

while ((byteRead = fis.read()) != -1) {
content += (char) byteRead; // Very slow!
}

fis.close();
return content;
}

// Good: Use buffered reading
public String readFileGood(String filename) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) {
StringBuilder content = new StringBuilder();
String line;

while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}

return content.toString();
}
}

// Better: Use Files.readAllLines for small files
public List<String> readFileLines(String filename) throws IOException {
return Files.readAllLines(Paths.get(filename));
}

// Best: Use Files.readString (Java 11+)
public String readFileString(String filename) throws IOException {
return Files.readString(Paths.get(filename));
}

Network I/O

// Bad: Synchronous I/O blocking
public String fetchUrlBad(String url) throws IOException {
URLConnection connection = new URL(url).openConnection();
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream())
);

StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}

reader.close();
return response.toString();
}

// Good: Use HttpClient (Java 11+)
public CompletableFuture<String> fetchUrlAsync(String url) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.build();

return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body);
}

📈 JVM Tuning

Garbage Collection

# G1GC (Good for most applications)
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 MyApp

# ZGC (Low latency, large heaps)
java -XX:+UseZGC MyApp

# Parallel GC (High throughput)
java -XX:+UseParallelGC -XX:ParallelGCThreads=4 MyApp

Memory Settings

# Set heap size
java -Xms512m -Xmx2g MyApp

# Set metaspace size
java -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m MyApp

# Optimize for containers
java -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 MyApp

🔍 Performance Monitoring

JVM Tools

# JVisualVM - GUI monitoring
jvisualvm

# JConsole - Basic monitoring
jconsole

# JFR - Flight Recorder (Java 11+)
java -XX:StartFlightRecording=duration=60s,filename=recording.jfr MyApp

# JHSDB - Serviceability agent
jhsdb jmap --pid <pid> --heap

Profiling Tools

// Use JMH for microbenchmarks
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class MyBenchmark {

@Benchmark
public String stringConcatenation() {
String result = "";
for (int i = 0; i < 1000; i++) {
result += i;
}
return result;
}

@Benchmark
public String stringBuilderConcatenation() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
return sb.toString();
}
}

🔗 Language-Specific Performance

📍 Visit Us

🏫 VD Computer Tuition Surat

VD Computer Tuition
📍 Address
2/66 Faram Street, Rustompura
Surat395002, Gujarat, India
📞 Phone / WhatsApp
+91 84604 41384
🌐 Website

Computer Classes & Tuition — Areas We Serve in Surat

AdajanAlthanAmroliAthwaAthwalinesBhagalBhatarBhestanCanal RoadChowkCitylightDumasGaurav PathGhod Dod RoadHaziraJahangirpuraKamrejKapodraKatargamLimbayatMagdallaMajura GateMota VarachhaNanpuraNew CitylightOlpadPalPandesaraParle PointPiplodPunaRanderRing RoadRustampuraSachinSalabatpuraSarthanaSosyo CircleUdhnaVarachhaVed RoadVesuVIP Road
📞 Call Sir💬 WhatsApp Sir