---
title: "JMeter JVM, Memory & Operating System Tuning"
description: "Scale JMeter injectors for high throughput: JVM heap sizing, G1GC tuning, headless CLI optimization, and Linux kernel TCP/socket configuration."
url: https://docs.jmeter.ai/topics/jmeter-performance-tuning-guide/
lastUpdated: 2026-10-18
source: docs.jmeter.ai
---

# JMeter JVM, Memory & Operating System Tuning

When running high-volume performance tests (thousands of virtual users or tens of thousands of requests per second), the bottleneck is frequently the **load generator itself** rather than the target application. Un-tuned JMeter injectors suffer from heap exhaustion (`OutOfMemoryError`), excessive Garbage Collection (GC) pauses, port exhaustion, and CPU throttling.

This guide provides end-to-end instructions for tuning JMeter’s JVM heap, Garbage Collector, operating system TCP parameters, and test plan efficiency.

---

## 1. JVM Heap Sizing (`setenv.sh` / `setenv.bat`)

By default, Apache JMeter ships with a conservative heap allocation (often 1 GB). For production load generation, allocate 50% to 70% of available system RAM to the JVM heap.

Create a `setenv.sh` (Linux/macOS) or `setenv.bat` (Windows) file in JMeter’s `bin/` directory:

### Linux / macOS (`bin/setenv.sh`):

```bash
#!/bin/sh
# Allocate 8GB min and max heap with G1GC
export HEAP="-Xms8g -Xmx8g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
export GC_ALGO="-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=15"
export JVM_ARGS="-XX:+AlwaysPreTouch -Djava.awt.headless=true"
```

### Windows (`bin/setenv.bat`):

```bat
@echo off
set HEAP=-Xms8g -Xmx8g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
set GC_ALGO=-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=15
set JVM_ARGS=-XX:+AlwaysPreTouch -Djava.awt.headless=true
```

> **Keep -Xms equal to -Xmx**
> Setting the initial heap (`-Xms`) equal to the maximum heap (`-Xmx`) eliminates JVM memory resizing overhead during test execution and guarantees that heap memory is pre-allocated upon startup (`-XX:+AlwaysPreTouch`).

---

## 2. Garbage Collection (GC) Optimization

Use the **G1 Garbage Collector** (default on modern Java versions). Key flags:

- `-XX:+UseG1GC`: Low-latency concurrent collector optimized for multi-gigabyte heaps.
- `-XX:MaxGCPauseMillis=100`: Target maximum pause time goal.
- `-XX:InitiatingHeapOccupancyPercent=45`: Initiates concurrent marking before memory gets dangerously full.
- `-XX:G1ReservePercent=15`: Prevents allocation failures during concurrent cycles.

To log garbage collection events for analysis:

```bash
-Xlog:gc*,gc+phases=debug:file=jmeter_gc.log:time,uptime,pid:filecount=5,filesize=50M
```

---

## 3. Operating System & Kernel TCP Tuning (Linux)

Under high RPS, JMeter opens and closes thousands of TCP sockets per minute. Without kernel tuning, you will encounter `java.net.BindException: Address already in use` or `Too many open files`.

### A. Increase File Descriptor Limits (`/etc/security/limits.conf`)

```text
* soft nofile 655350
* hard nofile 655350
* soft nproc  655350
* hard nproc  655350
```

### B. Optimize TCP Sockets in `/etc/sysctl.conf`

Apply with `sudo sysctl -p`:

```ini
# Enable fast recycling of TIME_WAIT sockets
net.ipv4.tcp_tw_reuse = 1

# Expand ephemeral port range
net.ipv4.ip_local_port_range = 1024 65535

# Reduce TIME_WAIT timeout to 30 seconds
net.ipv4.tcp_fin_timeout = 15

# Increase network connection backlog queue
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 100000

# Increase socket memory buffers
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
```

---

## 4. Test Plan & Execution Architecture Best Practices

| Anti-Pattern (High Overhead) | Tuned Best Practice (Maximum Throughput) |
| --- | --- |
| Running test via GUI | **Always use CLI (`jmeter -n -t plan.jmx`)** |
| Active View Results Tree or Summary Report | **Disable all GUI listeners during load runs** |
| Saving full response data in JTL log | **Save only minimal CSV metrics (`jmeter.save.saveservice.*`)** |
| BeanShell / JavaScript scripts | **JSR223 Groovy with “Cache compiled script” checked** |
| Dynamic `\${var}` inside cached scripts | **`vars.get("var")` inside script body** |
| Heavy DOM XPath extractors | **Boundary Extractor or JSON Extractor** |

---

## 5. Network Interface & DNS Caching

By default, Java caches DNS lookups forever. If load testing microservices behind an AWS ALB or round-robin DNS:

1. In `system.properties`, set DNS cache TTL:

```properties
networkaddress.cache.ttl=10
networkaddress.cache.negative.ttl=0
```

1. In HTTP Request Defaults, check **Use MD5 checksum** only if verifying large file download integrity.

## Continue Learning

→

### Next Practical Step

Create a `bin/setenv.sh` or `bin/setenv.bat` file in your JMeter directory with `-Xms4g -Xmx4g` and verify with the interactive Heap Estimator tool.

📖

### Related Reference

- [Heap Estimator Tool](/tools/heap-estimator/)
- [OutOfMemoryError Heap Playbook](/topics/errors/out-of-memory-heap/)
- [Too Many Open Files (ulimit)](/topics/errors/too-many-open-files-ulimit/)
- [Thread Calculator Tool](/tools/thread-calculator/)

⚠

### Common Mistakes

Allocating more than 80% of total physical RAM to JMeter heap (causing OS kernel page swapping); keeping View Results Tree enabled in headless CLI runs.

🔧

### Troubleshooting

If the test freezes or pauses periodically, inspect GC logs (`jmeter_gc.log`) to verify whether Full GC stop-the-world pauses are occurring.
