堆的核心概述

概述


一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。Java堆区在JVM 启动的时候即被创建,其空间大小也就确定了。是JVM管理的最大一块内存空间。

堆内存的大小是可以调节的。

《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的

所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区( ThreadLocal Allocation Buffer,TLAB)。

《Java制拟机规范》中时Java堆的描述是:所有的对象实例以及数组都应当在运行时分配在堆上。(The heap is the run-time data area fromwhich memory for all class instances and arrays is allocated )

我要说的是:“几乎”所有的对象实例都在这里分配内存。—从实际使用角度看的。

数组和对象可能永远不会存储在栈上,因为栈帧中保存引用,这个引用指向对象或者数组在堆中的位置。

在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除。

堆,是GC( Garbage Collection,垃圾收集器)执行垃圾回收的重点区域。


内存细分

现代垃圾收集器大部分都基于分代收集理论设计,堆空间细分为:

Java 7及之前堆内存逻辑上分为三部分:新生区+养老区+永久区

 Young Generation Space      新生区                 Young /New又被划分为Eden区和Survivor区Tenure generation space       养老区             Old/TenurePermanent Space               永久区                 Perm

Java 8及之后堆内存逻辑上分为三部分:新生区+养老区+元空间

Young Generation Space           新生区         Young /New又被划分为Eden区和Survivor区
Tenure generation space         养老区     old/Tenure
Meta Space                      元空间     Meta


逻辑上堆空间是包含 永久区或者元空间的,实际上是不归属于堆管辖的

JDK7 堆空间结构

JDK8 堆空间结构

JDK7与JDK8的内存结构变化

设置堆内存大小与OOM

堆空间大小设置

Java堆区用于存储Java对象实例,那么堆的大小在JVM启动时就已经设定好了,大家可以通过选项"-Xmx"和"-Xms"来进行设置。

 “-Xms"用于表示堆区的起始内存,等价于-XX:InitialHeapsize“-xmx"则用于表示堆区的最大内存,等价于-XX:MaxHeapsize

一旦堆区中的内存大小超过“-Xmx"所指定的最大内存时,将会抛出OutofMemoryError异常。

通常会将-Xms和一Xmx两个参数配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小,从而提高性能。

默认情况下,

 初始内存大小:物理电脑内存大小/ 64最大内存大小:物理电脑内存大小/ 4

开发中建议将初始堆内存和最大堆内存设置成相同的值,因为释放最大堆内存会消耗系统线程

代码演示

package com.fs.dui;/*** 1.如何设置堆空间大小参数*  -xms用来设置堆空间(年轻代+老年代)的初始内存大小*      -X是jvm的运行参数*      ms 是memory start* -Xmx用来设置堆空间(年轻代+老年代)的最大内存大小** 2. 默认堆空间大小*        初始内存大小:物理电脑内存大小/ 64*        最大内存大小:物理电脑内存大小/ 4*  手动设置*      -Xms600m -Xmx600m*      开发中建议将初始堆内存和最大堆内存设置成相同的值,因为释放最大堆内存会消耗系统线程*/
public class DuiDemo {public static void main(String[] args) {//返回Java虚拟机中的堆内存总量long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;//返回Java虚拟机试图使用的最大堆内存量long maxMemory = Runtime.getRuntime( ).maxMemory() / 1024 / 1024;System.out.println( "-xms : " + initialMemory + "M");System.out.println("-xmx : " + maxMemory +"M");//核算可用内存实际上是小于内存的
//        System.out.println("系统内存大小为: " + initialMemory * 64.0 / 1024 +"G");
//        System.out.println("系统内存大小为: " + maxMemory * 4.0 / 1024 + "G");/*未设置 -Xms与-Xmx参数获取到的值
-xms : 123M
-xmx : 1812M
系统内存大小为: 7.6875G
系统内存大小为: 7.078125G*//*以设置 -Xms600m -Xmx600m
-xms : 575M
-xmx : 575M*/}
}

