002 jvm_堆参数调优

        Java虚拟机在运行的过程中,虚拟机提供了一些跟踪系统状态的参数,使用给定的参数执行java虚拟机,就可以在系统运行时打印相关日志,用于分析实际问题。我们进行虚拟机参数配置,其实主要就是围绕着堆、栈进行配置。

1.虚拟机参数-Heap内存

• -XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志。
• -XX:+UseSerialGC 配置串行回收器
• -XX:+PrintGCDetails 可以查看详细信息,包括各个区的情况
• -Xms:设置java程序启动时初始堆大小
• -Xmx:设置java程序能获得的最大堆大小
• -XX:+PrintCommandLineFlags: 可以将隐式或者显示传给虚拟机的参数输出

【注意:在实际工作中,直接将初始的堆大小与最大堆大小设置相等,这样的好处是可以减少程序运行时的垃圾回收次数,从而提高性能。】

       非常多的开源框架都采用Lock Memory的机制,将初始化堆大小与最大堆大小固定设置为一致,并独占固定内存大小,强制占用固定内存,不被其他应用使用。

2.Heap内存结构

Young:年轻代中的数据频繁的创建销毁,所以采用复制算法

Eden区:所有new出来的对象都存在此区域;

from(S0)/to(S1):YGC执行会将Eden区中一直引用(存活)的对象放入S0或S1其中一个区域;发生GC的时候S0或S1同时只有一个区域启用(复制算法);

复制算法:Survivor区,一块叫From,一块叫To,对象存在Eden和From块;当进行GC时,Eden存活的对象全移到To块,而From中,存活的对象按年龄值确定去向,当达到一定值(年龄阈值,通过-XX:MaxTenuringThreshold可设置,默认15次)的对象会移到年老代中,没有达到值的复制到To区,经过GC后,Eden和From被清空。之后,From和To交换角色,新的From即为原来的To块,新的To块即为原来的From块,且新的To块中对象年龄加1。

Old:Young区中默认经历过15次(可设置)GC的对象会进入Old区,相对而言Old区中的数据非常庞大,那么Old区执行GC会非常消耗性能,其采用标记压缩算法

标记压缩算法:标记压缩算法是在标记清除算法的基础之上,做了优化改进的算法。和标记清除算法一样,也是从根节点开始,对对象的引用进行标记,在清理阶段,并不是简单的清理未标记的对象,而是将存活的对象压缩到内存的一端,然后清理边界以外的垃圾,从而解决了碎片化的问题;优缺点同标记清除算法,解决了标记清除算法的碎片化的问题,标记压缩算法多了一步,对象移动内存位置的步骤,其效率也有一定的影响。

在这里插入图片描述

3.内存溢出

通过微缩方法来模拟内存溢出,并导出文件排查;

step1:配置参数运行应用

-Xms5m (初始化化5M)

-Xmx20m (最大20M)

-XX:+PrintGCDetails (打印GC详细信息)

-XX:+UseSerialGC (应用串行化垃圾回收器)

-XX:+PrintCommandLineFlags(打印命令行参数)

/**
 * 01 堆内存分配查看
 */
public class Test_001 {

	public static void main(String[] args) {
		
		//-Xms5m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+PrintCommandLineFlags
		
		//查看GC信息
		System.out.println("max memory:" + Runtime.getRuntime().maxMemory());
		System.out.println("free memory:" + Runtime.getRuntime().freeMemory());
		System.out.println("total memory:" + Runtime.getRuntime().totalMemory());
		
		byte[] b1 = new byte[1*1024*1024];
		System.out.println("分配了1M");
		System.out.println("max memory:" + Runtime.getRuntime().maxMemory());
		System.out.println("free memory:" + Runtime.getRuntime().freeMemory());
		System.out.println("total memory:" + Runtime.getRuntime().totalMemory());
		
		byte[] b2 = new byte[4*1024*1024];
		System.out.println("分配了4M");
		System.out.println("max memory:" + Runtime.getRuntime().maxMemory());
		System.out.println("free memory:" + Runtime.getRuntime().freeMemory());
		System.out.println("total memory:" + Runtime.getRuntime().totalMemory());
		
	}
}

 

