1-JVM内存模型

Java开发人员一般情况下,使用过程中,不用关注内存的申请和释放,得益于JVM自动内存分配机制,但是其实是个双刃剑,这可以提升Java开发的效率,但是弱化了开发人员内存管理意识,系统容易发生内存异常,垃圾回收(GC)的方式不合适以及GC次数过于频繁等问题,这些都将直接影响到应用服务的性能。

在Java中,JVM内存模型主要分为堆、程序计数器、方法区、虚拟机栈和本地方法栈。

1.1-堆

堆是JVM内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由From Survivor和To Survivor组成。

在Java6版本中,永久代在非堆内存区;到了Java7版本,永久代的静态变量和运行时常量池被合并到了堆中;而到了Java8,永久代被元空间取代了,元空间存储静态变量和运行时常量池与Java7的永久代一样,都移到了堆中。 结构如下图所示:

1.2-程序计数器

程序计数器是一块很小的内存空间,主要用来记录各个线程执行的字节码的地址,例如,分支、循环、跳转、异常、线程恢复等都依赖于计数器。

1.3-方法区

方法区主要是用来存放已被虚拟机加载的类相关信息,包括类信息、运行时常量池、字符串常量池。类信息又包括了类的版本、字段、方法、接口和父类等信息。

方法区只是JVM中规范的一部分,可以说,在HotSpot虚拟机中,设计人员使用了永久代来实现了JVM规范的方法区。

JVM的内存模型只是一个规范,方法区也是一个规范,一个逻辑分区,并不是一个物理空间,我们这里说的字符串常量放在堆内存空间中,是指实际的物理空间。

元空间是属于方法区的,方法区只是一个逻辑分区,而元空间是具体实现。所以类的元数据是存放在元空间,逻辑上属于方法区。

在HotSpot虚拟机、Java7版本中已经将永久代的静态变量和运行时常量池转移到了堆中,其余部分则存储在JVM的非堆内存中,而Java8版本已经将方法区中实现的永久代去掉了,并用元空间(class metadata)代替了之前的永久代,并且元空间的存储位置是本地内存。之前永久代的类的元数据存储在了元空间,永久代的静态变量(class static variables)以及运行时常量池(runtime constant pool)则跟Java7一样,转移到了堆中。

Java8为什么使用元空间替代永久代?

官方给出的解释是:

  • 移除永久代是为了融合 HotSpot JVM 与 JRockit VM 而做出的努力,因为JRockit没有永久代,所以不需要配置永久代。

  • 永久代内存经常不够用或发生内存溢出,爆出异常java.lang.OutOfMemoryError: PermGen。这是因为在JDK1.7版本中,指定的PermGen区大小为8M,由于PermGen中类的元数据信息在每次FullGC的时候都可能被收集,回收率都偏低,成绩很难令人满意;还有,为PermGen分配多大的空间很难确定,PermSize的大小依赖于很多因素,比如,JVM加载的class总数、常量池的大小和方法的大小等。

1.4-虚拟机栈

Java虚拟机栈是线程私有的内存空间,它和Java线程一起创建。当创建一个线程时,会在虚拟机栈中申请一个栈帧,用来保存方法的局部变量、操作数栈、动态链接方法和返回地址等信息,并参与方法的调用和返回。每一个方法的调用都伴随着栈帧的入栈操作,方法的返回则是栈帧的出栈操作。

1.5-本地方法栈

本地方法栈跟Java虚拟机栈的功能类似,Java虚拟机栈用于管理Java函数的调用,而本地方法栈则用于管理本地方法的调用。但本地方法并不是用Java实现的,而是由C语言实现的。

2-JVM运行原理

通过示例来认识JVM运行的原理

示例代码

