Is there a way to find out how much memory my java thread is taking in the VM?
For example, using stack trace dump, or some other means.
Thanks
Java threads use the heap as shared memory. Individual threads have their stack (the size of which you can set via the -Xss command line option, default is 512KB), but all other memory (the heap) does not belong to specific threads, and asking how much of it one specific thread uses simply does not make sense.
Related
I have an application with degrading performance.
I have analyzed its behavior using Java VisualVM. I detected a group of threads in a pool that increase their allocated bytes on each execution.
So, I know where the problem is, however I can't find the root of the problem by looking at the code. I would like to look at the objects that these threads are accumulating. Is there a way to do this?
I did a heap dump, but I can't find a way to get only the instances that represent the memory allocated by these threads.
A Java application starts up with one heap for all threads. Each thread has its own stack.
When a Java application is started, we use the JVM option -Xms and -Xmx to control the size of heap and -Xss to control the stack size.
My understanding is that the heap being created becomes a "managed" memory of JVM and all the object being created are placed there.
But how does the stack creation work? Does Java create a stack for each thread when it is created? If so, where exactly the stack is on the memory? It is certainly not in the "managed" heap.
Does JVM create stack from native memory or does it pre-allocate a section of managed memory area for stack? If so, how does JVM know how may threads will be created?
There are a few things about thread stacks that the Java specification tells us. Among other things:
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.
Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.
Specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation.
Now, if we focus on JVM implementations such as HotSpot, we can get some more information. Here are a few facts I've collected from different sources:
The minimum stack size in HotSpot for a thread seems to be fixed. This is what the aforementioned -Xss option is for.
(Source)
In Java SE 6, the default on Sparc is 512k in the 32-bit VM, and 1024k in the 64-bit VM. ... You can reduce your stack size by running with the -Xss option. ...
64k is the least amount of stack space allowed per thread.
JRockit allocates memory separate from the heap where stacks are located. (Source)
Note that the JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures.
There is a direct mapping between a Java Thread and a native OS Thread in HotSpot. (Source).
But the Java thread stack in HotSpot is software managed, it is not an OS native thread stack. (Source)
It uses a separate software stack to pass Java arguments, while the native C stack is used by the VM itself. A number of JVM internal variables, such as the program counter or the stack pointer for a Java thread, are stored in C variables, which are not guaranteed to be always kept in the hardware registers. Management of these software interpreter structures consumes a considerable share of total execution time.
JVM also utilizes the same Java thread stack for the native methods and JVM runtime calls (e.g. class loading). (Source).
Interestingly, even allocated objects may be sometimes located on stack instead on heap as a performance optimization. (Source)
JVMs can use a technique called escape analysis, by which they can tell that certain objects remain confined to a single thread for their entire lifetime, and that lifetime is bounded by the lifetime of a given stack frame. Such objects can be safely allocated on the stack instead of the heap.
And because an image is worth a thousand words, here is one from James Bloom
Now answering some of your questions:
How does JVM knows how may threads will be created?
It doesn't. Can be easily proved by contradiction by creating a variable number of threads. It does make some assumptions about the maximum number of threads and stack size of each thread. That's why you may run out of memory (not meaning heap memory!) if you allocate too many threads.
Does Java create a stack for each thread when it is created?
As mentioned earlier, each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. (Source).
If so, where exactly the stack is on the memory? It is certainly not in the "managed" heap.
As stated above, Java specification allows stack memory to be stored on heap, technically speaking. But at least JRockit JVM uses a different part of memory.
Does JVM create stack from native memory or does it pre-allocate a section of managed memory area for stack?
The stack is JVM managed because the Java specification prescribes how it must behave: A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language. One exception are Native Method stacks used for native methods. More about this again in the specification.
JVM uses more memory than just the heap. For example Java methods,
thread stacks and native handles are allocated in memory separate from
the heap, as well as JVM internal data structures.
Further reading.
So to answer your questions:
Does Java create a stack for each thread when it is created?
Yes.
If so, where exactly the stack is on the memory?
In the JVM allocated memory, but not on the heap.
If so, how does JVM knows how may threads will be created?
It doesn't.
You can create as many as you'd like until you've maxed out your JVM memory and get
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
EDIT:
All of the above refers to Jrockit JVM, although i find it hard to believe other JVMs would be different on such fundamental issues.
Is it possible to make some sub-set of threads (e.g. from specific ThreadPool) allocate memory from own heap? E.g. most of the threads are allocating from regular shared heap, and few worker threads are allocating from individual heaps (1:1 per thread).
The intent is to ensure safe execution of the code in shared environment - typical worker is stateless and is running on separate thread, processing of one request should not consume more than 4MB of heap.
Update #1
Re: But why are you worried about "safe execution" and unpredictable increasing of heap consumption?
The point is about safe hosting of arbitrary 3rd party java code within my process. Once of the points is to not get "Out of Memory" for my entire process because of bugs in the 3rd party code.
Update #2
Re: As of limiting memory usage per thread, in Java the language it's impossible
According to my investigation before I've posted this question my opinion is the same, I'm just hoping I'm missing something.
The only possible alternative solutions for my use-case as I see right now are ...
1) How much memory does my java thread take? - track thread memory usage in some governor thread and terminate bad threads
2) Run Java code on my own JVM - Yes it is possible. You can download a JVM open source implementation, modify it ... :)
Check out Java nonblocking memory allocation — threads are usually allocating memory from their own allocation blocks already. So if the speed is of concern, Sun has done it for you.
As of limiting memory usage per thread, in Java the language it's impossible. Whether it is possible (or makes sense) in JVM and Java the platform is an interesting question. You can of course do it the same way as any memory profiler does, but I'm afraid the management system will outgrow the application itself pretty soon.
No. There is no concept of this in Java. There is one 'heap' that new allocates from. Java allocation is thread-safe. And why do you think that making more heaps would cause threads to consume less memory?
If you want to control memory usage in a thread, don't allocate things.
You could, in theory, create pools of reusable objects for a purpose like this, but the performance would almost certainly be worse than the obvious alternative.
Threads by design share all the heap and other regions of memory. Only the stack is truly thread local, and this space can be limited.
If you have tasks which you want to run in their own memory and/or can be stopped, you have to run them as a separate process.
I wrote Thread pool class referring http://www.informit.com/articles/article.aspx?p=30483&seqNum=5
Environment: Windows7 4 cp
Executed my program with 70,000 Thread in Windows 7, under JDK 1.5 it went through successfully. Not used vm arguments.
The same Code i tried to execute with 5,000 Thread in Linux enterprise edition which is under Virtual Box with 4GB base memory. with vm arguments -xms512m -xmx1024m. It executes till 2156 threads and throws an exception
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:597)
at testthreadpool.ThreadPool.(ThreadPool.java:38)
at testthreadpool.TestThreadPool.main(TestThreadPool.java:16)
But the same code run perfectly in windows7.
May i know why this error occurs. Does this java code need 1GB memory to run Just 5,000 Threads?...
My actual requirement is to hold a ThreadPool with 10,000 Workthread.
My actual requirement is to hold a
ThreadPool with 10,000 Workthread.
I think you need to revisit your requirement. That in no way is a good idea, and is catastrophic to performance.
As #Yann points out, using 10,000 threads is a really bad idea ... unless you have a machine with thousands of cores. You should take a serious look at your application design.
In the short term, try tuning the default thread stack size with the -Xss... JVM parameter. Also note that stacks are not allocated in heap memory, so your -Xms512m -Xmx1024m option is not reserving space for stacks. On the contrary, it is reserving space that cannot then be used for stacks.
Finally, there may be other things (other than memory for thread stacks) that will limit the number of threads that your application can create.
Threads require a stack, that has to have an initial size. For threads, the initial stack size is by default the stack size reource limit, as shown by ulimit -s, but can be changed by a call to pthread_attr_setstacksize(). (See this other SO question).
Are you on 64-bit?
Don't expect a 32-bit machine to be able to run lots of threads. You may also wish to tweak the stack size. Starting lots of threads uses lots of memory for stacks, and you can't get around that unless you can tolerate smaller stacks.
Checking on x86_64, Linux seems to default to 8M stacks, which means that 1k threads takes 8G stack, so you really want to be careful with that.
I have a standalone Java problem running in a linux server. I started the jvm with -Xmx256m. I attached a JMX monitor and can see that the heap never really passes 256Mb. However, on my linux system when I run the top command I can see that:
1) First of all, the RES memory usage of this process is around 350Mb. Why? I suppose this is because of memory outside of the heap?
2) Secondly, the VIRT memory usage of this process just keeps growing and growing. It never stops! It now shows at 2500Mb! So do I have a leak? But heap doesn't increase, it just cycles!
Ultimately this poses a problem because the swap of the system keeps growing and eventually the system dies.
Any ideas what is going on?
The important question I want to ask, what are some scenarios that this could be a result of my code and not the JVM, kernal, etc. For example, if the number of threads keeps growing, would that fit the description of my observations? Anything similar that you can suggest me to look out for?
A couple of potential problems:
Direct allocated buffers and memory mapped files are allocated outside of the Java heap, and can't conveniently be disposed.
An area of stack is reserved for each new thread.
Permanent generation (code and interned strings) is outside of the usual stack. It can be a problem is class loaders leak (usually when reloading webapps).
It's possible that the C heap is leaking.
pmap -x should show how your memory has disappeared.
Swap Sun vs IBM JVM to test
RES will include code + non-head data. Also, some things that you think would be stored in the heap aren't, such as the thread stack and "class data". (It's a matter of definition but code and class data are controlled by -XX:MaxPermSize=.)
This one sounds like a memory leak in either the JVM implementation, the linux kernel, or in library JNI code.
If using the Sun JVM, try IBM, or vice versa.
I'm not sure exactly how dlopen works, but code accessing system libraries might be remapping the same thing repeatedly, if that's possible.
Finally, you should use ulimit to make the system fail earlier, so you can repeat tests easily.
WRT #1, it's normal for your RSS to be larger than your heap. This is because system libraries and non-Java code are included in the RSS but not the heap size.
WRT #2, Yes, it sounds like you have a leak of some sort. If the system itself is crashing, you are likely consuming too much of a system resources, like sockets, threads, or files.
Try using lsof to see what files the JVM has open. Run this a few times as your memory increases. If the JVM is crashing, be sure to set the -XX:+HeapDumpOnOutOfMemoryError option.
In my experience, the most common cause of non-heap memory leak in Java is thread leak.
A tool you may find useful is jvmtop, which lets you monitor heap size, thread number and other metrics in real time.
Sounds like you have a leak. Can't you do profiling to see which function is driving the memory up? I am not sure though.
If I had to take a stab in the dark, I would say that the JVM you are using has a memory leak.