Each java application will run in a specific Java Virtual Machine Instance. I am really getting confused on below aspects and Googling has confused me even more. Different articles on different sites.
If I have a web service written in java it will need a JVM instance to run.So can JVM be made a daemon process?
If yes when we run any other java application it will use this instance of JVM or create a new one?
Main memory available in any machine is constant. When we start n java processes simultaneously without providing any initial heap size how is the heap size distributed among processes?
Is there any process that manages n number of JVM instances or is it managed by OS itself?
When stop-the-world happens during an GC are other JVM instances(different threads I assume) affected?
1) If I have a web service written in java it will need a JVM instance to run. So can JVM be made a daemon process?
Yes it can. How it is done depends on the O/S and on the web server container itself.
2) If yes when we run any other java application it will use this instance of JVM or create a new one?
No. Each Java application uses an independent JVM.
Each JVM is a separate process, and that means there is no sharing of stacks, heaps, etcetera. (Generally, the only things that might be shared are the read only segments that hold the code of the core JVM and native libraries ... in the same way that normal processes might share code segments.)
3) Main memory available in any machine is constant. When we start n java processes simultaneously without providing any initial heap size how is the heap size distributed among processes?
The mechanism for deciding how big to make the heap if you don't specify a size depends on the JVM / platform / version you are using, and whether you using the "client" or "server" model (for Hotspot JVMs). The heuristic doesn't take account of the number or size of other JVMs.
Reference: https://stackoverflow.com/a/4667635/139985
In practice, you would probably be better off specifying the heap size directly.
4) Is there any process that manages n number of JVM instances or is it managed by OS itself?
Neither. The number of JVM instances is determined by the actions of various things that can start processes; e.g. daemons scripts, command scripts, users typing commands at the command line, etcetera. Ultimately, the OS may refuse to start any more processes if it runs out of resources, but JVMs are not treated any different to other processes.
5) When stop-the-world happens during an GC are other JVM instances(different threads I assume) affected?
No. The JVMs are independent processes. They don't share any mutable state. Garbage collection operates on each JVM independently.
see How to Daemonize a Java Program?
new instance of JVM will be created
the same way as memory is shared between all other processes
it is managed by O/S
other instances are not affected
If your instances have to coordinate their work, you can create single main instance which would run/stop other instances.
You did not explain why you need multiple JVM instances. Probably, single instance would work better.
Related
I have a Java application which uses 10 threads. Each thread opens a Matlab session by using the Java Matlabcontrol library. I'm running the application on a cluster running CentOS 6.
The used physical memory (Max Memory) for the whole application is around 5GB (as expected) but the reserved physical memory (Max Swap) is around 80GB which is too high. Here a short description from the cluster wiki:
A note on terminology: in LSF the Max Swap is the memory allocated by
an application and the Max Memory is the memory physically used (i.e.,
it is actually written to). As such, Max Swap > Max Memory. In most
applications Max Swap is about 10–20% higher than Max Memory
I think the problem is Java (or perhaps a mix between Java and Matlab). Java tends to allocate about 50% of the physically available memory on a compute node by default. A java process assumes that it can use the entire resources available on the system that it is running on. That is also the reason why it starts several hundred threads (although my application only uses 11 threads). It sees 24 cores and lots of memory even though the batch system reserves only 11 core for the job.
Is there a workaround for this issue?
Edit: I've just found the following line in the Matlabcontrol documentation:
When running outside MATLAB, the proxy makes use of multiple
internally managed threads. When the proxy becomes disconnected from
MATLAB it notifies its disconnection listeners and then terminates all
threads it was using internally. A proxy may disconnect from MATLAB
without exiting MATLAB by calling disconnect().
This explains why there are a lot of threads created but it does not explain the high amount of reserved memory.
Edit2: Setting MALLOC_ARENA_MAX=4 environment variable brought the amount of reserved memory down to 30GB. What value of MALLOC_ARENA_MAX should I choose and are they other tuning possibilities?
Each time I run a Java application in my machine, am I creating an instance of the JVM? If so, am I also getting a single heap (with the size I specify) for this JVM instance and its Java application running?
Or do I have a single heap and a single JVM instance in my machine where or java applications run and reserves a heap space for their processes? If this one is true, do I have to care about a global JVM heap size when specifying the heap space to reserve for each application? I would not want to ask for more memory than the JVM has.
Yes, each time you run java you get a new JVM with its own heap. There have been some attempts to try alternatives (for example, IBM's multitenancy feature), but none seem to have provided enough advantages to be worthwhile.
I have a Tomcat webapp which does some pretty memory and CPU-intensive tasks on the behalf of clients. This is normal and is the desired functionality. However, when I run Tomcat, memory usage skyrockets over time to upwards of 4.0GB at which time I usually kill the process as it's messing with everything else running on my development machine:
I thought I had inadvertently introduced a memory leak with my code, but after checking into it with VisualVM, I'm seeing a different story:
VisualVM is showing the heap as taking up approximately a GB of RAM, which is what I set it to do with CATALINA_OPTS="-Xms256m -Xmx1024".
Why is my system seeing this process as taking up a ton of memory when according to VisualVM, it's taking up hardly any at all?
After a bit of further sniffing around, I'm noticing that if multiple jobs are running simultaneously in the applications, memory does not get freed. However, if I wait for each job to complete before submitting another to my BlockingQueue serviced by an ExecutorService, then memory is recycled effectively. How can I debug this? Why would garbage collection/memory reuse differ?
You can't control what you want to control, -Xmx only controls the Java Heap, it doesn't control consumption of native memory by the JVM, which is consumed completely differently based on implementation. VisualVM is only showing you what the Heap is comsuming, it doesn't show what the entire JVM is consuming as native memory as an OS process. You will have to use OS level tools to see that, and they will report radically different numbers, usually much much larger than anything VisualVM reports, because the JVM uses up native memory in an entirely different way.
From the following article Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )
Maintaining the heap and garbage collector use native memory you can't control.
More native memory is required to maintain the state of the
memory-management system maintaining the Java heap. Data structures
must be allocated to track free storage and record progress when
collecting garbage. The exact size and nature of these data structures
varies with implementation, but many are proportional to the size of
the heap.
and the JIT compiler uses native memory just like javac would
Bytecode compilation uses native memory (in the same way that a static
compiler such as gcc requires memory to run), but both the input (the
bytecode) and the output (the executable code) from the JIT must also
be stored in native memory. Java applications that contain many
JIT-compiled methods use more native memory than smaller applications.
and then you have the classloader(s) which use native memory
Java applications are composed of classes that define object structure
and method logic. They also use classes from the Java runtime class
libraries (such as java.lang.String) and may use third-party
libraries. These classes need to be stored in memory for as long as
they are being used. How classes are stored varies by implementation.
I won't even start quoting the section on Threads, I think you get the idea that
-Xmx doesn't control what you think it controls, it controls the JVM heap, not everything
goes in the JVM heap, and the heap takes up way more native memory that what you specify for
management and book keeping.
Plain and simple the JVM uses more memory than what is supplied in -Xms and -Xmx and the other command line parameters.
Here is a very detailed article on how the JVM allocates and manages memory, it isn't as simple as what you are expected based on your assumptions in your question, it is well worth a comprehensive read.
ThreadStack size in many implementations have minimum limits that vary by Operating System and sometimes JVM version; the threadstack setting is ignored if you set the limit below the native OS limit for the JVM or the OS ( ulimit on *nix has to be set instead sometimes ). Other command line options work the same way, silently defaulting to higher values when too small values are supplied. Don't assume that all the values passed in represent what are actually used.
The Classloaders, and Tomcat has more than one, eat up lots of memory that isn't documented easily. The JIT eats up a lot of memory, trading space for time, which is a good trade off most of the time.
You should also check for CPU usage and garbage collector.
It is possible that garbage collection pauses and the CPU gc consumes further slow down your machine.
In my application i run some threads with untrusted code and so i have to prevent a memory overflow. I have a WatchDog wich analyses the time of the current thread (the threads were called in serial).
But how i can determine the memory usage?
I only know the memory usage of the whole VM with Runtime.totalMemory()?
If there is a possibility to find out the usage of the thread, or the usage of the single process it would be great. With the memory usage of the process i could calculate the usage of the thread anyway.
Since a JVM executing a Java program is a Java process you don't have to worry about that. All threads share the same memory space in the JVM process.
Hence it is sufficient to rely on
Runtime.totalMemory()
Runtime.freeMemory()
A Java application cannot control the amount of memory or (or CPU) used by its threads,
irrespective of whether the threads are running trusted or untrusted code. There are no APIs for doing
this in current generation JVMs. And there are certainly no APIs for monitoring a thread's usage of memory. (It is not even clear that this is a meaningful concept ... )
The only way you can guarantee to control the resource usage of untrusted Java code is to run the code in a separate JVM, and use operating system level resource controls (such as ulimit, nice, sigstop, etc) and "-Xmx" to limit that JVM's resource usage.
Some time back, a Sun produced JSR 121 aimed at addressing this issue. This JSR would allow an application to be split into parts (called "isolates") that communicated via message passing, and offered the ability for one isolate to monitor and control another. Unfortunately, the Isolate APIs have yet to be implemented in any mainstream JVM.
What you need to do is to run the untrusted code in its own process/JVM. This is possible using the JNI interfaces (if your operating system permits it).
I have two Java programs. On my computer, one of them uses 9MB of RAM and the other uses 77MB. But when I upload them to a server, the same programs use 382MB and 186MB! Is there a way to stop this from happening?
How do you measure the memory usage in each case? Different operating systems have a different concept of what constitutes "memory usage".
64-bit systems require more memory than 32-bit systems due to the increased pointer (reference in Java speak) size. Are you using a 32-bit OS and JVM on your desktop computer?
Are you using different JVM options? A moderately active Java application usually ends up using all the memory that is permitted by the -Xmx option, to minimize the CPU time spent on garbage collection. In addition, the default maximum heap space is determined in relation to the available physical memory - if the server has more memory, the Java applications are bound to use more memory as well.
Server JVMs (see the -server JVM option) have different settings and favor performance over memory usage. The -server option is the default on 64-bit systems.
Are you absolutely certain that the application load is the same in both cases?
It is quite common for applications to allocate virtual memory in large chunks to improve performance and efficiency. Nobody bothers to optimize such things because they have no effect. If you don't actually have a problem, there's nothing to fix.
Virtual memory is not a scarce resource. Attempting to reduce the consumption of vm is wasted effort.
How did you measure that numbers?
Comparing the numbers of Windows Task Manager and ps(1) on Linux is futile because they are computed differently. For example shared libraries and shared memory are attributed differently on both platforms. Also the memory management is completely different.
If, on the other hand, you refer to numbers gathered from within your apps via Runtime (or similar), then you have to look how the JVM was started with what parameters. Most important are the parameters -Xmx and -Xms but you might lookup several others in the doc of either java or javaw.
Related to point 1:
How to measure actual memory usage of an application or process?
Unless you've explicitly set it (e.g command line arguments like -Xmx128M), the default maximum heap size of the JVM depends on the amount of RAM available.