public class JVMCase {// 常量public final static String MAN_SEX_TYPE = "man";// 静态变量public static String WOMAN_SEX_TYPE = "woman";public static void main(String[] args) {Student stu = new Student();stu.setName("nick");stu.setSexType(MAN_SEX_TYPE);stu.setAge(20);JVMCase jvmcase = new JVMCase();// 调用静态方法print(stu);// 调用非静态方法jvmcase.sayHello(stu);}// 常规静态方法public static void print(Student stu) {System.out.println("name: " + stu.getName() + "; sex:" + stu.getSexType() + "; age:" + stu.getAge()); }// 非静态方法public void sayHello(Student stu) {System.out.println(stu.getName() + "say: hello"); }
}class Student{String name;String sexType;int age;
//省略get/set}

当我们通过Java运行以上代码时,JVM的整个处理过程如下:

1-JVM向操作系统申请内存,JVM第一步就是通过配置参数或者默认配置参数向操作系统申请内存空间,根据内存大小找到具体的内存分配表,然后把内存段的起始地址和终止地址分配给JVM,接下来JVM就进行内部分配。

2-JVM获得内存空间后,会根据配置参数分配堆、栈以及方法区的内存大小。

3-class文件加载、验证、准备以及解析,其中准备阶段会为类的静态变量分配内存,初始化为系统的初始值。

4-完成上一个步骤后,将会进行最后一个初始化阶段。在这个阶段中,JVM首先会执行构造器<clinit>方法,编译器会在.java 文件被编译成.class 文件时,收集所有类的初始化代码,包括静态变量赋值语句、静态代码块、静态方法,收集在一起成为 <clinit>() 方法。

5-执行方法。启动main线程,执行main方法,开始执行第一行代码。此时堆内存中会创建一个student对象,对象引用student就存放在栈中。

6-此时再次创建一个JVMCase对象,调用sayHello非静态方法,sayHello方法属于对象JVMCase,此时sayHello方法入栈,并通过栈中的student引用调用堆中的Student对象;之后,调用静态方法print,print静态方法属于JVMCase类,是从静态方法中获取,之后放入到栈中,也是通过student引用调用堆中的student对象。

JVM-01-JVM知识相关推荐

  1. 【重难点】【JVM 01】OOM 出现的原因、方法区、类加载机制、JVM 中的对象

    [重难点][JVM 01]OOM 出现的原因.方法区.类加载机制.JVM 中的对象 文章目录 [重难点][JVM 01]OOM 出现的原因.方法区.类加载机制.JVM 中的对象 一.OOM 出现的原因 ...

  2. java的JVM虚拟机相关知识,简单易懂。

    一.    Java class执行方式 1)  概要 Java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次 ...

  3. 01.JVM内存区域

    01.JVM内存区域 0101.运行时数据区 程序计数器 存储:下一段要执行的代码的地址 共享:线程私有 特点:占用非常小的内存空间 OOM:唯一不会出现OOM的区域 虚拟机栈: 存储: 方法执行的线 ...

  4. JVM速补知识,还不来抱大腿!

    概述 1.什么是虚拟机? Java 虚拟机,是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被编译成能被 Java 虚拟机执行的字节码文件( .class ). 跨平台的是 Java 程 ...

  5. 深入理解JVM之JVM内存区域与内存分配

    在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处: http://www.cnblogs. ...

  6. 第五篇:初识JVM,JVM自动内存管理

    文章目录 一.前言 1.1 计算机==>操作系统==>JVM 1.1.1 虚拟与实体(对上图的结构层次分析) 1.1.2 Java程序执行(对上图的箭头流程分析) 二.JVM内存空间与参数 ...

  7. JVM详解——什么是JVM、JVM优点

    JVM详解--什么是JVM.JVM优点 最近在学习Java,经常在书中看到JVM这三个字母,那到底什么是JVM呢? 并且JVM的知识在Java面试中也是非常受面试官青睐的知识点,那对于JVM我们到底要 ...

  8. JVM之JVM内存区域与内存分配(转载)

    2019独角兽企业重金招聘Python工程师标准>>> 先来看看JVM运行时候的内存区域 大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区),He ...

  9. 小师妹学JVM之:JVM的架构和执行过程

    文章目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础 ...

  10. JVM笔记(JVM内存+垃圾回收器)详解

    一:java代码的执行流程(引出JVM) 首先由程序员编写成.java文件 然后由javac(java编辑器)将.java文件编译成.class文件 .class文件可以在不同平台/操作系统上的JVM ...

最新文章

  1. mybatis-plus对datetime返回去掉.0_华为AI认证-TensorFlow2.0编程基础
  2. 【深度学习】Transfomer在文本处理上的应用(风格识别)
  3. 4.7 参数 vs 超参数-深度学习-Stanford吴恩达教授
  4. Acwing第 14 场周赛【完结】
  5. c# 两个list比较_C#刷遍Leetcode面试题系列连载(1) 入门与工具简介(VS Code amp; VS)...
  6. 安卓世界微观搏杀激烈,网易云信教你存活绝招
  7. Java 图形用户界面 AWT事件处理
  8. Python安装教程分享
  9. 在unity2d同屏显示9千人
  10. 异常处理准则和最佳实践
  11. linux培训笔记1
  12. 利用redis-sentinel+keepalived实现redis高可用
  13. 搜索推荐广告中的Position Bias:美团DPIN
  14. 在远程MQ上启动应用程序时,IBM MQ更改用户标识
  15. 2345浏览器网址_清理流氓网站2345.com劫持浏览器
  16. Roboter's blog » python 读取ini文件
  17. [论离职]走的人不少,来的人更多
  18. Python 数据处理数据挖掘(五):线性回归
  19. 谷歌身份验证器插件以及基于utools的otp快捷使用
  20. 『Java安全』反序列化-浅析Hessian反序列化POP链

热门文章

  1. BCGControlBar使用工具教程
  2. [Windows Server 2012] MySQL移机方法
  3. SQL中where 1=1是什么意思?
  4. 数据降维-MDS 算法
  5. 逐浪字库打造最全的书法字体,最全的合集(字体书法欣赏下载)
  6. 前三位必须是大写字母的正则,长度限制5位
  7. 西班牙馅饼 ECNU3528 java
  8. Docker学习笔记 [声明:基于官网教程的学习笔记]
  9. nodeJS - 1 - Buffer处理二进制数据
  10. SQL Server Browser是什么