输出:

-XX:InitialHeapSize=5242880 -XX:MaxHeapSize=20971520 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseSerialGC 
max memory:20316160
free memory:5200384
total memory:6094848
[GC (Allocation Failure) [DefNew: 873K->192K(1856K), 0.0009620 secs] 873K->576K(5952K), 0.0009875 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
分配了1M
max memory:20316160
free memory:4423312
total memory:6094848
[GC (Allocation Failure) [DefNew: 1248K->0K(1856K), 0.0215669 secs][Tenured: 1600K->1600K(4096K), 0.0015010 secs] 1632K->1600K(5952K), [Metaspace: 2635K->2635K(1056768K)], 0.0344427 secs] [Times: user=0.00 sys=0.00, real=0.03 secs] 
分配了4M
max memory:20316160
free memory:4491456
total memory:10358784
Heap
 def new generation   total 1920K, used 68K [0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
  eden space 1728K,   3% used [0x00000000fec00000, 0x00000000fec11158, 0x00000000fedb0000)
  from space 192K,   0% used [0x00000000fedb0000, 0x00000000fedb0000, 0x00000000fede0000)
  to   space 192K,   0% used [0x00000000fede0000, 0x00000000fede0000, 0x00000000fee10000)
 tenured generation   total 8196K, used 5696K [0x00000000ff2a0000, 0x00000000ffaa1000, 0x0000000100000000)
   the space 8196K,  69% used [0x00000000ff2a0000, 0x00000000ff830198, 0x00000000ff830200, 0x00000000ffaa1000)
 Metaspace       used 2641K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 280K, capacity 386K, committed 512K, reserved 1048576K

step2模拟内存溢出,并导出文件;(查看文件需要安装Memory Analyzer) 

安装Memory Analyzer

/**
 * 02 堆内存溢出
 */
public class Test_002 {

	static List<byte[]> list = new ArrayList<>();
	
	public static void main(String[] args) {
		
		/**
		 * yum install lrzsz
		 * 1 设置初始化内存与最大内存一致,并使用串行化垃圾收集器
		 * -Xms20m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+PrintCommandLineFlags
		 * 
		 *  //Full GC
		 *	//Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
		 */
		
		/**
		 * 2 内存溢出时导出dump快照文件:
		 * -Xms20m -Xmx20m 
		 * -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/
		 * 
		 */
		
		/**
		 * 3 使用Memory Analyser dump内存进行分析
		 * <1> Leak Suspects 泄露疑点 overview
		 * <2> Histogram 图表查看具体内存数量 
		 * <3> Merge GC root 查看对象引用个数
		 * <4> entrie Heap 查看对象引用百分比与大小
		 */

		/**
		 * 4 使用jmap实时查看内存情况/导出dump文件:
		 * <1> jmap -heap 5236
		 * <2> jmap -dump:format=b,file=app.hprof 5236
		 */
		
		/**
		 * 5 设置新生代与老年代内存比例:
		 * <1> 这个参数对系统性能以及GC行为有很大的影响, 新生代大小一般会设置整个堆空间的1/3 ~ 1/4左右。
		 * 	
		 *     -Xms40m -Xmx40m -Xmn10m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
		 * 
		 * <2> -XX:SurvivorRatio:用来设置新生代中eden空间和from/to空间的比例。
		 * 
		 *     含义:-XX:SurvivorRatio=eden/from=eden/to
		 * 
		 *     基本策略:尽可能将对象预留在新生代,减少老年代的GC次数
		 * 
		 * <3> -XX:NewRatio=老年代/新生代 :用来设置新生代和老年代的比例
		 * 
		 * <4> Q:如果仅仅给出 eden区40M,那么比较合理的整个堆设置为多少?
		 * 	   A: eden/8 = 5M = S0 = S1  新生代 = 50M  * 3 OR * 4= 150M ~ 200M
		 * 		 
		 */
		
		while(true) {
			byte[] b = new byte[1*1024];
			list.add(b);
		}
		
		
	}
}

输出:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/ -XX:InitialHeapSize=20971520 -XX:MaxHeapSize=20971520 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseSerialGC 
[GC (Allocation Failure) [DefNew: 5504K->639K(6144K), 0.0028424 secs] 5504K->5094K(19840K), 0.0028726 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 6143K->639K(6144K), 0.0028299 secs] 10598K->10530K(19840K), 0.0028536 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew: 6143K->6143K(6144K), 0.0000090 secs][Tenured: 9891K->13695K(13696K), 0.0052929 secs] 16034K->15952K(19840K), [Metaspace: 2634K->2634K(1056768K)], 0.0053436 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0036933 secs] 19839K->19820K(19840K), [Metaspace: 2634K->2634K(1056768K)], 0.0037170 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0028377 secs] 19838K->19838K(19840K), [Metaspace: 2634K->2634K(1056768K)], 0.0028741 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0040750 secs] 19838K->19824K(19840K), [Metaspace: 2634K->2634K(1056768K)], 0.0040955 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0030613 secs] 19838K->19838K(19840K), [Metaspace: 2634K->2634K(1056768K)], 0.0030813 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0026850 secs] 19838K->19838K(19840K), [Metaspace: 2634K->2634K(1056768K)], 0.0027027 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
java.lang.OutOfMemoryError: Java heap space
Dumping heap to d:/\java_pid23584.hprof ...
Heap dump file created [21140604 bytes in 0.015 secs]
Exception in thread "main" [Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0030278 secs] 19839K->19839K(19840K), [Metaspace: 2659K->2659K(1056768K)], 0.0030517 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
java.lang.OutOfMemoryError: Java heap space
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0043163 secs] 19839K->19838K(19840K), [Metaspace: 2659K->2659K(1056768K)], 0.0043393 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
	at com.bfxy.jvm.Test_002.main(Test_002.java:65)
