Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are some of the details of memory allocation and collection in java garbage collector

2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail some details about memory allocation and collection in java garbage collector. The content of the article is of high quality, so the editor will share it for you as a reference. I hope you will have a certain understanding of the relevant knowledge after reading this article.

1. Disable System.gc ()

Jvm provides a parameter DisableExplicitGC to control whether GC is triggered manually. If you need to disable it, you can use the following configuration:

-XX:+DisableExplicitGC2. System.gc () uses concurrent recycling

By default, even if System.gc takes effect, the entire heap is recycled using the traditional Full GC method, ignoring the UseG1GC and UseConcMarkSweepGC in the parameters, that is, CMS and G1 are not executed concurrently.

Sample code

Public class Demo01 {public static void main (String [] args) {System.gc ();}}

Using-XX:+PrintGCDetails-XX:+UseConcMarkSweepGC, the log is as follows:

[Full GC (System.gc ()) [CMS: 0K-> 372K (174784K), 0.0246450 secs] 2798K-> 372K (253440K), [Metaspace: 2906K-> 2906K (1056768K)], 0.0247414 secs] [Times: user=0.02 sys=0.01, real=0.02 secs]

Using-XX:+PrintGCDetails-XX:+UseG1GC, the log is as follows:

[Full GC (System.gc ()) 1517K-> 368K (819K), 0.0089949 secs] [Eden: 2048.0K (12.0M)-> 0.0B (3072.0K) Survivors: 0.0B-> 0.0B Heap: 1517.6K (256.0M)-> 368.7K (8192.0K)], [Metaspace: 2906K-> 2906K (1056768K)] [Times: user=0.01 sys=0.00, real=0.01 secs]

Obviously, CMS and G1 are not executed concurrently at this time, because there is no concurrency-related information in the log. You can use the following parameters to change this default behavior:

-XX:+ExplicitGCInvokesConcurrent

Using-XX:+PrintGCDetails-XX:+UseConcMarkSweepGC-XX:+ExplicitGCInvokesConcurrent, the log is as follows:

[GC (System.gc ()) [ParNew: 2798K-> 398K (78656K), 0.0010206 secs] 2798K-> 398K (253440K), 0.0010476 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (CMS Initial Mark) [1 CMS-initial-mark: 0K (174784K)] 1797K (253440K), 0.0001720 secs] [Times: user=0.00 sys=0.00 Real=0.00 secs] [CMS-concurrent-mark-start] [CMS-concurrent-mark: 0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-preclean-start] [CMS-concurrent-preclean: 0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (CMS Final Remark) [YG occupancy: 1797 K (78656 K)] [Rescan (parallel), 0.0007200 secs] [weak refs processing] 0.0000066 secs] [class unloading, 0.0001855 secs] [scrub symbol table, 0.0003697 secs] [scrub string table, 0.0001424 secs] [1 CMS-remark: 0K (174784K)] 1797K (253440K), 0.0014769 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-sweep-start] [CMS-concurrent-sweep: 0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-reset-start]

Using-XX:+PrintGCDetails-XX:+UseG1GC-XX:+ExplicitGCInvokesConcurrent, the log is as follows:

