Originally the title Party wanted to write "in-depth JVM", but not too bold, I think a small blog I think it is not enough to explain the JVM, in this article, I would like to introduce you to the JVM a lot of internal knowledge, the concept will be relatively coarse, because too fine content to write, here is certainly not written; , in addition to some official information in the middle, there are some of their own understanding, so please do not fully trust the contents of this article; In addition, this article will be a small part of the text to correct the previous article for the Intern () use of the error, this article will explain the reasons for using the error, the general article content has the following parts:
1. JVM Virtual memory composition and operating system Address Table
2. How the new generated objects change in HeapSize
3. How the virtual machine defines the recovery algorithm
4, the JVM occupies the space besides HeapSize also will occupy what, OutOfMemory kind!
5, correct error: Intern () of the use of the error
OK, let's start with the topic: 1, JVM virtual memory composition and operating system Address Table 1.1. virtual Address Concept
at the OS level is usually mapped to a linear address by the logical address, if the linear address management, if the paging is started, then the linear address will be converted to the corresponding physical address, otherwise it is directly considered a physical address; The address unit used in programming is the logical unit , such as in the C language & means that the specified address is the logical address, and the physical address is not what we think of RAM, but also should include the network card, memory, swap and other related content, which is managed by the OS all can be mapped to the top-level logical unit of the target location, However, most of the cases only need to consider the RAM, especially on the server; the virtual memory address of the JVM and the virtual memory address of the operating system are not a concept, the virtual memory address of the operating system is equivalent to a swap zone partitioned on disk for memory, memory and the page Out and page in, this is not enough for the physical memory itself, and the address space is sufficient, once the program appears page out of these cases, the program will become very slow, and the JVM's virtual memory is in a valid space to allocate a continuous linear address space, Because the JVM wants to manage its own memory, the allocated heap memory is inside its own heapsize, because it implements some of the complexities that are caused by the management of non-contiguous heap processing from the memory itself, that is, when the JVM initializes, it loads a large memory unit, The internal operations are then done internally by themselves. 1.2. Memory allocation
General C language Allocation memory is the initialization of the corresponding basic content and code snippet loading, but does not load the runtime stack memory allocation, that is, when running to a specific function through malloc, Callloc, realloc and other parties to apply for the region, These zones must be reassigned from the operating system and must be released using the Delete method after the use is complete, and it is found that the OS heap will inevitably produce a lot of memory fragmentation in the process of memory application and release, causing you to request a large amount of memory free,c++ Logical connection is required, resulting in a decrease in the speed of the application, of course, Linux uses a block of memory divided into a number of different sizes to better deal with this problem, but the fragment still exists, but the idea is really good, and the JVM is how to complete the processing of fragments, the later chapter will say The JVM will request a large amount of memory from the OS at the time of initialization, and the JVM requires that the address space be contiguous (not physically contiguous), that all programs are allocated in this internal area and managed by themselves, so it is internally equivalent to doing a small OS-to-memory management, So the JVM is trying to make Java programmers do not care about which platform to write code on, but you must care about how Java manages memory;
Linear address as the actual physical memory increases, will cause the page table is very large, and even lead to multi-layer page table, such as memory up to 96G this class, then this will be very cumbersome to manage (normally the next page is only 4 K, you can figure out how many management addresses you need to point to this 4 K, This management address is too large, but also need other management address to manage this address, it will lead to multi-tier address, possibly to the end, a large memory of 40% are used to manage memory, the real use is conceivable, so in the Linux high version of the memory addressing aspects of the improvement, is to support large pages to support (in fact, it is done through a suite, not the OS itself), such as a page size of 1M, but there are some risks inside, it requires large page memory or put down your memory, but you can not put part of your process in the large page memory, Part of the OS management of the small page memory, that is, either this piece put down, or put in other places, it may lead to both sides just a little bit worse, the OS side can use swap, but the system will be very slow, and swap a lot of cases will certainly be down. 1.3. Memory allocation status
A large process if the initialization needs to allocate a large amount of memory space, memory space will typically go through two state conversion process, first of all the memory must be Free State can be allocated, if it is indeed the state and space is sufficient, then it will first occupy a large hole, in Java heapsize is the-XMX parameter, which is the maximum memory space of the JVM virtual machine (note that-XMX does not contain permsize space), this pit is not allowed to be occupied by other processes, the state of the memory is: Reserved state, when the need to use the space, Memory will be commited state, in the JVM initialization is the-XMS state of memory space, in this state of memory if found not enough to use (physical memory), the swap area will occur, the program will become very slow, but will not cause downtime, And a lot of times at this time to locate the reason, so we have to let the physical memory is not enough to expose the phenomenon can be found, as for the location is not a program code problem, we will directly disable swap memory; One problem is that since the memory of the reserved can not be occupied by other processes, Why do you daoteng back and forth between these two states? Isn't that a more expensive one? The JVM in the process of going back and forth Daoteng will cause the capacity of each region to change correspondingly, inevitably lead to the process of FULLGC, then how is the JVM usually set on the server side? The description is gradually refined later in the article. 1.4.JVM Memory Organization
About the JVM memory organization, the previous time to talk about Java garbage collection has been mentioned, but not too thin, some may be mistaken, so here based on the knowledge of the operating system and the official part of the information continue to go deep, dare not say exactly right, but at least more deeply than before, First, look at the organization graph of a JVM memory unit given by Oracle:
In fact, I have seen many times this figure is very faint, because before the memory allocation in the commited and reserved difference, so that I thought that this picture is that the Java heapsize is composed of more than n parts, and also contains heapsize, In fact, after a lot of data access, especially to see some monitoring tools, only to know that the official information is also a misunderstanding, hehe, through simplification, I draw this picture I want to help you understand the JVM's approximate memory division (this is only referring to the JVM's own memory, That is heapsize and permsize part, the rest of the article is explained later), here only the above graphics stand up to draw, it seems to be convenient to understand a lot (personal feeling):
In other words, you first need to separate the two large plates of the JVM, one is heapsize, that is, the left part, the right part is the size of permsize, and heapsize is divided into a large area of young and old, the young region is divided into three parts, One is Eden and two survivor areas of the same size, noticing that people will find out why there is also a virtual area inside each area, which is what we said above without commited at that time, it was occupied by the address list, it can not be occupied by other processes, At that time the general operating system hints that this is a block of space, but in fact, can only be used by themselves, which has been mentioned above, as to why we explain later, here to ask some questions, that is why the JVM to propose so many regional division to manage it? If an area can be managed, why bother? So many areas are useful, and we will elaborate on this part in the allocation of the second chapter of the object. 2. How does the new generated object change in HeapSize 2.1.java New Object creation method
people who have learned Java first may not know the new keyword, which is the keyword that creates an object, what does the JVM do for you when the new operation occurs? Let's put this problem down, and for the JVM initialization loading, let's say what else is in addition to new, is to get a new instance by java.lang.Class.forName the dynamic state, of course, the method has overloads, also through the dynamic state through ClassLoader, what is dynamic loading? Why is there a dynamic load for new? And what does the JVM initialize do? What is the difference between dynamic loading and new? That's what we're going to talk about, and it's a big chunk of what's in PermSize. What to do with 2.2.JVM initialization
After the JVM has requested an address list from the OS, and then it needs to initialize, what does initialization do? JVM startup is equivalent to a process, of course, it can start the child process, here I we only consider a single process, process startup must initialize some content, C or C + + it will be the corresponding global variables and code snippets and other content in memory compiled into the corresponding instruction set, and what the JVM did? JVM It also needs to do some operations; First, each process must have at least one boot process, which is what we call the main, which is associated with the bootstrap process, and the associated Association (that is, the import). The JVM will form the contents of these associations into a large JVM network for relationships between classes and guarantee that each class has its own private pool, where they are placed in PermSize, the permanent generation of many Chinese translations, Each class has its own private pool to manage its own structure, and for a Java program source file, write a description of the program, generate class is the description of the information in the byte format (in this process will automatically do some simple logic merge work), The byte format is a byte-code format, that is, the basic format of each 8 bit bits, as long as the character set is uniform, for each operating system is recognized by the format, the JVM needs to do is to translate these unified cognitive format information to the corresponding operating system instructions or hardware instructions, So the real meaning of the JVM is to write a unified JRE for each operating system: the Java Runtime Environment, which is available to all systems, and the initialization that loads the definition of class into memory for conversion and compression, which in turn forms the original type description and execution order, Without confusion, but not the corresponding operating system instructions (the corresponding operating system instructions are known at runtime), such as description type, scope, access permissions and so on, this part of the space depends on the number of classes, that is, the size of your project, PermSize also contains other content, And only under normal circumstances will not occur GC, but some time it will still occur GC, continue to explain in the following, after the load is completed, they naturally have their own memory in the pool address, to find that he must have a corresponding list, the base of the list must be a symbol vector, that is, a symbol based on the name vector, Then when new occurs, it will look for the corresponding class in the symbol vector, find and then convert the symbolic address to the corresponding class address, and this content will only be reproduced once, can be used directly, from which to find the definition of class, allocating memory in a heap places some of the organizational units of its definition part with the head of the object, which are independent of each other as you add the Synchronize keyword in front of the method body, for non-Static methods, the different objects this keyword is not affected by each other, that is, if multiple threads call the object is not the same, only in the method (non-static method) of the body above the addition of synchronized this for multi-threaded synchronization is not valid (more on the knowledge of multithreading, such as lock, Atomic and other aspects of the knowledge is not the content of this article, the discussion is no longer discussed here; note that there is no mention of the Application object and the dynamic loading, the dynamic loading of the class is generally not when the JVM is initialized to the perm, but the runtime dynamically loaded in, Like the JDBC driver, almost all of us use dynamic loading to dynamically load different database connections, which is the question we raised in the previous section, what does dynamic loading do? It is responsible for the runtime loading the definition of some classes, not initialization, of course, when you go through the full name to load, they will be from the symbol vector to find whether the class has been loaded, if it has been loaded directly to use, otherwise from the corresponding package to get the class definition, and then loaded up, The unit of loading is also in class, not in the jar package, here please if you do not abuse dynamic loading, one is caused perm instability, and the other is its efficiency is certainly not new high, because it needs to go through the symbol vector to find whether there, there is no reload, You can then instantiate one or more instances with newinstance, and, of course, use it to give your program a very high level of flexibility in some special cases. 2.3. Pointers and instances in memory applications
The previous section of the
Memory request has been addressed to address space and symbolic references to the corresponding data structure, which is no longer mentioned here, the object as a whole, in the heap, in the JVM's original intention, it wants the new application of memory is continuous, although the definition of the heap is to make the memory is randomly allocated, but for the entire JVM , it wants to allocate the memory is more continuous, that is, in a more striped way to allocate, the benefits are several, one is so very simple, after the streamlined situation now a new translation to machine code only need about 10 instructions, near and C language, so in the high version of the JDK, New's overhead is no longer a reason for the slow Java virtual machine, and there is no need to try to minimize the new, but also do not misuse, the performance of the disorderly definition of unnecessary objects; second, another advantage, when the memory is more contiguous, memory in the allocation there is no similar to a large number of fragmentation problems, resulting in running a period of time, A lot of fragmentation, when you need to apply for a large amount of memory, you need to find a lot of places to logically compose, and lead to unnecessary waste allocation space; A simple memory allocation string a = new string ("abc"); What is the action of such a code? A is equivalent to a pointer to the object, the size of a long length, which can be supported to any conceivable memory size, it is not stored in the heapsize, but placed in the stack, by the OS to dispatch management, that is, when A's function area is completed, This pointer will be broken, the string in Java is no longer a character array in C or C + +, but a wrapped object, which is why Java says it is an object, because it wraps the original ecological content and makes the program easier to write. Here, incidentally: In earlier JDK, the JVM is not a pointer directly to the first address in the allocation heap, but first a handle space, which holds the definition and structure information of some of the objects that are being said, that is, the location is found, and then the position is converted to the corresponding object. But at that time the object header information is not so full now, that is, a part of the handle content is placed in a separate space, now the JDK is no more like that. 2.4. Where to put the memory allocation and how to move the
Finally back to the topic above, where is the memory allocated in the heap? That's what we're talking about. In the Eden area of the young area of HeapSize, where new objects are mostly placed (excluding a very large object's special case), there is a particularly interesting place in Java design, Is it in the newly generated object it thinks that most of your objects should be destroyed, as in Java Web applications, a list request, the content of the request may be 2K, after the request is completed, this content is generally not necessary, That is, in his original consideration, it did not consider yourself at the application level to do the page cache operation; Well, when the memory is not enough, here refers to the commited space is not enough, then Java will do an action, that will be the young space to be recycled, Because of the newly generated object, Java thinks this space is not very large, and most of it should be killed content, so many times Java will use a single-threaded copy algorithm (you can also set to multi-threaded), about the core of the algorithm in the third chapter will say, here in short understand to find the living object, Copy it into one of the survivor areas, and in the next operation, copy the live and previous surivor of Eden to another survivor, which is why you set up two survivor zones, and after the copy, the Eden area is empty, The other survivor is also empty and can be completely removed entirely directly, so it is very fast, and the target of the copy is also continuous, and the newly generated objects begin to allocate space from the initial location of Eden.
When the object is copied to a survivor every time (alive), the Java Virtual machine will record the number of times the object has been moved, when the number of times to a certain extent, that is, the official document is said to be old enough, the memory that it is not easy to write off, This will be moved to the second area of the tenured area, which can also be controlled by itself.
In addition, in the general default situation when the recovered memory still occupies more than 70% of the actual current commited memory, then the virtual machine will begin to expand these memory, and when the recovered memory is less than 40%, the virtual machine will reduce this part of memory, But other threads are still not available (this parameter is also configurable, as explained at the end of the article), so shrinkage and expansion will inevitably lead to some problems, but Java's original intention is to let you no longer use the table of addresses, the size of the reclaimed memory is smaller, Because the young region is generally used single-threaded recovery, this time period is suspended, so it is considered less memory use when the memory of the speed should be faster, but, contrary to the actual, we just need to use a large amount of memory, just want to speed up the recovery speed, When memory usage is small, recycling is irrelevant, so we often recommend setting-XMS and-XMX to the same size, instead of going back and forth Daoteng.
Under the description, the following three case objects are promoted to the old area :
1, in Eden and survivor can be minor GC multiple times, this number more than-xx:maxtenuringthreshold
2, in the occurrence of minor GC, found to survivor can not drop these objects, will enter old.
3, in the new Application object, greater than half the Eden area of the size of the direct entry to old, you can also set the parameter-xx:pretenuresizethreshold This parameter specifies that when the value is exceeded directly into the old.
When the above object is moved to the tenured area, this area is generally very large, occupying the vast majority of the space of heapsize, if it occurs a memory recovery, it can not be copied back and forth like just now, so the price is too high, and this area can be said to be a test object will be moved over, It is not easy to be destroyed in the probability of the object will be moved over; Then, we think at this time is the reverse calculation, that is, to find the object to be destroyed, destroy it, about the algorithm is the third chapter below to say, in short, the object will be stored here.
Why is Java in the area of young Daoteng, and in the tenured area will continue to do compression, which is what we said earlier, it wants to be relatively contiguous memory, Java in the Yong region, it is not a lot of content that can be left, so the cost of copying is not very large, So it thinks that the back and forth copy is a suitable method, and the tenured area it uses the purge, after a certain number of times to compress the way, of course, this number of times you can set yourself, at the end of the article has parameters, and it does not use a similar operating system according to the plate size and other series of algorithms to complete, This is what I am more puzzled about, but generally speaking, this algorithm is still feasible, I hope that in the division of some strategies can have more flexibility, so that can be more flexible in the use of more applications, so much the more confusing is that the architecture itself if the frequency is not high-low page cache, Performance is not measurable, perhaps less than the cache is lower, depending on the situation. What content does 2.5.Perm usually store
Perm In addition to storing the class definition above, there is a static code snippet, a class variable of the final static type, a string constant, and the contents of the string being intern, as well as what I wrote wrong in the last chapter. , how to deal with the constant pool, and whether the constant pool will be GC, is also what we need to explain the content of the perm permanent generation, how should be configured so that it can be recycled, at the end of the article has a corresponding description, please check it yourself; however, for the size of Perm, it is generally not recommended to do GC , that is, reasonable to use perm, in the program runs the most perm is the string constant, especially if a large number of use intern, it will cause a lot of perm expansion, but also the last part of the content to be explained, but intern is not useless, Because you can say this: if it is not useful, Java does not need to put the string constant in a separate place, it has many advantages, as long as the appropriate time to use the constant pool this area can improve performance when necessary, specifically in the last chapter to explain. 3, virtual machine How to define the recovery algorithm 3.1. The first virtual recovery algorithm is divided into two parts
One part is the object's lookup algorithm, and the other is how to really recycle it. Generally there are two types of lookups:
a) reference count: I don't want to mention reference counting in this article, because it's the most primitive and the most junk algorithm, and it's the reason why the lower version of the JDK is surprisingly slow, but in order to explain the following questions, Reference counting is the number of pointers to each object that is specifically recorded by the Java Virtual machine, and when a pointer points to it or is assigned a value, the counter is incremented by 1, but the pointer to it is =null or out of scope, and the JVM reduces the corresponding counter by 1, which is simple, but slow to death. Not only surprisingly slow operation, because to do a simple assignment to go to a lot of places to find a large number of things, and one will be very difficult to detect the memory leak, that is, when two or more objects there is a circular cross-reference, At this point their reference count will never be equal to 0 (such as using a doubly linked list or using a complex collection class after each other's references), that is, the garbage collector will never think this is garbage (of course, the complex algorithm can be solved, but the algorithm is very complex, it may be more slowly garbage collection), Finally, this garbage collection method inevitably leads to the process of memory traversal operation. The reference count is as follows:
b) Reference tree traversal : is actually a graph, just have root, it follows the object's root handle to find the living node, and mark down, the rest of the node is not labeled is dead node, these objects can be recycled, or the living node can be copied away, Depending on the area in the HeapSize and the algorithm, it is roughly as shown (objects: B, G, D, J, K, L, F are garbage objects, although they also have a mutual direction, but not by the root node can traverse to, note here is the pointer is one-way):
3.2. Memory recovery
The above method we can find the memory can be used, or that the memory can be recycled, more time we are certainly willing to do less things to achieve the same purpose, we will be based on the general situation of different algorithms to make the system performance to achieve a better degree, First of all, what is the algorithm for memory recycling or what is its experience?
a): Mark clear Algorithm , which is a relatively primitive algorithm, that is, through the above lookup tag, we do not mark the object of the space release process, although very primitive, but it is the basis of all subsequent algorithms, the advantages of simple, the defect is caused by the same memory fragments as other languages , to solve these fragments through more complex algorithms, the other drawback is that this process if used in larger memory will result in long-time external service stops (of course, this stop is not as long as the legend, but relatively long compared to the computer, as to how long is also related to the JDK version and vendor, Bea used to test under the 1G JVM, there is 300M space is free space, according to the test result is 30ms stop service time, I think this time should be acceptable, but it has its own test scenario, can not fully explain the problem, and generally in the case of single-threaded reference, Conventional recycling will be at least several times longer than this time, or even more than 10 times.
b): Mark clear compression, the algorithm is also relatively primitive, it is to solve the above algorithm can not be compressed space problem, but not replaced, because it is caused by another problem is longer service stop, because compression is a space copy to a more continuous place, Instead of compressing the data itself, many times they are used together, such as how many times they are purged and then compressed once.
c) Replication recycling : That is, the development of the JVM in the process of the algorithm, now basically can only see some of the ideological shadow in the inside, but there is no way, that is, divide it into 2 the same size, and then copy the live node back and forth, so that the memory waste caused by a very large, It's not just half the problem of waste, and the cost of each copy is very large, because it involves copying the entire JVM's live node.
d) Incremental recovery : This is a predecessor of modern garbage collection, it is to do is to solve the replication recovery algorithm is a problem, is the space cost of each replication is very large problem, at this time it will be divided into the memory of the plate, these plates, each internal use of the replication algorithm, That is, there is no solution to the problem of space waste, the process of recycling has not been refined, although the recovery speed is faster, and will only result in a partial stop service, but for different plate size, different life cycle of the object is not divided open.
e) Generational collector : The generational collector is another incarnation of incremental collection, or continuation bar, which divides the plates according to the life cycle into the above-mentioned plates, each plate can be recycled using different algorithms, which is the biggest difference from incremental recovery, At this point, the JVM can be recycled to achieve better results, but because the JVM after the life cycle partition is the specified plate, so according to the memory size of the custom plate is not possible, at least now it seems to have not, so in the recycling process if the memory is large recycling, especially the old area of the recovery , so concurrent recycling has to happen.
f) Concurrent reclamation : the so-called concurrent Recycle refers to the external access at the same time, the Java collector is still doing the recycling work, the original I think that concurrent recycling is not possible, because you need to know that memory needs to be recycled, you can not let the memory continue to be applied and released, But Sun's people are still more talented, there is a way to let him do it concurrently, the concurrent collector will actually pause, but the time is very short, it does not start to recover from the beginning of the search, marking, clear, compressed or copy process completely suspended service, it found a few times longer, one is the mark, Because this recycling is generally facing the old age, this area is generally very large, and generally most of the objects should be alive, so the mark time is very long, there is a time is compression, but compression does not have to be done every time the GC is compressed, and the copy is generally not used in the old age, so temporarily do not consider ; so they came up with the idea that the first short stop is to find the root of all the objects, which is very easy to find, and very fast, and when found, the GC starts to tag the live node from these root nodes (which can be used in parallel), and then when the tag is complete, there may be a new Memory requests and is discarded (Java itself does not have the concept of memory release), at which time the JVM will record the incremental information in this process, and for the old age, it will have to go through the survivor Daoteng many times before entering the old age, so it will generally be very small in this increments, and the probability that it will be released is not very large (the JVM does not do pagecache, if it does not do the cache completely, and the probability of pageout and Pagein is not appropriate); The JVM quickly marks the internal nodes based on these incremental information, which is also very fast, Can start recycling, because there are not many nodes to kill, so this process is also very fast, compression in a certain time after a special operation, the pause time in the hotspot version, that is, Sun's JDK is configurable, when the specified time range can not be recycled, The JVM will adjust the corresponding size, if you do not want it to adjust, when setting the size of each area, the use of quantitative, rather than proportional to control, when the use of concurrent recovery algorithm, generally for the old age zone, will not wait for memory less than 10% when the recovery will be initiated, Because concurrent collections are allowed to be allocated at the time of collection, it may be too late, so the JVM may start to start the GC for the old age around 68% when it is recycled.
g) Parallel recovery: Parallel recycling refers to the process of parallel garbage collection using multiple CPUs for the JVM, which can be set up to use parallel recycling for the younger generation and older generations.
Well, the recovery algorithm here, then how to use a good recovery algorithm, after looking at the above introduction, whether the JVM has a general understanding, specific details, you can slowly practice, at the end of the article to give some common Java Virtual machine memory settings parameters of the description, but not authoritative, It needs to be based on the actual situation.
What memory does the Java virtual machine consume in addition to consuming basic memory? 4, the JVM occupied by the space in addition to HeapSize will occupy what
In general, for many years of learning, and even many years of Java people, once see Outofmemeory (Oom), think heapsize not enough, and then crazy increase-xmx value, but heapsize is only one part, when you go to do an experiment, That is, the Java startup directly in the program crazy new some threads out, until the memory overflow, when the-XMS-XMX set the larger the number of threads will get less, why? Because Oom is not heapsize enough to cause, and by many kinds of circumstances.
First look at how the operating system partition memory to the application system, in fact, in the win 32, Linux 32 system, address bus 32-bit theory should be able to support 4G memory space, but when you set the initialization memory on the win 32 if 2G, will be error, said this block space can not be done, First of all, the default Win32 system will be given to the kernel in accordance with the 50% scale, and the other part to the application of memory, that is, the operating system kernel part whether or not to use, this half will not give you, and there is 2G, it is in the system extension part, that is not kernel part, There are a lot of static area and the contents of the dictionary table, so to partition a continuous 2G memory to the JVM on Win 32 is not possible, win 32 proposed a win 3G mode, seemingly can be divided into 3G space, in fact, it is only the kernel part of the reduction is the management of the part of the reduction, That is, a part of the external to use, and Win 32 is used in memory 2G position to do some hands and feet, let you allocate continuous 2G no possibility, generally in the win 32 platform, in the case of sufficient physical memory to the JVM division of space is generally 1.4~1.5g around, the specific data has not been tested , while Linux 32 is similar to the win 3G mode, but it is usually distributed in a non-cluttered situation, the JVM can generally be divided into 2G size. Linux Hugemem is an extended version, can be divided into larger space, but there are some other costs, can theoretically support to 4G to the application, that is, Kenel is independent; Solaris X86-32 and Aix 32 systems, similar to Linux 32 platforms.
Why do we have to set aside some space? Who are these spaces for?
When you apply for a thread, it's in addition to the overhead of the thread's internal objects, the cost of the thread itself, is to require the OS to schedule the completion, generally speaking, the OS thread and the virtual machine has a one by one corresponding, but will vary according to the operating system, some may have only one, In short heapsize outside of that part of the space is not run off, where it put? is placed in the stack, so the above-XSS is set this, after JDK 1.5, the size of each thread is set to the default stack cost of 1M, we are accustomed to reduce this overhead.
All right, I know. Pointers, threads are outside the heapsize, what else?
When you use the native method, that is, JNI, call local other languages, such as C, C + + in the program using a similar method of malloc to open up memory, is not in the heapsize, but in the local OS control, and this part of the space without the corresponding release command, You need to call other native methods inside the corresponding Finalize method to complete the release of the corresponding object, otherwise this will become an OS-level memory leak until the JVM process restarts or goes down (the operating system records the relationship between the process and the corresponding thread and the heap memory. However, the OS will not reclaim this part of the memory until the process is released again.
In addition, when working with Javanio and JDBC, Stream series operations, when interacting with the terminal, a memory area is formed in another location that is not in the heapsize.
So the common Oom phenomenon has the following kinds:
1, heapsize overflow, this need to set the Java Virtual machine memory situation
2, PermSize overflow, you need to set perm related parameters and check the memory of the constant situation.
3, OS address space is not enough, that is, there is not so much memory allocation, this is generally the start of the times wrong.
4, swap space frequent interaction, the process is directly crash off, in different operating systems will reflect different situations.
5, native thread overflow, note the size of the threads stack, as well as the limitations of its own operating system.
6, Directbytebuffer overflow, this class is generally in doing some nio operation, or in some cases using bytebuffer, in allocating memory using allocatedirect and using some framework to indirectly invoke a similar method, Causes direct memory allocation (such as Mina in the use of iobyte to call, when the parameter is set to TRUE is allocated as direct memory, the so-called direct memory is the OS-defined memory, and does not need to copy the process indirectly from the program, to improve performance, but if no manual recycling is not recycled), The resulting buffer problem, such as the output of a large amount of content, enter a large amount of content, at this time need to try to limit its size.
Use a lot of tool area to detect Java memory such as: Jstat (only see HeapSize and PermSize), jmap (very fine things), JPS (Java ps-ef hehe), jdb (this is not a monitoring tool ha, this is the Debug tool), Jprofile (graphics support, but can be remotely connected), etc. jconsole (you can see the heapsize, permsize+native mem size (this is called: non-heapsize), and so on, the use of the trend map), VISUALVM ( Highly recommended things, graphical view, you can see the memory unit allocation, exchange, recycling, mobile and so the whole process, very clear display of the JVM's global resources, the other pmap can show very clear information, can be accurate to a Java process within each detail, And you can see that heapsize is just a small part (the most complete on the Solaris operating system, some processes under Linux may not be understood), or it can be viewed in the/proc/process number/maps (where you can see the start address of the memory address cell. Contains the address range of the reserved and the address range of the commited), the global resource uses the operating system top command and the free command to see, IBM has a GCMV freeware download tool is also good, Win32 has a wmmap tool is a good tool.
Using the appropriate tools to observe the corresponding content, when the memory is observed to use from scratch, rise, and then in a smooth trend, then the JVM should be more stable, if it is found that after a period of smoothing, there is a spike, this must be problematic, as to what the problem, According to the previous study and the actual situation we can analyze; when it starts, the smoothing process occurs slowly, but always rises to the pole, then one needs to know when physical memory is available, and the other is a small amount of memory leaks (the JVM has a memory leak, but its memory leaks are not C, C + + Memory leaks in the. 5, correct error: Intern () of the use of the error
The last chapter, I myself correct my own mistakes, the previous article, that is, about the use of intern, recently did some in-depth research on him, because before and many classmates, hear what others recommend crazy use, know the point principle is also point probably, not in-depth study of internal content.
I have said in the article that any system uses the most data type must be a string, regardless of what to do, so there is a lot of research on string processing, it is recommended to use Java friends in a large number of comparisons do not use equals, and recommend the use of intern (), But I recently found that I was wrong, I apologize to everyone here, because it may mislead many friends;
First I began to doubt myself when I was trying to say, if intern can be efficient, then equals is not in the string there is no need to exist, at that time for me to understand only a constant pool of an address comparison, like a two number of compare, Just need a single command of the CPU to complete; So I started to do two experiments, one is the most primitive, the initial level of the method using a single-threaded loop 1 million calls Equals and intern equivalent, and using a different length of the string to do the comparison, Find equals unexpectedly faster than intern, and with the increase in the length of the string, equals will be significantly faster and intern, and then the use of multi-threaded testing is also obtained the same effect, I can not believe that their insistence on the theory is completely harmonious, and then calm down must be faced, With a lot of authoritative readings, I've found that my understanding of the JVM's constant pool is just a little superficial, so I've done more in-depth research.
The original intern method was called in the perm in the string privatization constant pool to find the corresponding content, while looking for although the hash can be located in some of the smaller linked list, but still need to be in the list by contrast, the comparison method is still equals, that is, the cost of throwing away the hash , intern at least 0 to multiple objects inside the equals operation, and if not, but also in the constant pool to open a space to record, if there is a return address, that is, the constant pool to ensure that each string constant is unique, this cost is of course large, And if used in the business code will cause the perm area to increase continuously;
So, I think again: since equals is more efficient than him, why use intern? And the algorithm of equals to the raised here string-by-character comparison of the process I am really difficult to get into the eye, but also really feel that they are not reconciled to their own theory is so easy to be harmonious, because I have in a lot of procedures so used, so I did not make a big mistake, because I have participated in the project is too much, And there's a similar code I wrote in the framework, and I finally found out that I could be half wrong, that is, the history of the record maybe I have half the similar code is wrong; Intern still useful, I first made a test, that is, with an already intern good object, let him and a constant to do the equivalent, the number of cycles and the same as above, the result I expected to happen, that is more than equals faster than n multiples, with the increase in length, Will show a more obvious advantage, because the intern is always the address, and the length is irrelevant, so I think how to use it, is to return in the program by a string similar to a number of type determination, such as: When doing a sqlparser, often according to the data type to do different actions, This way, if you use equals to pay a lot of overhead in each cycle, especially many of the database type is very large, the worst is from top to bottom each string match once, of course, the length of unequal overhead is very small, the length of equal cost is large; intern I intern these schema messages beforehand, That is, they have pointed to the constant pool, when the real match, it does not need to use intern, but the direct match, that is, to put this overhead in the initialization process, the runtime we do not increase its overhead.
Therefore, the individual is committed a mistake, and the past is also very public propaganda, hehe, now feel a little silly, hope to see some recommendations with what new things, never in no research understand him to use it, and even abuse it, at least after some simple test, but for the modern many complex things, Some simple tests are not enough to explain the problem, just like the cost of lock and synchronize, if you use a simple loop, you will find that the cost of the new version of lock will be more expensive than the synchronized, it is suitable for concurrency, read and write concurrency, So the real need to figure out or study inside.
Finally, my personal expectation of the JVM is that the JVM does a lot of different algorithms between the plates, and the JVM does not want the programmer to care about the memory, but some special applications require a lot of support from the JVM, but some companies have modified the JVM kernel to fit a particular application. However, we would prefer the standard JVM to provide a more flexible memory management mechanism, not just the configuration, because the configuration is dead, and in many cases it is subject to scalability constraints, as many times we think that many of the objects themselves are not recycled or are not easily recycled at all. There is no need to go to Young's space and other business Daoteng together, for often do page cache system, and page cache hit rate is not particularly high (95% or higher), is not very low (such as 80% below), this time, displacement to fast not slow, And will lead to the recovery in the old times, I personally hope that these spaces can be independent, and even can be controlled and specified by the program, of course, the JVM can itself go to the default, especially according to some special object class type or object size, these details can be used by some of the corresponding default GC means to complete , can also be manually specified, of course, by default, the schema can be based on the original mode, so that the JVM's memory adjustment flexibility will be more relaxed, so that it can be used in all kinds of situations as long as the corresponding means of configuration and program adjustment can be done to target.
This article contains a lot of personal insights, if there is no place, please give us a lot of advice! This is the end of the article, the content is not deep, the details of the problem, the details of the discussion.
Common Parameters JVM parameter configuration (Java VM Hotspot TM 1.6)
- -xms is the space that is initialized to HeapSize, which is the size of the commited.
- -xmx is the largest heapsize space, some of which have not yet been commited, but have been reserved by the process, and have now been in a commit space for a long time (jdk1.1 has a-mx for the space containing the handler table).
- -xmn Set the space size of young, at which point NewSize and maxnewsize are identical, or the-xx:newsize=128m is set separately
- -xx:permsize = 64M and-xx:maxpermsize= 64M is the initial size and maximum size of the permanent generation.
- -xx:newratio= 3 is the initial size ratio of Tenured:young (set to no longer set this value), and Young takes up the 1/4 size of the entire heapsize.
- -xx:survivorratio= 6: The size of Eden:survivor, at which point a survivor takes up 1/8 of young, while Eden occupies 3/4 of the size.
- -xss=256k is threadstack space size, JDK 1.5 defaults to 1M, and in IBM's JDK there are-xoss parameters (at this point each thread occupies 256K size of the stack space)
- -xx:maxtenuringthreshold =3: Typically an object is moved to the old area after how many times the GC has passed.
- -XX:+USEPARNEWGC: Enables the parallel recycle algorithm for the Yong region.
- -XX:+USEPARALLELGC: An older parallel recovery algorithm.
- -XX:+USEPARALLELOLDGC: Uses a parallel recovery algorithm for the tenured region.
- -xx:parallelgcthread=10: The number of parallel, the general and the number of CPUs corresponds.
- -xx:+useadaptivesizepollcy: The collector automatically adjusts some proportions according to the actual situation and the recovery algorithm.
- -xx:cmsfullgcsbeforecompaction= 3: How many times the GC will be compressed after fragmentation
- -xx:+usecmsfullcompactatfullcollction: Open old age compression
The following 3 parameters are permanent with recycle parameters:
- -xx:+useconcmarksweepgc-xx:+cmsclassunloadingenabled
- -xx:+ CMSPermGenSweepingEnabled to recycle a permanent band without requiring a number in jdk1.6: -xx:+cmspermgensweepingenabled
- -xx:minheapfreeratio This refers to the amount of space remaining, starting to reduce the memory of commited;
- -xx: Maxheapfreeratio refers to the percentage of space remaining, starting to increase commited's memory until the-XMX size.
- -xx:maxgcpausemillis refers to the maximum time the GC pauses, and when this time is exceeded, the JVM adjusts the memory scale appropriately (provided that the proportional-based Yong and settings are used).
- -XX:+USECONCMARKSWEEPGC launches a concurrent GC, typically for the tenured zone. The
- -xx:+cmsincrementalmode increments the GC, cutting the memory in chunks and distributing it across multiple partial GC.
- - xx:cmsinitiatingoccupancyfraction under concurrent GC, because one side is used, once the GC is not enough, the GC will not be available. By default, the GC is used when you use 68%, which allows you to adjust the actual value.
The approximate parameter setting is these, but the GC itself has many parameters, especially when combined with the application or with the specific hardware, and BEA and IBM have their own JDK, here are some parameters they support, some parameters are not supported, In some platforms and even hardware can support special parameters to control (such as in some Intel series of multi-CPU machine, through its NUMA architecture, can set the corresponding parameter support, node and CPU can achieve division of load, the General Service is SMP, and the mainframe is mostly MPP) , similar to the above concurrent GC in general will not be compact compression, because it wants to reclaim the time is short, but full compact compression time must not be so short, so in some special applications some use fixed width of memory size, after recycling regardless of spare memory, Because each memory size is so large, so to deal with, of course, this will inevitably lead to a lot of memory waste, but its advantage is that there can be no compact and there is no memory allocated to the allocation of the problem.
This article goes from:
Http://www.importnew.com/18242.html
Understanding the JVM (1)--Object Assignment & Recovery algorithm