7.JVM调优-方法区,堆,栈调优详解
通常我们都知道在堆空间新生代Eden区满了,会触发minor GC, 在老年代满了会触发full GC, 触发full GC会导致Stop The World, 那你们知道还有一个区域满了一会触发Full GC么?而且这个区域满了会直接影响我们的开发效率。
一、方法区参数调优
我们可以对运行时数据区的内存进行参数设置. 这是jvm调优的重点. 参数的变化将影响到整体效率
核心参数设置如下:
java -Xms2048M -Xmx1024M -Xss512k -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar microservice-eureka-server.jar
这是一个通用的设置。图中具体含义如下:
- -Xms:堆空间最小值
- -Xmx:堆空间最大值
- -Xmn:新生代占堆空间的大小
- -XX:MetaspaceSize:方法区(元空间)初始值
- -XX:MaxMetaspaceSize:方法区(元空间)最大值
- -Xss:每一个线程的空间大小
下面主要研究方法区参数设置
1. 方法区(元空间)参数设置
在jdk8之前有个区域叫做永久代, 在jdk8及以后改名字了, 叫做元空间. 这块内存空间占用的是直接的物理内存.
元空间有一个特点: 可以动态扩容。如果, 我们没有设置元空间的上限, 那么他可以扩大到整个内存. 比如内存条是8G的, 堆和栈分配了4G的空间, 那么元空间最多可以使用4G。
我们可以通过参数来设置使用的元空间内存。
对于64位的JVM来说, 元空间默认大小是21M, 元空间的默认最大值是无上限的, 他的上限就是内存空间
- -XX:MetaspaceSize: 元空间的初始空间大小, 以字节位单位, 默认是21M,达到该值就会触发full GC, 同时收集器会对该值进行调整, 如果释放了大量的空间, 就适当降低该值, 如果释放了很少的空间, 提升该值,但最到不超过-XX:MaxMetaspaceSize设置的值
比如:
初始值是21M, 第一次回收了20M, 那么只有1M没有被回收, 下一次, 元空间会自动调整大小, 可能会调整到15M
初始大小依然是21M, 第二次回收发现回收了1M, 有20M没有被回收, 他就会自动扩大空间, 可能扩大到30M,也可能是40M
- -XX:MaxMetaspaceSize: 设置元空间的最大值, 默认是-1, 即不限制, 或者说只受限于本地内存的大小
由于调整元空间的大小需要full GC, 这是非常昂贵的操作, 如果应用在启动的时候发生大量的full GC, 通常都是由于永久代或元空间发生了大小的调整, 基于这种情况, 一般建议在JVM参数中将-XX:MetaspaceSize和-XX:MaxMetaspaceSize设置成一样的值, 并设置的比初始值还要大, 对于8G物理内存的机器来说, 一般会将这两个值设置为256M或者512M都可以
2. 建议设置元空间值, 如果不设置会怎么样?
不设置元空间默认就是21M, 很容易就会放满, 通常我们的war可能都是几十M, 甚至几个G. 如果我们在启动程序的时候, 会启动几分钟. 这很有可能是没有设置元空间的大小.
放满后会发生full GC, 然后在扩大一点元空间, 扩大到25M, 重新开始, 过了一会又放满了, 再次full GC, 在扩大一点, 元空间扩大到30M, 就这样一直发生full GC, 然后一直扩大元空间, 直到扩大的元空间大小合适, 不再发生full gc, 程序才会正常启动运行. 这是个很耗时耗性能的操作, 这样的full GC也是没有必要的.
如果项目启动较慢,多次重复启动,考虑是不是元空间设置不合理,或者内存不够导致。
二. 线程栈参数调优
-Xss512k:设置栈空间参数的
这个参数就是用来设置栈空间的. 他是设置的一个线程栈占用的空间, 一个程序启动后可能有多个线程栈, 那么他们占用的空间都是512k。
一个程序启动以后,系统为其分配的栈空间是固定的。理论上来说,如果每一个线程占用的空间少,那么就能分配更多的线程。否则则相反。但这也不是确定的,还有和系统的cpu,内存有关系。
当线程分配的空间用完的时候,就会抛出栈溢出异常。下面来看一个例子
package com.lxl.jvm;
public class StackOverflowTest {
/**
* jvm 设置-Xss128M, (默认是1M)
*/
static int count = 0;
public static void redo(){
count ++;
redo();
}
public static void main(String[] args) {
try {
redo();
}catch (Throwable e) {
e.printStackTrace();
System.out.println(count);
}
}
}
这里定义了一个变量count, main方法里调用了redo()方法. 当我们执行main方法的时候, 线程栈模型是什么样的呢?
当程序执行到main方法的时候, 会在线程栈中开辟一个main方法的栈帧
继续执行, 执行到redo()的时候, 会在线程栈在开辟一块redo方法栈帧
redo方法里又调用了redo方法. 继续开辟一块redo方法栈帧,
.......
栈帧是占用内存空间的. 总有一个时刻会把栈内存消耗完. 就会报栈内存溢出了
我们看到程序一共运行了16979次发生了栈溢出.
当栈空间设置的小一些呢?比如256k
我们运行看效果
当运行到2079次的时候, 发生了栈溢出。
7.JVM调优-方法区,堆,栈调优详解的更多相关文章
- [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机, ...
- JVM存储位置分配——java中局部变量、实例变量和静态变量在方法区、栈内存、堆内存中的分配
Java中的变量根据不同的标准可以分为两类,以其引用的数据类型的不同来划分可分为“原始数据类型变量和引用数据类型变量”,以其作用范围的不同来区分可分为“局部变量,实例变量和静态变量”. 根据“Java ...
- 牛客网Java刷题知识点之内存的划分(寄存器、本地方法区、方法区、栈内存和堆内存)
不多说,直接上干货! 其中 1)程序计数器:用于指示当前线程所执行的字节码执行到了第几行,可以理解为当前线程的行号指示器.每个计数器志勇赖记录一个线程的行号,所以它是线程私有的. ...
- Java中局部变量、实例变量和静态变量在方法区、栈内存、堆内存中的分配
转自:https://blog.csdn.net/leunging/article/details/80599282 感谢CSDN博主「leunging」的总结分享 ———————————————— ...
- 常量池、perm(持久代)、方法区、栈
常量池.perm(持久代).方法区.栈 常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据. 除了包含代码中所定义的各种基本类型(如:int.long等等)和对象型(如St ...
- JVM中的方法区
JVM中的方法区 方法区存储什么? 用于存储已被虚拟机加载的类型信息.常量.静态变量.即时编译器编译后的代码缓存 1.类型信息 对每个加载的类型(类class.接口interface.枚举.注解)jv ...
- C/C++堆、栈及静态数据区详解
转自:https://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html 做略微修改 C/C++堆.栈及静态数据区详解 本文介绍C ...
- “全栈2019”Java第九十七章:在方法中访问局部内部类成员详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码
详解C#泛型(二) 一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...
随机推荐
- mysql8.0----mysqldump抛出:Unknown table 'COLUMN_STATISTICS' in information_schema (1109)
问题:我尝试使用mysqldump时,得到以下错误: 复制 $> mysqldump --single-transaction --h -u user -p db > db.sql my ...
- k8s笔记0528-基于KUBERNETES构建企业容器云手动部署集群记录-4
部署kubelet 1.二进制包准备 将软件包从linux-node1复制到linux-node2中去. [root@linux-node1 ~]# cd /usr/local/src/kuberne ...
- 三.Go微服务--令牌桶实现原理
1. 前言 在上一篇文章 Go微服务: 令牌桶 当中简单的介绍了令牌桶实现的原理,然后利用 /x/time/rate 这个库 10 行代码写了一个基于 ip 的 gin 限流中间件,那这个功能是怎么实 ...
- openwrt开发笔记一:源码下载与编译
1.1 环境要求 编译系统:Linux发行版(本文使用Ubuntu) 编译一个可以安装的OpenWrt固件镜像文件(大约8MB大小的),你需要: 一个纯净的OpenWrt编译系统大约需要200MB的空 ...
- 浅谈 JVM GC 的安全点与安全区域
OopMap 前文我们说到,JVM 采用的可达性分析法有个缺点,就是从 GC Roots 找引用链耗时. 都说他耗时,他究竟耗时在哪里? GC 进行扫描时,需要查看每个位置存储的是不是引用类型,如果是 ...
- charles 抓包修改app页面数据
1,首先给手机安装Charles证书,安装官方的来,在无线网配置项目,输入手动代理地址,后开启飞行模式刷新网络, 2,在浏览器输入chls.pro/ssl 下载并安装证书,此时电脑端charles 会 ...
- DPDK 无锁环形队列(Ring)详解
DPDK 无锁环形队列(Ring) 此篇文章主要用来学习和记录DPDK中无锁环形队列相关内容,结合了官方文档说明和源码中的实现,供大家交流和学习. Author : Toney Email : vip ...
- Vue配置axios
1)安装插件(一定要在项目目录下): >: cnpm install axios 2)在main.js中配置: import axios from 'axios' Vue.prototype.$ ...
- SpringBoot自定义初始化Bean+HashMap优化策略模式实践
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 传统的策略模式一般是创建公共接口.定义公共方法-->然后创建实体类实现公共接口.根据各自的 ...
- 用python的pandas读取excel文件中的数据
一.读取Excel文件 使用pandas的read_excel()方法,可通过文件路径直接读取.注意到,在一个excel文件中有多个sheet,因此,对excel文件的读取实际上是读取指定文件.并 ...