前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jvm优化实战(一篇文章看懂)

jvm优化实战(一篇文章看懂)

作者头像
一写代码就开心
发布2022-05-27 08:19:40
3860
发布2022-05-27 08:19:40
举报
文章被收录于专栏:java和python

目录

1 项目上线遇到的问题

1 运行的项目卡住了,项目里面的日志没有输出,程序没有反应 2 服务器的cpu 负载突然升高; 3 只有在上线的情况,才会有多线程的情况,本地即使压测,也没有什么用处,所以多线程,一定要上线的情况进行压测;

2 jvm的运行参数

jvm有3种参数类型

2.1 标准参数

这种参数是,不管java版本如何变,这些参数也不可能有什么大变化; 我们可以使用java -help 查看标准参数

我们找到这个

2.1.1 -D<名称>=<值>

代码语言:javascript
复制
 -D<名称>=<值>
  设置系统属性

这个参数就是我们的项目里面设置了一个变量属性,之后再启动项目的时候使用这个进行给变量属性赋值;

举例子: 我们自己写一个代码,在系统属性里面获取一个变量并且输出,但是这个变量名字是我们自己编的,所以在启动项目的时候,我们需要给他赋值

代码语言:javascript
复制
public class mytest {

    public static void main(String[] args) {
        String name = System.getProperty("name");
        if(name!=null){
            System.out.println(name);
        }
        else{
            System.out.println("jing");
        }
    }
}

在哪里给这个name变量设置值?我们在idea里面可以设置

以上的这个里面就是专门设置java的的一些参数的,我们现在的例子可以这样设置

然后执行这个代码,看控制台输出

通过以上的 例子,可以看到-D 这个可以设置系统变量;相当于使用-D 可以设置系统属性参数;

2.1.2 -server 和 -client

通过这两个参数设置运行模式 -server 根据这个设置的是,初始化的时候,堆空间的内存大一些,启动项目的时候慢,但是之后因为内存大,所以运行快,默认使用的是并行垃圾回收器

-client 初始化堆空间小,启动快,但是之后因为内存小,所以运行速度慢,使用的是串行垃圾回收器

代码语言:javascript
复制
64位的系统,只有server模式

2.2 -X 参数(非标准参数)

这种参数是,java版本变,这些参数有可能变化; 我们可以使用java -X 查看标准参数

我们咋查看启动我们的项目是什么模式

以上可以看到,我们的项目启动,如果不设置这个,就是默认混合模式

2.2.1 -Xint

我们在启动项目的时候,如果设置了这个,那么

就是在编译java项目的时候,一边编译一边执行,就是编译多少,运行多少

启动项目,控制台输出

2.2.2 -Xcomp

我们启动项目的时候设置一下

控制台输出就是

2.2.3 -Xmixed

混合模式的输出标志是

代码语言:javascript
复制
1、-Xint是强制解释模式执行,指的是字节码解释执行,
中间不需要经过c语言编程成本地代码。
这种经过c语言编译成本地代码,然后再执行的方式就是编译模式。
这是解释模式和编译模式最大的区别。
这里不是你说的编译成操作系统指令实际是最后一步,本质就是字节码指令。

2、本地代码就是通常我们看到的类里面有native方法,
此类方法的实现都是通过本地代码实现的,通常是c或者c++写的。

2.2.4 -Xms 设置堆内存初始化大小

设置多少合适?

2.2.5 -Xmx 设置堆内存最大大小

设置多少合适?

2.3 -XX 参数(使用效率高)

2.3.1 boolean类型

2.3.2 非Boolean类型

就是把加号减号去掉,后面是键值对的形式

2.4 查看jvm的运行参数

我们启动一个项目,需要在控制台输出所有的jvm的运行参数

代码语言:javascript
复制
-XX:+PrintFlagsFinal

控制台输出的是

以上是所有的jvm参数都输出了,现在我们想要查看正在运行的;就是现在有很多的java项目启动,以上是将所有的都展示了,我现在想要查看某一个项目里面某一个jvm参数的值是什么,需要借助jsp命令和jinfo命令

2.5 jsp命令

jps是jdk提供的一个查看当前java进程的小工具;

代码语言:javascript
复制
 很多人都是用过unix系统里的ps命令,这个命令主要是用来显示当前系统的进程
 情况,有哪些进程以及进程id。 