查看设置参数命令

查看设置的参数:
方式一:jps/ jstat -gc进程id
方式二:-XX:+PrintGcDetails

方式一:jps/ jstat -gc进程id


计算一下
(25600+25600+153600+409600) /1024 = 600
为什么代码中是575呢?
(25600+153600+409600) /1024 = 575

方式二:-XX:+PrintGcDetails


OutOfMemory举例

代码

package com.fs.dui;import java.util.ArrayList;
import java.util.Random;/*** 模拟OOM* 设置上限 100m*/
public class OOMDemo {public static void main(String[] args) {ArrayList<Picture> pictures = new ArrayList<Picture>();while (true){try {Thread.sleep(20);}catch (Exception e){e.printStackTrace();}pictures.add(new Picture(new Random().nextInt(1024*1024)));}}
}class Picture{private byte[] pixels;public Picture(int len) {this.pixels = new byte[len];}
}


年轻代与老年代

存储在JVM中的Java对象可以被划分为两类:

 一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速另外一类对象的生命周期却非常长,在某些极端的情况下还能够与JVM的生命周期保持一致。

Java堆区进一步细分的话,可以划分为年轻代(YoungGen)和老年代(oldGen)

其中年轻代又可以划分为Eden空间、Survivor0( 幸存者0)空间和survivor1空间(有时也叫做from区、to区) 。


下面这参数开发中一般不会调:

配置新生代与老年代在堆结构的占比。

 默认-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的1/3可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5

在HotSpot中,Eden空间和另外两个survivor空间缺省所占的比例是8:1:1当然开发人员可以通过选项

 -xX :  survivorRatio”调整这个空间比例。默认值为8比如:  -xx:survivorRatio=8 设置新生代中Eden区与survivor区的比例为8:1:1-XX:-UseAdaptivesizePolicy :关闭自适应内存分配策略

几乎所有的Java对象都是在Eden区被new出来的

绝大部分的Java对象的销毁都在新生代进行了

 IBM公司的专门研究表明,新生代中 80% 的对象都是“朝生夕死”的。

可以使用选项"-xmn"设置新生代最大内存大小

 -xmn 这个参数一般使用默认值就可以了。

新生代对象分配过程

概述

为新对象分配内存是一件非常严谨和复杂的任务,JVM的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑Gc执行完内存回收后是否会在内存空间中产生内存碎片。

 1. new的对象先放伊甸园区。此区有大小限制。2.当伊甸园的空间填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区3.然后将伊甸园中的剩余对象移动到幸存者0区。4.如果再次触发垃圾回收,此时上次幸存下来的放到幸存者0区的,如果没有回收,就会放到幸存者1区。5.如果再次经历垃圾回收,此时会重新放回幸存者0区,接着再去幸存者1区。6.啥时候能去养老区呢?可以设置次数。默认是15次。》可以设置参数:-XX:MaxTenuringThreshold=<N>进行设置。7.在养老区,相对悠闲。当养老区内存不足时,再次触发cC: Major Gc,进行养老区的内存清理。8.若养老区执行了Major Gc之后发现依然无法进行对象的保存,就会产生ooM异常》java.lang. outOfMemoryError: Java heap space

YGC/Minor GC是当Eden满的时候,就会触发YGC/Minor GC

可以设置参数:-XX:MaxTenuringThreshold=进行设置 进入老年代的阈值。

总结:

针对幸存者se,s1区的总结:复制之后有交换,谁空谁是to.
关于垃圾回收:频繁在新生区收集,很少在养老区收集,几乎不在永久区/元空间收集。

对象分配的特殊情况

图解对象分配过程

代码举例与JVisualVM演示对象的分配过程

package com.fs.jvm.xlniandai;
import java.util.ArrayList;/*** -Xms60om -Xmx600m*/
public class HeapInstanceDemo {public static void main(String[] args) {ArrayList<HeapInstanceDemo> list = new ArrayList< HeapInstanceDemo > ();while (true) {list.add(new HeapInstanceDemo());try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}
}

将代码运行起来,使用工具查看变化

当老年代对象存放满后,就会报错OOM

常用调优工具

