Java虚拟机性能监控与调优实战

Java虚拟机的内存结构,区别于侧重于多线程的Java内存模型(Java Memory Model)

  

  但在此之前,我们该思考一下:JVM的内存结构为什么要这样划分?

  我认为主要是依据于不同数据的更新频率、访问速度要求、垃圾收集管理由此划分的JVM的五大内存区-- PC寄存器、JVM Stack 、Native Method Stack 、Java Heap、方法区、共享区

  下面主要详细解释一下这五个内存区:

  1.PC寄存器

  PC寄存器(Program Counter Register,程序计数器),是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

  由于JVM的多线程是通过轮流切换分配CPU执行时间的方式来实现的,在某个特定时刻,一个CPU/内核只会执行一条线程的指令。为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个私有、独立的PC寄存器,各线程间互不影响,我们称这类内存区域为“线程私有”的内存。
  如果线程当前执行的是一个Java方法,PC寄存器记录的是正在执行的虚拟机字节码指令的地址
  如果线程正在执行的是native方法,它的值则为空(undefined)

  2.JVM Stack

  和PC寄存器一样,JVM Stack也是线程私有的。它的生命周期与线程相同。JVM Stack描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个Frame用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应着一个Frame在JVM Stack中入栈到出栈的过程

  经常有人把Java内存分为堆内存(Heap)和栈内存(Stack),这种分法比较粗糙,Java内存区域的划分远比这复杂。其中所指“栈”就是现在讲的JVM Stack,或者说是JVM Stack中局部变量表部分(直接越过了Stack和Frame)。

  当线程请求分配的栈容量超过JVM允许的最大容量时,将抛出StackOverflowError;

  如果JVM可动态扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成扩展,或在建立新的线程时没有足够的内存去创建对应的JVM Stack,将抛出OutOfMemoryError。
  StackOverflowError 表示 请求 > Stack.Max
  OutOfMemoryError 表示 请求 > 可分配内存

  3.本地方法栈

  本地方法栈与JVM Stack所发挥的作用是非常相似的,区别只是JVM Stack为虚拟机执行Java方法服务,而本地方法栈是为虚拟机使用到的Native方法服务。

  在虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构没有强制规定,由实现自由选择。甚至有的虚拟机(如HotSpot)直接将本地方法栈和JVM Stack合二为一。与JVM Stack一样,也会抛出StackOverflowError和OutOfMemoryError异常

  def default_key_func(key, key_prefix, version):
  
  """
  
  Default function to generate keys.
  
  Constructs the key used by all other methods. By default it prepends
  
  the `key_prefix‘. KEY_www.taohuaqing178.com FUNCTION can be used to specify an alternate
  
  function with custom key making behavior.
  
  """
  
  return ‘%s:%s:%s‘ % (key_prefix,www.dongfan178.com/ version, key)
  
  def get_key_func(key_func):
  
  """
  
  Function to decide which key function to use.
  
  Defaults to ``default_key_func``.
  
  """
  
  if key_func is not None:
  
  if callable(key_func):
  
  return key_func
  
  else:
  
  return import_string(www.fencaiyule.cn/ key_func)
  
  return default_key_func
  
  复制代码
  
  内存:
  
  说明:内存版本的时候,必须设置一个值,这个值是唯一的,此缓存将内容保存至内存的变量中
  
  
  CACHES = {
  
  ‘default‘: {
  
  ‘BACKEND‘: ‘django.core.cache.backends.locmem.LocMemCache‘,
  
  ‘LOCATION‘: ‘www.chaoyueyule.com unique-snowflake‘, #这边必须设置一个值,这个值是唯一的
  
  }
  
  #其他的配置和开发调试版本一样
  
  }
  
  文件:说明:此缓存将内容保存至文件

  CACHES = {
  
  ‘default‘: {
  
  ‘BACKEND‘: ‘django.core.cache.backends.filebased.FileBasedCache‘,
  
  ‘LOCATION‘: ‘/var/tmp/django_cache‘, #缓存存放的路径
  
  }
  
  #其他的配置和开发调试版本一样
  
  }
  

  4.Java Heap

  对大多数应用来说,Java堆(Java Heap)是JVM所管理的内存中最大的一块,它是被所有线程共享的一块内存区域,在虚拟机启动时创建。该区的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

  Java Heap是GC管理的主要区域。由于现在收集器基本都采用了分代收集算法,所以Java Heap还细分为:新生代和老年代;再细一点的 Eden空间、From Survivor空间、To Survivor空间等。不过无论怎么划分,都与存放内容无关,无论哪个区域存储的都是对象实例。

  在实现时,既可以是固定大小的,也可以是扩展的,不过主流的虚拟机都是按照可扩展来实现的(-Xmx和-Xms)。如果堆 中没有内存完成实例分配,并且堆无法再扩展时,就会抛出OutOfMemoryError

  5.方法区

  与Java Heap一样,方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然JVM规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫Non-Heap(非堆),目的应该是与Java Heap分区来的。

  Java虚拟机规范对方法区的限制非常宽松,可以选择不实现垃圾收集。垃圾收集行为在本区是比较少出现的,但非数据进入方法区就如永久代的名字一样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说,这个区域的回收“成绩”很难令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。

  

  而运行时常量池作为方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

  Java虚拟机对Class文件每一部分(自然也包括常量池)的格式都有严格规定,每一个字节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可、装载和执行,但对于运行时常量池,Java虚拟机规范没有做任何细节的要求,不同的提供商实现的虚拟机可以按照自己的需要来实现这个内存区域。

  既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时抛出OutOfMemoryError异常。

  大概就是这样了,拜!

