My linux free memory is 4942356kb before I run a java application.my StartUp paramter use -Xmx2048m and -Xms2048m to make the max heap memory and initial heap memory to be 2G.But I find that after I start up the application,my linux system free memory is decreasing step by step , instead of total 2G memory was consumed after starting up.Anyone can tell me the reason and mechanism?
And another question , My jvm startup parameter is -XX:+PrintGCDetails -Xss512k -Xmx4096m -Xms4096m -Xloggc:gc_01221859.log
, and free memory before start up is 5G, after 1 hour , I find that this application has already 14,053 threads .Obviously , 14053 * 512k = 7195136 = 7.2G stack memory is consumed, which is obvious larger than system free memory and total memory.Anyone could explain this for me ?
when number of thred is 14053 , I use jcmd <pid> VM.native_memory summary
to dump the Native memory , it output:
Native Memory Tracking:
Total: reserved=8688195KB, committed=8645103KB
- Java Heap (reserved=2181632KB, committed=2181632KB)
(mmap: reserved=2181632KB, committed=2181632KB)
- Class (reserved=5997KB, committed=5997KB)
(classes #8918)
(malloc=5997KB, #7418)
- Thread (reserved=5815888KB, committed=5815888KB)
(thread #11139)
(stack: reserved=5752332KB, committed=5752332KB)
(malloc=35936KB, #44562)
(arena=27620KB, #22266)
- Code (reserved=51385KB, committed=8293KB)
(malloc=1465KB, #2689)
(mmap: reserved=49920KB, committed=6828KB)
- GC (reserved=85657KB, committed=85657KB)
(malloc=5889KB, #155)
(mmap: reserved=79768KB, committed=79768KB)
- Compiler (reserved=294KB, committed=294KB)
(malloc=196KB, #400)
(arena=98KB, #2)
- Internal (reserved=52609KB, committed=52609KB)
(malloc=52609KB, #283728)
- Symbol (reserved=13406KB, committed=13406KB)
(malloc=10010KB, #98269)
(arena=3396KB, #1)
- Memory Tracking (reserved=301363KB, committed=301363KB)
(malloc=301363KB, #28396)
- Pooled Free Chunks (reserved=179933KB, committed=179933KB)
(malloc=179933KB)
- Unknown (reserved=32KB, committed=32KB)
(mmap: reserved=32KB, committed=32KB)
the top output:
top - 18:47:02 up 397 days, 26 min, 1 user, load average: 3.68, 3.46, 2.58
Tasks: 164 total, 1 running, 163 sleeping, 0 stopped, 0 zombie
Cpu(s): 2.5%us, 0.6%sy, 0.0%ni, 96.7%id, 0.1%wa, 0.0%hi, 0.0%si, 0.1%st
Mem: 5990984k total, 5144764k used, 846220k free, 11564k buffers
Swap: 0k total, 0k used, 0k free, 132748k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
11513 wuchang 20 0 12.1g 3.7g 15m S 188.8 64.9 41:46.42 java
1264 wuchang 20 0 17116 1240 900 R 1.8 0.0 0:00.02 top
1 root 20 0 19232 364 84 S 0.0 0.0 0:02.57 init
the free output is:
total used free shared buffers cached
Mem: 5990984 5786744 204240 0 12012 134092
-/+ buffers/cache: 5640640 350344
Swap: 0 0 0
I have wrote a very simple java code whose work is just create thread:
public class CreateThread {
private static int threadNumber = 0;
public static void main(String[] args) {
while (true) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Thread " + threadNumber++);
while(true){
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
}
}
After wrapper it into a jar file run it in linux like this:
java -Xss512k -jar CreateThread.jar > /home/wuchang/test
it created totally 32313 threads before report :
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:714)
at CreateThread.main(CreateThread.java:22)
And another question ,why the error is OutOfMemory instead of StackOverflow?
Some limit of my linux system thread is :
[wuchang@hz10-45-88 ~]$ cat /proc/sys/kernel/threads-max
93335
[wuchang@hz10-45-88 ~]$ ulimit -u
46667
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
UPDATE 1 : Everytime I run my java application with different startup parameters, including three cases:
case 1: -Xss512k -Xmx4096m -Xms4096m
case 2: -Xss512k -Xmx2048m -Xms2048m
case 3: -Xss256k -Xmx2048m -Xms2048m
of course, since my application is a pressure test, after a period of time ,the process will be killed automically by OS.I have record the last top output before it is killed below:
case 1:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18136 wuchang 20 0 15.4g 4.3g 6456 S 99.3 75.0 36:16.22 java
case 2:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9689 wuchang 20 0 15.0g 4.2g 14m S 98.6 73.0 55:36.62 java
case 3:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8237 wuchang 20 0 10.1g 4.2g 9284 S 100.6 74.0 60:43.95 java
each time before I run start up the process, system free memory is about 5G. from above output , each time the VIRT vary a lot , but RES stay approximately the same. So ,my additional question is:
What does the MAX VIRT depend on before my process is killed by OS?
How can I estimate the maximum thread according to 1)OS free memory before startup up and 2)the JVM startup parameter?
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
UPDATE 2 :
I have run the code provided by @Ivan:
public class CreateThread {
private static int threadNumber = 0;
public static int doRecursiveCall(int i) throws StackOverflowError {
return doRecursiveCall(++i);
}
public static void warmupNativeStack() {
int sideEffect;
try {
sideEffect = doRecursiveCall(0);
} catch (StackOverflowError ignored) {
return;
}
System.out.println("Never happend " + sideEffect);
}
public static void main(String[] args) {
while (true) {
new Thread(new Runnable() {
@Override
public void run() {
warmupNativeStack();
System.out.println("Thread " + threadNumber++);
while (true) {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}).start();
}
}
}
The result is:
java -Xss512k -Xmx2048m -Xms2048m -jar CreateThread.jar
totally 8600 threads are created.before exit,the max VIRT is 8.7G and max RSS is 4.5G
java -Xss256k -Xmx2048m -Xms2048m -jar CreateThread.jar
totally 16780 threads are created.before exit,the max VIRT is 8.7G and max RSS is 4.6G
Experiment show that in this case, the max VIRT and RSS has nothing to do with jvm startup parameter,they stay the same.So ,according to the experiment result of UPDATE 1 AND UPDATE 2, I guess, the reason that my app is killed by OS may be that the RSS memory has reached the limit ,instead of the number of thread or the total VIRT , right?