 JDK命令行Eclipse: Memory Analyzer ToolJconsolevisualVMJprofilerJava Flight RecorderGcviewerGC Easy

浅谈 Minor GC、Major GC、Full GC

JVM在进行GC时,并非每次都对上面三个内存(新生代,老年代,方法区)区域一起回收的,大部分时候回收的都是指新生代。

针对HotSpot VM的实现,它里面的Gc按照回收区域又分为两大种类型:一种是部分收集(Partial Gc) ,一种是整堆收集( Fu1l GC)

 部分收集:不是完整收集整个Java堆的垃圾收集。其中又分为:新生代收集(Minor Gc / Young cc):只是新生代(Eden/S1,S0)的垃圾收集老年代收集(Major Gc / old Gc):只是老年代的垃圾收集。√目前,只有cMS Gc会有单独收集老年代的行为。√注意,很多时候Major GC会和Fu1l Gc混淆使用,需要具体分辨是老年代回收还是整堆回收。混合收集(Mixed Gc):收集整个新生代以及部分老年代的垃圾收集.√目前,只有G1 Gc会有这种行为整堆收集(Full Gc):收集整个java堆和方法区的垃圾收集。

最简单的分代式GC策略的触发条件

年轻代GC(Minor GC)触发机制:

当年轻代空间不足时,就会触发Minor Gc,这里的年轻代满指的是Eden代满,Survivor满不会引发Gc。(每次Minor Gc会清理年轻代的内存。)

因为Java 对象大多都具备朝生夕灭的特性,所以 Minor GC非常频繁,一般回收速度也比较快。这一定义既清晰又易于理解。

Minor GC会引发STW,暂停其它用户的线程(STW),等垃圾回收结束,用户线程才恢复运行。

老年代Gc (Major GC/Fu11 GC)触发机制:

指发生在老年代的Gc,对象从老年代消失时,我们说“Major Gc”或“Full Gc发生了。

出现了Major Gc,经常会伴随至少一次的Minor Gc(但非绝对的,在Parallel scavenge收集器的收集策略里就有直接进行Major Gc的策略选择过程)

 √ 也就是在老年代空间不足时,会先尝试触发Minor Gc。如果之后空间还不足,则触发Major Gc

Major Gc的速度一般会比Minor Gc慢1e倍以上,STw的时间更长。

如果Major GC后,内存还不足,就报oOM了。

Major Gc的速度一般会比Minor Gc慢1e倍以上。

Full Gc触发机制: (后面笔记会详细来说明)

触发Fu1l GC执行的情况有如下五种:

(1)调用system.gc()时,系统建议执行Fu1l Gc,但是不必然执行(2)老年代空间不足
(3)方法区空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、survivor spacee (From Space)区向survivor space1 (To Space)区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

说明: full gc是开发或调优中尽量要避免的。这样暂时时间会短一些。

堆空间分代思想

为什么需要把Java堆分代?不分代就不能正常工作了吗?·

经研究,不同对象的生命周期不同。70%-99%的对象是临时对象。

新生代:有Eden、两块大小相同的survivor (又称为from/to,s0/s1)构成,to总为空。
老年代:存放新生代中经历多次Gc仍然存活的对象。


其实不分代完全可以,分代的唯一理由就是优化GC性能。如果没有分代,那所有的对象都在一块,就如同把一个学校的人都关在一个教室。GC的时候要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而很多对象都是朝生夕死的,如果分代的话,把新创建的对象放到某一地方,当GC 的时候先把这块存储“朝生夕死”对象的区域进行回收,这样就会腾出很大的空间出来。

内存分配策略(或对象提升(Promotion)规则)

如果对象在Eden出生并经过第一次MinorGc后仍然存活,并且能被survivor容纳的话,将被移动到survivor空间中,并将对象年龄设为1 。对象在survivor区中每熬过一次MinorGc ,年龄就增加1 岁,当它的年龄增加到一定程度(默认为15 岁,其实每个JVM、每个Gc都有所不同)时,就会被晋升到老年代中。
对象晋升老年代的年龄阈值,可以通过选项-XX:MaxTenuringThreshold来设置。

针对不同年龄段的对象分配原则如下所示:

