JVM和JMM的关系

JVM(java Virtual Machine)

JVM(Java Virtual Machine的简称。意为Java虚拟机。)
虚拟机: 指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。
在这里插入图片描述
JDK1.6java虚拟机模型大致如上图,方法区中包含常量池;在JDK1.7常量池分为类常量池,运行时常量池和字符串常量池,并将 字符串常量池 移进了堆中;JDK1.8后,方法区移进了本地内存.改名为元数据区.这就是大致的变化

运行时数据区

JVM会在执行Java程序的过程中把它管理的内存划分为若干个不同的数据区域。这些数据区域各有各的用处,各有 各的创建与销毁时间,有的区域随着JVM进程的启动而存在,有的区域则依赖用户线程的启动和结束而创建与销 毁。一般来说,JVM所管理的内存将会包含以下几个运行时数据区域:
线程私有区域:程序计数器、Java虚拟机栈、本地方法栈
线程共享区域:Java堆、方法区、常量池

1.程序计数器(线程私有)

程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址; 如果正在执行的是Native方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟 机规范中没有规定任何OutOfMemoryError情况的区域。

2.java虚拟机栈(线程私有)

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

局部变量表 : 存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表大小.

此区域一共会产生以下两种异常:

  1. 如果线程请求的栈深度大于虚拟机所允许的深度(-Xss设置栈容量),将会抛出StackOverFlowError异常。
  2. 虚拟机在动态扩展时无法申请到足够的内存,会抛出OOM(OutOfMemoryError)异常
3.本地方法栈(线程私有)

本地方法栈与虚拟机栈的作用完全一样,他俩的区别无非是本地方法栈为虚拟机使用的Native方法服务,而虚拟机 栈为JVM执行的Java方法服务.

4.java堆(线程共享)

Java堆(Java Heap)是JVM所管理的大内存区域。Java堆是所有线程共享的一块区域,在JVM启动时创建。此内存 区域存放的都是对象实例。JVM规范中说到:“所有的对象实例以及数组都要在堆上分配”。 Java堆是垃圾回收器管理的主要区域,因此很多时候可以称之为"GC堆"。根据JVM规范规定的内容,Java堆可以处 于物理上不连续的内存空间中。Java堆在主流的虚拟机中都是可扩展的(-Xmx设置大值,-Xms设置小值)。如果在堆中没有足够的内存完成实例分配并且堆也无法再拓展时,将会抛出OOM .

5.方法区/元数据区(线程共享)

方法区与Java堆一样,是各个线程共享的内存区域。它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据.
永久代并不意味着数据进入方法区就永久存在,此区域的内存回收主要是针对常量池的回收以及对类型的卸载。JVM规范规定:当方法区无法满足内存分配需求时,将抛出OOM异常

6.常量池

常量池是方法区的一部分,存放字面量与符号引用。
字面量: 字符串(JDK1.7后移动到堆中) ,final常量、基本数据类型的值。 符号引用 : 类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符

直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的 内存区域。但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现.本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是会受到本机总内存(包括RAM以及SWAP区或者分页文件)大小以及处理器寻址空间的限制.

内存溢出与内存泄漏

内存溢出: 系统已经不能再分配出你所需要的空间,比如你需要100M的空间,系统只剩90M了,这就叫内存溢出.
原因:
1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;
4.使用的第三方软件中的BUG;
5.启动参数内存值设定的过小
内存泄漏: 是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光.内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。

JMM(java memory model)

Java内存模型(Java Memory Model,JMM).

JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。
在这里插入图片描述

总结

JVM内存模型(区域)描述的是JVM对所管理的物理内存到底是怎么划分,即某个区域是用来干A事情,另一个区域是用来干B事情的。因为程序的运行需要记录很多数据,有程序中每个线程自己要记录的东西,也有整个程序中所有线程一起共享使用的数据.

所以就搞清楚啦,JVM内存模型是对物理内存功能上的划分.而JMM是一个抽象概念,是对程序/线程对各种变量访问的规范.

所以JVM和JMM没多大关系啦.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值