[GC pause (System.gc ()) (young) (initial-mark), 0.0024614 secs] [Parallel Time: 1.5 ms, GC Workers: 8] [GC Worker Start (ms): Min: 100.6, Avg: 100.7, Max: 100.8, Diff: 0.2] [Ext Root Scanning (ms): Min: 100.8, Avg: 0.2, Max: 0.3, Diff: 0.3 Sum: 1. 6] [Update RS (ms): Min: 0, Avg: 0, Max: 0, Diff: 0, Sum: 0] [Processed Buffers: Min: 0, Avg: 0, Max: 0, Diff: 0, Sum: 0] [Scan RS (ms): Min: 0, Avg: 0, Max: 0, Diff: 0 Sum: 0] [Code Root Scanning (ms): Min: 0, Avg: 0, Max: 0, Diff: 0, Sum: 0] [Object Copy (ms): Min: 0. 4, Avg: 0. 6, Max: 1. 0, Diff: 0. 6, Sum: 5.] [Termination (ms): Min: 0. 0, Avg: 0. 4, Max: 0. 5, Diff: 0. 5 Sum: 3] [Termination Attempts: Min: 1, Avg: 3, Max: 8, Diff: 7, Sum: 25] [GC Worker Other (ms): Min: 0, Avg: 0, Max: 0, Diff: 0, Sum: 0] [GC Worker Total (ms): Min: 1. 1, Avg: 1. 2, Max: 1. 4, Diff: 0. 3 Sum: 9.8] [GC Worker End (ms): Min: 101.9, Avg: 101.9, Max: 102.0 Diff: 0.1] [Code Root Fixup: 0.0 ms] [Code Root Purge: 0.0 ms] [Clear CT: 0.1 ms] [Other: 0.8 ms] [Choose CSet: 0.0 ms] [Ref Proc: 0.6 ms] [Ref Enq: 0.0 ms] [Redirty Cards: 0.1 ms] [Humongous Register: 0.0 ms] [Humongous Reclaim: 0. 0 ms] [Free CSet: 0.0 ms] [Eden: 2048.0K (24.0m)-> 0.0B (23.0m) Survivors: 0.0B-> 1024.0K Heap: 2009.1K (256.0m)-> 568.1K (256.0m)] [Times: user=0.01 sys=0.00 Real=0.00 secs] [GC concurrent-root-region-scan-start] [GC concurrent-root-region-scan-end, 0.0003924 secs] [GC concurrent-mark-start] [GC concurrent-mark-end, 0.0002255 secs] [GC remark [Finalize Marking, 0.0001208 secs] [GC ref-proc, 0.0000284 secs] [Unloading, 0.0002767 secs], 0.0005331 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC cleanup 1039K-> 1039K (256m) 0.0003741 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Explicit GC like System.gc () will not be recycled concurrently until the ExplicitGCInvokesConcurrent parameter is used, otherwise concurrent recycling will not occur regardless of whether CMS or G1 is enabled or not.

3. A new generation of GC triggered before parallel GC

For parallel collectors (using UseParallelOldGC or UseParallelGC), there is a new generation of GC before each FullGC, which is very different from serial collectors, as shown in the following example:

Public class Demo01 {public static void main (String [] args) {System.gc ();}}

Use the-XX:+PrintGCDetails-XX:+UseSerialGC,gc log as follows:

[Full GC (System.gc ()) [Tenured: 0K-> 367K (174784K), 0.0017465 secs] 2798K-> 367K (253440K), [Metaspace: 2903K-> 2903K (1056768K)], 0.0017770 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

As you can see, System.gc () triggers a Full GC.

Use the-XX:+PrintGCDetails-XX:+UseParallelOldGC,gc log as follows:

[GC (System.gc ()) [PSYoungGen: 2621K-> 528K (7628K)] 2621K-> 536K (251392K), 0.0008817 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (System.gc ()) [PSYoungGen: 528K-> 0K (76288K)] [ParOldGen: 8K-> 368K (175104K)] 536K-> 368K (251392K), [Metaspace: 2905K-> 2905K (1056768K)], 0.0036679 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

As you can see, before triggering FullGC, there is a new generation of GC. Therefore, the Sytem.gc () here actually triggers the GC twice, and the goal is to recycle the new generation first, to avoid handing all the recycling work to one Full GC at the same time, thus minimizing the pause time as much as possible.

If you don't need this feature, you can use the parameter-XX:-ScavengeBeforeFullGC to remove the Cenozoic GC that occurred before FullGC. Run using-XX:+PrintGCDetails-XX:+UseParallelOldGC-XX:-ScavengeBeforeFullGC, and the gc log is as follows:

[Full GC (System.gc ()) [PSYoungGen: 2621K-> 0K (76288K)] [ParOldGen: 0K-> 368K (175104K)] 2621K-> 368K (251392K), [Metaspace: 2906K-> 2906K (1056768K)], 0.0032836 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

As you can see, there is no new generation of gc before Full GC.

4. When does the object enter the old age?

Start-up objects are generated in the eden area

The age of the old object: the virtual machine provides a parameter to control the maximum age of the new generation object: MaxTenuringThreshold, which defaults to 15, that is, the new generation object can be promoted to the old age after a maximum of 15 times of GC. In practice, the actual promotion age of the object is dynamically calculated based on the usage of the survivor area, while MaxTenuringThreshold only represents the maximum age. You can use the parameter TargetSurvivorRatio to set the target utilization of survivor. The default is 50, that is, if the utilization rate of survivor area exceeds 50% after GC, then a smaller age is likely to be used as the promotion age.

Large objects enter the old era: if the object is very large, neither the eden area nor the survivor area of the new generation can accommodate the object, and naturally this object cannot be stored in the new generation. Jvm provides a parameter PretenureSizeThreshold parameter to set the threshold for the object to be promoted directly to the old age, in bytes. As long as the object is greater than the specified value, it will be allocated directly in the old age. This parameter is valid only for serial collectors and ParNew, not for ParallelGC. By default, the value is 0, that is, the maximum promotion size is not specified, and everything depends on the performance.

An example of a large object going directly into the old age:

Public class Demo04 {public static final int _ 1K = 1024; public static void main (String [] args) {Map map = new HashMap (); for (int I = 0; I < 5 * _ 1K; iTunes +) {byte [] b = new byte [_ 1K]; map.put (I, b);}

Run with the parameter-Xmx32m-Xms32m-XX:+UseSerialGC-XX:+PrintGCDetails-XX:PretenureSizeThreshold=1000-XX:-UseTLAB, and the results are as follows:

Heap def new generation total 9792K, used 963K [0x00000007be000000, 0x00000007beaa0000, 0x00000007beaa0000) eden space 8704K, 11% used [0x00000007be000000, 0x00000007be0f0f88, 0x00000007be880000) from space 1088K, 0% used [0x00000007be880000, 0x00000007be880000, 0x00000007be990000) to space 1088K, 0% used [0x00000007be990000, 0x00000007be990000, 0x00000007beaa0000) tenured generation total 21888K, used 5953K [0x00000007beaa0000, 0x00000007c0000000, 0x00000007c0000000) the space 21888K, 27% used [0x00000007beaa0000, 0x00000007bf070408, 0x00000007bf070600, 0x00000007c0000000) Metaspace used 3054K, capacity 4496K, committed 4864K, reserved 1056768K class space used 33K, class space used 388K, capacity 512K, capacity 104857K

As you can see, there is no gc log output, and in the end, about 5m of space was used in the old age.

5. Assign objects on TLAB

The full name of TLAB is Thread Local Allocation Buffer, which means thread-local allocation of caches. In terms of name, TLAB is a thread-specific memory allocation area. Because objects are generally allocated on the heap, and the heap is globally shared, multiple threads may request space on the heap at the same time. Therefore, every object allocation must be synchronized, and the efficiency of object allocation will be further reduced in competitive situations. Considering that object allocation is almost the most commonly used operation in java, the java virtual machine uses TLAB, a thread-specific area, to avoid multi-thread conflicts and improve the efficiency of object allocation. TLAB itself takes up space in the eden zone, and when TLAB is enabled, the virtual machine allocates a TLAB area to each Java thread.

By default, the size of the TLAB is constantly adjusted at run time to optimize the running state of the system. If you want to disable automatic resizing of TLAB, you can disable ResizeTLAB using-XX:ResizeTLAB and manually specify the size of TLAB using-XX:TLABSize.

Example: performance difference between enabling TLAB and turning off TLAB

Public class Demo05 {public static void alloc () {byte [] b = new byte [2]; b [0] = 1;} public static void main (String [] args) {long b = System.currentTimeMillis (); for (int I = 0; I < 100000000; iTunes +) {alloc ();} long e = System.currentTimeMillis () System.out.println (e-b);}}

Run with the parameter-XX:+UseTLAB-Xcomp-XX:-BackgroundCompilation-XX:-DoEscapeAnalysis-server, and the result is 71

Run with the parameter-XX:-UseTLAB-Xcomp-XX:-BackgroundCompilation-XX:-DoEscapeAnalysis-server, and the result is 135

As a result, whether TLAB is enabled or not has a significant impact on object allocation.

The allocation process of the object:

If stack allocation is enabled, the system will make stack allocation first.

If the stack allocation is not enabled or does not meet the conditions, TLAB allocation will be carried out.

If the TLAB allocation is not successful, try allocating on the heap again

If the conditions for direct entry into the old age are met, it will be distributed in the old age.

Otherwise, it will be allocated in the GC area, and of course, if necessary, a new generation of EDN may be carried out.

6. The influence of finalize () function on garbage collection.

Java provides a mechanism similar to the C++ destructor, the finalize () function, which allows it to be overloaded in subclasses for resource release when the object is reclaimed. At present, it is generally recognized that the finalize () function should not be used for resource release as far as possible, mainly for the following reasons:

In the finalize () function, it may cause the object to be resurrected

The execution time of the finalize () function is not guaranteed. It is entirely determined by the GC thread. In extreme cases, if GC,finalize () does not occur, there will be no opportunity to execute.

A bad finalize () function can seriously affect GC performance.

Although the finalize () function is not recommended, in some cases, using the finalize () function can provide double insurance. For example, in the jdbc driver of mysql, com.mysql.jdbc.ConnectionImpl implements the finalize () function with the following code:

Protected void finalize () throws Throwable {this.cleanup (Throwable) null); super.finalize ();}

That is, when a jdbc connection is recycled, the connection needs to be closed, that is, the cleanup () method here. In fact, if the developer calls the Connection.close () method normally before recycling, the connection will be explicitly closed and nothing will be done in the cleanup () method. If the developer forgets to explicitly close the connection and the Connection object is recycled, the connection is closed implicitly to ensure that there is no database connection leakage. At this point, the finalize () function may be used as a compensation measure to compensate in the event of an accident in the normal method to ensure the stability of the system as much as possible. Of course, because of the uncertainty of its call time, this can not be used alone as a reliable means of resource recovery.

On the java garbage collector in the memory allocation and collection of some details are shared here, I hope the above can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report