jps 也是一样,它的作用是显示当前系统的java进程情况及进程id。

我们可以通过它来查看我们到底启动了几个java进程
(因为每一个java程序都会独占一个java虚拟机实例)
代码语言:javascript
复制
(jps存放在JAVA_HOME/bin/jps,
使用时为了方便需将JAVA_HOME/bin/加入到Path) 
代码语言:javascript
复制
-q:仅输出VM标识符,不包括classname,jar name,arguments in main method 
-m:输出main method的参数 
-l:输出完全的包名,应用主类名,jar的完全路径名 
-v:输出jvm参数 

就是使用这个命令可以查看,当前系统运行的java程序,并且展示进程号

2.6 jinfo 命令

我们先用 jps 命令查到 PID ,然后可以通过 jinfo 来查看对应进程的参数信息:

查看 JVM 参数:

查看系统参数:

代码语言:javascript
复制
-Xms:初始堆大小,默认为物理内存的1/64(<1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制
-Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制
-Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=新生代大小 + 老生代大小 + 永久代大小。在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:SurvivorRatio:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。
-Xss:每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。应根据应用的线程所需内存大小进行适当调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。一般小的应用, 如果栈不是很深, 应该是128k够用的,大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了。
-XX:PermSize:设置永久代(perm gen)初始值。默认值为物理内存的1/64。
-XX:MaxPermSize:设置持久代最大值。物理内存的1/4。

3 jvm 的内存模型

jvm的调优,就是在内存里面进行调优;

我们项目启动之后,需要查看堆里面的情况。可以使用命令jstat

3.1 jatat 命令

Jstat是JDK自带的一个轻量级小工具。 它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。

jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。参考格式如下:

jstat -options 1、jstat –class : 显示加载class的数量,及所占空间等信息。

2、jstat -compiler 显示VM实时编译的数量等信息。

jstat -gc : 可以显示gc的信息,查看gc的次数,及时间。

4 内存溢出的定位与分析

4.1 分析

系统爆出oom,分析的时候,业务是正常的,这个时候就需要加大内存; 如果你的业务不正确,就需要修改代码;

4.2 代码演示内存溢出

代码语言:javascript
复制
public class TestOOM {
	public static void main(String[] args) {
		ArrayList<String> stringArrayList = new ArrayList<>();
		for (int i = 0; i <1000000 ; i++) {
			String str="";
			for (int j = 0; j <1000 ; j++) {
				str=str+UUID.randomUUID().toString();
			}
			stringArrayList.add(str);
		}
		System.out.println("it is over!!");
	}
}

以上是一直往一个数组里面存数据,我们启动这个文件,可以手动分配堆内存的大小

hprof文件里面包含了内存堆详细的使用信息。

5 项目卡住不动的情况

项目卡住不动,有可能出现死锁,所以我们可以使用

6 jvisualvm 的使用(包含之前所有命令的功能)

有各个程序的进程pid,比如我们看到 的idea软件

还有一个远程,就是服务器上面有一个软件,比如Tomcat软件,我们想要监控这个Tomcat的jvm的使用情况,那么就可以使用他远程连接,前提是在Tomcat的配置文件里面,需要加一个配置

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 1 项目上线遇到的问题
  • 2 jvm的运行参数
    • 2.1 标准参数
      • 2.1.1 -D<名称>=<值>
      • 2.1.2 -server 和 -client
    • 2.2 -X 参数(非标准参数)
      • 2.2.1 -Xint
      • 2.2.2 -Xcomp
      • 2.2.3 -Xmixed
      • 2.2.4 -Xms 设置堆内存初始化大小
      • 2.2.5 -Xmx 设置堆内存最大大小
    • 2.3 -XX 参数(使用效率高)
      • 2.3.1 boolean类型
      • 2.3.2 非Boolean类型
    • 2.4 查看jvm的运行参数
      • 2.5 jsp命令
        • 2.6 jinfo 命令
        • 3 jvm 的内存模型
          • 3.1 jatat 命令
          • 4 内存溢出的定位与分析
            • 4.1 分析
              • 4.2 代码演示内存溢出
              • 5 项目卡住不动的情况
              • 6 jvisualvm 的使用(包含之前所有命令的功能)
              相关产品与服务
              云服务器
              云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档