原文地址:https://www.cnblogs.com/qwangxiao/p/9246577.html

时间: 2024-11-09 00:41:18

Java虚拟机性能监控与调优实战的相关文章

JVM虚拟机性能监控与调优(JDK命令行、JConsole)

很多资料在介绍JDK命令行工具时并不是在Java8环境下,因此还在使用过时的永久区系列的参数,给一些读者造成困难. Java8使用Metaspace(元空间)代替永久区,对于64位平台,为了压缩JVM对象中的_klass指针的大小,引入了类指针压缩空间(Compressed Class Pointer Space) .关于这点,可以参考博客https://blog.csdn.net/liang0000zai/article/details/51168095. 1. JDK命令行工具 在JDK的开

Java项目性能监控和调优工具-Javamelody的学习总结

1.简介: JavaMelody能够在运行环境监测Java或Java EE应用程序服务器.并以图表的形式显示:Java内存和Java CPU使用情况,用户Session数量,JDBC连接数,和http请求.sql请求.jsp页面与业务接口方法(EJB3.Spring.Guice)的执行数量,平均执行时间,错误百分比等.图表可以按天,周,月,年或自定义时间段查看. 2.准备: 下载javamelody-1.47.0.jar和jrobin-1.5.9.1.jar,引用到项目中. 3.配置方法: 一般

Java生产环境下性能监控与调优详解

第1章 课程介绍(Java秒杀课程老师倾力打造)本章为大家介绍生产环境可能存在的问题和常用的性能监控工具,以及课程能学到什么,课程内容如何安排等,让大家对课程有个全貌的认识,从而更好的学习这门课程.1-1 为什么学习这门课程? 第2章 基于JDK命令行工具的监控本章带大家学习JDK的命令行监控工具的使用,包括jps.jinfo.jstat.jmap.jstack, 并结合MAT实战如何定位内存溢出,实战如何定位死循环和死锁.2-1 JVM的参数类型2-2 查看JVM运行时参数2-3 jstat查

Linux系统CPU的性能监控及调优

前言: 性能优化是一个老生常谈的话题,典型的性能问题如页面响应慢.接口超时,服务器负载高.并发数低,数据库频繁死锁等.尤其是在“糙快猛”的互联网开发模式大行其道的今天,随着系统访问量的日益增加和代码的臃肿,各种性能问题开始纷至沓来. 在系统层面能够影响应用性能的一般包括三个因素:CPU.内存和IO,今天,我们先谈谈CPU性能的监控以及调优. CPU性能监控 当程序响应变慢的时候,首先使用top.vmstat.ps等命令查看系统的cpu使用率是否有异常,从而可以判断出是否是cpu繁忙造成的性能问题

Tomcat性能监控与调优

tomcat远程debug Tomcat是目前被应用得最多的一款Java Web服务器,很多人都会使用Tomcat来作为项目的服务器.也经常需要在开发的时候对Tomcat进行debug.在本地对Tomcat进行debug相信很多人都会,但如果需要对远程的Tomcat进行debug,相信有部分小伙伴还是没接触过的,而本小节将简单介绍一下如何对Tomcat进行远程debug. Tomcat远程debug是基于 JDWP 协议实现的,关于 JDWP 协议,可参考以下文档: https://www.ib

DB2数据库性能监控和调优实践

1.性能调优概述 性能问题的症状 响应时间慢 吞吐量低 资源占用高(CPU.Memory.I/0等) 数据库角度 数据库逻辑设计 数据库物理设计(存储规划) SQL语句 数据库调优关键 I/O最关键 减少I/O 最大化I/O效率 存储规律,物理设计 CPU两个杀手 表扫描 排序 Memory命中率可能会骗人 SQL是一切问题的根源 2.性能调优步骤 明确问题->收集数据->分析数据->细化.定位问题->优化 3.DB2数据库监控工具-db2pd 3.1.监控工具总结 即时监控工具

MySQL写压力性能监控与调优

写压力调优:数据库的写.写压力性能监控.写压力调优参数 一.关于DB的写 1.数据库是一个写频繁的系统 2.后台写.写缓存 3.commit需要写入 4.写缓存失效或者写满-->写压力陡增-->写占读的带宽 1.BBU失效 2.写入突然增加.cache满 5.日志写入.脏缓冲区写入 二.写压力性能监控 全面剖析写压力:多维度的对写性能进行监控. 1.OS层面的监控:iostat -x [[email protected] mydata]# iostat -x Linux 2.6.32-642.

java - 虚拟机性能监控与故障处理工具

背景 在项目开发中往往不是一个人完成整个项目,而是由一个团队进行开发,而团队中成员的编程能力参差不齐难免会影响项目性能.当一个项目基本定型后难免会遇到项目产品使用的效果不理想例如长时间失去响应.系统卡顿等一系列问题.此时就需要对整体应用进行具体分析.而对于分析人员来说对于整个项目的所有细节并不能全部知道,此时就需要一些辅助工具来对JVM的某些数据(例如GC次数,内存分布状态)进行提取,然后对该类数据进行分析.准确定位到应用造成该类情况的主要原因.然后针对原因进行针对性的故障处理或者是性能调优等.

Tomcat 性能监控及调优

1.性能监控 方式1: /usr/local/tomcat7/conf/tomcat-users.xml 添加如下: <role rolename="manager-gui"/> <role rolename="manager-script"/> <role rolename="manager-jmx"/> <role rolename="manager-status"/> &l