[Full GC (Allocation Failure) [Tenured: 13695K->13695K(13696K), 0.0036342 secs] 19839K->19838K(19840K), [Metaspace: 2660K->2660K(1056768K)], 0.0036576 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 def new generation   total 6144K, used 6143K [0x00000000fec00000, 0x00000000ff2a0000, 0x00000000ff2a0000)
  eden space 5504K, 100% used [0x00000000fec00000, 0x00000000ff160000, 0x00000000ff160000)
  from space 640K,  99% used [0x00000000ff160000, 0x00000000ff1ffe50, 0x00000000ff200000)
  to   space 640K,   0% used [0x00000000ff200000, 0x00000000ff200000, 0x00000000ff2a0000)
 tenured generation   total 13696K, used 13695K [0x00000000ff2a0000, 0x0000000100000000, 0x0000000100000000)
   the space 13696K,  99% used [0x00000000ff2a0000, 0x00000000fffffe90, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 2666K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 283K, capacity 386K, committed 512K, reserved 1048576K

将D:/java_pid23854.hprof拷贝到工程中查看:

查看直方图:

【jvm中只有强引用才会导致内存溢出,弱引用、软引用经过GC都会被释放,所有定位只排查强引用】

4.定时巡检

        实际工作过程中,针对生产、预节点、测试、组单元等环境,不会等到内存溢出之后,在去分析内存溢出的原因和问题,都是定时的巡检,在不应组件的情况下,就需要人工使用jmap命令进行导出了。(定时巡检是RD的日常值例工作内容)

step1:查heap实时情况   jmap -heap pid

step2:通过jmap导出应用情况  jmap -dump:format=b,file=app.hprof pid

step3:从虚拟机导出(通过 lrzsz)并查看:

5.合理划分新生代老年代

• Java虚拟机,新生代的配置
• -Xmn:可以设置新生代的大小,设置一个比较大的新生代会减少老年代的大小,这个参数对系统性能以及GC行为有很大的影响,新生代大小一般会设置整个堆空间的1/3到1/4左右。
• -XX:SurvivorRatio:用来设置新生代中eden空间和from/to空间的比例。
• 含义:-XX:SurvivorRatio=eden/from=eden/to

基本策略:尽可能将对象预留在新生代,减少老年代的GC次数

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值