 优先分配到Eden大对象直接分配到老年代尽量避免程序中出现过多的大对象。更恐怖的是创建的大对象是朝生夕死的,就是只使用一次,那么直接放在老年代就会浪费内存长期存活的对象分配到老年代动态对象年龄判断如果survivor区中相同年龄的所有对象大小的总和大于survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无须等到MaxTenuringThreshold 中要求的年龄。空间分配担保-XX:HandlePromotionFailure

演示大对象直接分配到老年代的代码


执行后的堆日志说明大对象就直接存储在老年代中,之前是没有进行任何GC操作的,因为没有GC日志打印

为对象分配内存:TLAB

为什么有TLAB ( Thread Local Allocation Buffer ) ?

·堆区是线程共享区域,任何线程都可以访问到堆区中的共享数据

·由于对象实例的创建在JVM中非常频繁,因此在并发环境下从堆区中划分内存空间是线程不安全的

·为避免多个线程操作同一地址,需要使用加锁等机制,进而影响分配速度。

什么是TLAB ?

·从内存模型而不是垃圾收集的角度,对Eden区域继续进行划分,JVM为每个线程分配了一个私有缓存区域,它包含在Eden空间内。

·多线程同时分配内存时,使用TLAB可以避免一系列的非线程安全问题,同时还能够提升内存分配的吞吐量,因此我们可以将这种内存分配方式称之为快速分配策略。

·据我所知所有openJDK衍生出来的JVM都提供了TLAB的设计。

TL.AB的再说明:

尽管不是所有的对象实例都能够在TAB中成功分配内存,但JVM确实是将TLAB作为内存分配的首选。

在程序中,开发人员可以通过选项“-xX:UseTLAB”设置是否开启TLAB空间。

默认情况下,TLAB空间的内存非常小,仅占有整个Eden空间的1%,当然我们可以通过选项“-XX:TLABWasteTargetPercent”设置TLAB空间所占用Eden空间的百分比大小。

一旦对象在TAB空间分配内存失败时,JVM就会尝试着通过使用加锁机制确保数据操作的原子性,从而直接在Eden空间中分配内存。

代码测试TLAB参数是否开启的情况

整体加上TLAB图示

小结堆空间的参数设置

官网说明:官网说明
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

-XX:+PrintFlagsInitial :查看所有的参数的默认初始值
-XX:+PrintFlagsFinal :查看所有的参数的最终值(可能会存在修改,不再是初始值)

