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异常。

  大概就是这样了,拜!

Java虚拟机性能监控与调优实战相关推荐

  1. Java项目性能监控和调优工具-Javamelody

    JavaMelody能够在运行环境监测Java或Java EE应用程序服务器.并以图表的形式显示:Java内存和Java CPU使用情况,用户Session数量,JDBC连接数,和http请求.sql ...

  2. Java虚拟机|JVM知识点汇总及简述->性能监控与调优

    性能监控与调优 前言 这里学完整章后选择一到两个工具使用熟练,个人推荐Visual VM和Arthas搭配熟练使用 一.概述 1.性能评价/测试指标 1.1 停顿时间(响应时间) 提交请求和返回该请求 ...

  3. Java生产环境下性能监控与调优详解 第2章 基于JDK命令行工具的监控

    Java生产环境下性能监控与调优详解 第2章 基于JDK命令行工具的监控 2-1 JVM的参数类型 标准参数 x参数 XX参数 2-2 查看JVM运行时参数 2-3 jstat查看JVM统计信息 2- ...

  4. JAVA生产环境验证_Java生产环境下性能监控与调优详解

    本课程将为你讲解如何在生产环境下对Java应用做性能监控与调优:通过本课程,你将掌握多种性能监控工具应用,学会定位并解决诸如内存溢出.cpu负载飙高等问题:学会线上代码调试,Tomcat.Nginx, ...

  5. Java生产环境下性能监控与调优详解 大纲 学习感悟

    Java生产环境下性能监控与调优详解 生产环境发生了内存溢出如何处理? 生产环境应该给服务器分配多少内存合适? 如何对垃圾收集器的性能进行调优? 4.生产环境CPU负载飙高该如何处理? 5.生产环境应 ...

  6. Java生产环境下性能监控与调优详解 第5章 Tomcat性能监控与调优

    第5章 Tomcat性能监控与调优 5-1 tomcat远程debug 5-2 tomcat-manager监控 5-3 psi-probe监控 5-4 tomcat优化

  7. Java生产环境下性能监控与调优详解 第6章 Nginx性能监控与调优

    第6章 Nginx性能监控与调优 6-1 nginx安装 6-2 ngx_http_stub_status监控连接信息 6-3 ngxtop监控请求信息 6-4 nginx-rrd图形化监控 6-5 ...

  8. jinfo java_Java自带的JVM性能监控及调优工具(jps、jinfo、jstat、jmap、javap)使用介...

    JVM介绍 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的. ...

  9. 性能监控与调优篇之【3. JVM 监控及诊断工具-GUI 篇】

    文章目录 3. JVM 监控及诊断工具-GUI 篇 3.1. 工具概述 3.2. JConsole 3.3. Visual VM 3.4. Eclipse MAT 3.5. JProfiler 3.6 ...

最新文章

  1. 一年参加一次就够,全新升级的AI开发者大会议程出炉!
  2. 大数据的发展,伴随的将是软件工程师的渐退,算法工程师的崛起
  3. FJUT OJ 2466 T^T的叛乱计划(组合数学)
  4. c++ 字符类型总结区别wchar_t,char,WCHAR(转)
  5. mysql查询语句在哪里编写_mysql编写语句:更新查询
  6. 关于UIView的autoresizingMask属性的研究
  7. java掩码校验_Java 检查Ip掩码
  8. opengl与Directx的区别
  9. MTK eCos系统的有线驱动收包流程
  10. 单片机原理及应用程序c语言版题库,单片机原理及应用期末复习题库(含答案)...
  11. Java集合分页公式
  12. 如何在win7 启动盘中写入USB3.0驱动
  13. C语言 计算总分和平均数
  14. mysql 解决1062报错
  15. Goland 导入自定义包问题解决
  16. 计算机操作透明化,win10系统如何设置透明化效|win10电脑透明化功能怎么开启
  17. 计算x的n次方(用函数)
  18. [附源码]Python计算机毕业设计大学生社团管理系统
  19. c语言diy杀毒程序源代码,c - 源码下载|其它|杀毒|源代码 - 源码中国
  20. Android精通教程V

热门文章

  1. 【综述专栏】自动驾驶中可解释AI的综述和未来研究方向
  2. 无线网络未来十年十大产业趋势
  3. 数学史上的哲学绝唱——无穷观与数学基础的争论
  4. 15℃!人类首次实现高压下室温超导,研究登上Nature封面
  5. 华为云力推“普惠AI”,EI智能体正在落地行业
  6. 谷歌李飞飞:我们依旧站在人工智能研究的起点
  7. 洪小文: 今天的AI只是一个黑盒,仍需与HI密切配合
  8. 征服围棋之后 谷歌DeepMind宣布利用AI对抗乳腺癌
  9. 编程 25 年后,现实将我打回菜鸟程序员的起点
  10. 蚂蚁上市分给员工 7000 亿股权,曾有人 28 岁财务自由,这次又将产生多少千万富翁?...