 具体查看某个参数的指令:jps :查看当前运行中的进程jinfo -flag survivorRatio进程id

-Xms:初始堆空间内存(默认为物理内存的1/64)
-Xmx:最大堆空间内存(默认为物理内存的1/4)
-Xmn:设置新生代的大小。(初始值及最大值)
-XX:NewRatio:配置新生代与老年代在堆结构的占比
-XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄
-XX:+PrintGcDetails:输出详细的GC处理日志
-XX:+PrintGc-verbose:gc 打印gc简要信息
-XX:HandLePromotionFailure:是否设置空间分配担保

参数解释说明

堆是分配对象的唯一选择吗?

在《深入理解Java虚拟机》中关于Java堆内存有这样一段描述:

随着JIT编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。

在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一种特殊情况,那就是**如果经过逃逸分析(Escape Analysis)后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。**这样就无需在堆上分配内存,也无须进行垃圾回收了。这也是最常见的堆外存储技术。

此外,前面提到的基于openJDK深度定制的TaoBaoVM,其中创新的GCIH ( GC invisible heap)技术实现off-heap,将生命周期较长的Java对象从heap中移至heap外,并且cc不能管理GcIH内部的Java对象,以此达到降低cc的回收频率和提升Gc的回收效率的目的。

逃逸分析概述

如何将堆上的对象分配到栈,需要使用逃逸分析手段。

这是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。

通过逃逸分析,Java Hotspot编译莽能够才出一下新的N家的力u使用范围从而决定是否要将这个对象分配到堆上。

逃逸分析的基本行为就是分析对象动态作用域:

当一个对象在方法中被定义后,对象只在方法内部使用,则认为没有发生逃逸。
当一个对象在方法中被定义后,它被外部方法所引用,则认为发生逃逸。例如作为调用参数传递到其他地方中。

发生逃逸的几种情况

如何快速判断是否发生了逃逸分析,就看**new的对象是否有可能在方法外被调用**

逃逸参数设置

在JDK 7 版本之后,HotSpot中默认就已经开启了逃逸分析。

如果使用的是较早的版本,开发人员则可以通过:

选项“-XX:+DoEscapeAnalysis"显式开启逃逸分析
通过选项“-XX: +PrintEscapeAnalysis"查看逃逸分析的筛选结果。

结论

开发中能使用局部变量的,就不要使用在方法外定义。

逃逸分析:代码优化

使用逃逸分析,编译器可以对代码做如下优化:

一、栈上分配。将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会逃逸,对象可能是栈分配的候选,而不是堆分配。

二、同步省略。如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。

三、分离对象或标量替换。有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在cPU寄存器中。

代码优化:栈上分配

JIT编译器在编译期间根据逃逸分析的结果,发现如果一个对象并没有逃逸出方法的话,就可能被优化成栈上分配。分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量对象也被回收。这样就无须进行垃圾回收了。

常见的栈上分配的场景

在逃逸分析中,已经说明了。分别是给成员变量赋值、方法返回值、实例引用传递。

代码演示

package com.fs.demo;/*** 栈上分配测试* -Xmx1G -Xms1G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails*                  -DoEscapeAnalysis关闭逃逸  +DoEscapeAnalysis开启逃逸*/public class StackAllocation {public static void main(String[] args) {long start = System.currentTimeMillis();for (int i = 0; i < 10000000; i++) {alloc();}//查看执行时间long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start) + " ms");//为了方便查看堆内存中对象个数,线程sLeeptry {Thread.sleep(1000000);} catch (InterruptedException e1) {e1.printStackTrace();}}private static void alloc() {Demo demo = new Demo();}static class Demo {}
}
演示-DoEscapeAnalysis关闭逃逸分析

1:执行时间长
2:内存实例对象为遍历添加次数

演示+DoEscapeAnalysis开启逃逸分析

1:执行时间短
2:内存中添加的对象大量减少

将内存参数从1G改为256,关闭逃逸分析情况

1:发生GC
2:执行时间长

将内存参数从1G改为256,打开逃逸分析情况

未发生GC,执行时间短

代码优化:同步省略(消除)

线程同步的代价是相当高的,同步的后果是降低并发性和性能。

在动态编译同步块的时候,JIT编译器可以借助逃逸分析来判断同步块所使用的锁对象是否只能够被一个线程访问而没有被发布到其他线程。如果没有,那么JIT编译器在编译这个同步块的时候就会取消对这部分代码的同步。这样就能大大提高并发性和性能。这个取消同步的过程就叫同步省略,也叫锁消除

代码演示

下面绿色代码中,这个对象本身会发生逃逸分析,这个对象加锁是毫无意义的

若这个对象本身是个局部变量,不会被多个线程共用,若打开逃逸分析,jvm会自动取消掉同步这一块的代码

代码优化:分离对象或标量替换

**标量(scalar)**是指一个无法再分解成更小的数据的数据。Java中的原始数据类型就是标量。

相对的,那些还可以分解的数据叫做聚合量(Aggregate) , Java中的对象就是聚合量,因为他可以分解成其他聚合量和标量。

在JIT阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就会把这个对象拆解成若干个其中包含的若干个成员变量来代替。这个过程就是标量替换

列子:

下面的代码new Point(1,2)就是个聚合量

可以看到,Point这个聚合量经过逃逸分析后,发现他并没有逃逸,就被替换成两个聚合量了。那么标量替换有什么好处呢?就是可以大大减少堆内存的占用。因为一旦不需要创建对象了,那么就不再需要分配堆内存了。

标量替换为栈上分配提供了很好的基础。

标量替换参数设置︰

参数-XX:+EliminateAllocations:开启了标量替换(默认打开),允许将对象打散分配在栈上。

逃逸分析总结

逃逸分析并不成熟

关于逃逸分析的论文在1999年就已经发表了,但直到JDK 1.6才有实现,而且这项技术到如今也并不是十分成熟的。

其根本原因就是无法保证逃逸分析的性能消耗一定能高于他的消耗。虽然经过逃逸分析可以做标量替换、栈上分配、和锁消除。但是逃逸分析自身也是需要进行一系列复杂的分析的,这其实也是一个相对耗时的过程。

一个极端的例子,就是经过逃逸分析之后,发现没有一个对象是不逃逸的。那这个逃逸分析的过程就白白浪费掉了。

虽然这项技术并不十分成熟,但是它也是即时编译器优化技术中一个十分重要的手段。注意到有一些观点,认为通过逃逸分析,JVM会在栈上分配那些不会逃逸的对象,这在理论上是可行的,但是取决于JVM设计者的选择。据我所知,oracle HotspotJVM中并未这么做,这一点在逃逸分析相关的文档里已经说明,所以可以明确所有的对象实例都是创建在堆上。

目前很多书籍还是基于JDK 7以前的版本,JDK已经发生了很大变化,intern字符串的缓存和静态变量曾经都被分配在永久代上,而永久代已经被元数据区取代。但是,intern字符串缓存和静态变量并不是被转移到元数据区,而是直接在堆上分配,所以这一点同样符合前面一点的结论:对象实例都是分配在堆上。

本章小结

年轻代是对象的诞生、成长、消亡的区域,一个对象在这里产生、应用,最后被垃圾回收器收集、结束生命。

老年代放置长生命周期的对象,通常都是从survivor区域筛选拷贝过来的Java对象。当然,也有特殊情况,我们知道普通的对象会被分配在TLAB上;如果对象较大,JVM会试图直接分配在Eden其他位置上;如果对象太大,完全无法在新生代找到足够长的连续空闲空间,JVM就会直接分配到老年代。

当GC只发生在年轻代中,回收年轻代对象的行为被称为MinorGC。当GC发生在老年代时则被称为MajorGC或者FullGC。一般的,MinorcC的发生频率要比MajorGc高很多,即老年代中垃圾回收发生的频率将大大低
于年轻代。

JVM学习笔记之-堆,年轻代与老年代,对象分配过程,Minor GC、Major GC、Full GC,堆内存大小与OOM,堆空间分代,内存分配策略,对象分配内存,小结堆空间,逃逸分析,常用调优工具相关推荐

  1. 编写一个能监控到windows进程占用内存大小的脚本_Java性能监控分析及调优工具...

    >>>推荐阅读<<< 1.性能测试学习笔记-场景设计 2.性能测试的重要意义 3.性能分析流程及方法 4.应用系统性能调优之性能分析 Java性能监控分析及调优工具 ...

  2. 【JVM学习笔记】内存回收与内存回收算法 就哪些地方需要回收、什么时候回收、如何回收三个问题进行分析和说明

    目录 一.相关名词解释 垃圾收集常用名词 二.哪些地方需要回收 本地方法栈.虚拟机栈.程序计数器 方法区 Java堆 三.什么时候回收 1. 内存能否被回收 内存中的引用类型 引用计数算法 可达性分析 ...

  3. Major GC 是清理老年代。 Full GC 是清理整个堆空间—包括年轻代和老年代。

    Major GC 是清理老年代. Full GC 是清理整个堆空间-包括年轻代和老年代.

  4. 【JVM 学习笔记 05】:JVM性能调优工具的使用和优化案例

    [JVM 学习笔记 05]:JVM性能调优工具的使用 1. 使用 jstat(命令行工具) 查看线上系统的JVM运行状况 1.1 常用命令 1.2 使用技巧 1.2.1 随着系统运行,每秒钟会在年轻代 ...

  5. JVM学习笔记汇总:结合尚硅谷宋红康老师视频教程及PPT

    JVM学习笔记汇总:结合尚硅谷宋红康老师视频教程及PPT 第一章:JVM虚拟机的介绍 1.1虚拟机的分类 虚拟机通常分为两类:系统虚拟机和程序虚机.其中,系统虚拟机是指完全对物理计算机的仿真,而程序虚 ...

  6. JVM学习笔记(四)------内存调优

    首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提 ...

  7. JVM学习笔记(四)

    JVM学习笔记(四) 文章目录 JVM学习笔记(四) 笔记链接 1.GC算法 1.1GC-判断对象是否可回收 1.1.1 引用计数法 1.1.1 可达性分析 1.2GC-回收算法 标记清除法(Mark ...

  8. JVM学习笔记之-拉圾回收概述,垃圾回收相关算法

    拉圾回收概述 什么是垃圾 垃圾收集,不是Java语言的伴生产物.早在1960年,第一门开始使用内存动态分配和垃圾收集技术的Lisp语言诞生. 关于垃圾收集有三个经典问题: 哪些内存需要回收? 什么时候 ...

  9. JVM学习笔记-01-JVM的学习方式

    JVM学习笔记-01-JVM的学习方式 文章目录 JVM学习笔记-01-JVM的学习方式 JVM探究 最新JVM教程IDEA版[Java面试速补篇]-01-JVM的学习方式 JVM探究 请你谈谈对JV ...

最新文章

  1. Python3中__init__.py文件介绍
  2. transforms.normalize()函数
  3. aop对请求后端的参数修改_Spring Aop 修改目标方法参数和返回值
  4. Mysql查看和修改时区
  5. IntelliJ IDEA搭建一个web项目含配置tomcat
  6. 再写dll 关于declspec(dllexport)和declspec(dllimport)
  7. 什么时候用到mysql存储过程_什么时候用到存储过程
  8. SAP License:备选统驭科目问题
  9. 【AI】人工智能之深度学习(1)—— 入门
  10. win10系统怎么进行远程控制操作
  11. python海贼王logo_中年大叔学编程-Python下载海贼王漫画图片
  12. Unity 半透明图片遮挡半透明图片
  13. 基于React的富文本编辑器——Braft Editor使用
  14. 微信浏览器清理缓存的方法
  15. windows 安装Abin
  16. win10微软图标点击无反应_Win10下鼠标双击桌面图标打不开应用的三种解决方案...
  17. 向锦华北京个人演唱会倾情上演,用歌声唱出音乐梦想
  18. java生成报表(excel表格)的另类方法
  19. 算法图解[Aditya Bhargava]--读书笔记
  20. net6 winform应用读取配置文件(依赖注入、普通读取)

热门文章

  1. MySQL及其分支或衍生版
  2. ZOJ-2770 Burn the Linked Camp 差分约束
  3. 使用python移动飞信模块发送短信
  4. android 框架LoonAndroid,码农偷懒专用(2014/8/6更新)
  5. java应用程序中判断用户输入的一个整数是否在已知数组里。
  6. uva10050-罢工
  7. 【转】解决多文件编译中连接错误 multiple definition of*****
  8. 网络编程——第一篇 基础之进程线程
  9. 第三天【DOM4J Xpath】
  10. MongoDB 分布式部署教程