VM,Virtual Machine 即虚拟机,指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。

JVM,Java Virtual Machine 即Java虚拟机,在Java编辑器与OS操作系统之间的虚拟处理器,其模拟计算机的各种功能,将编译后的字节码解释成具体平台上的机器指令执行,从而实现Java的“一次编译,到处运行(Write once, run anywhere)

一、基本流程

开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),再然后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。

在Java平台的结构中, 可以看出,Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。

它的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作系统上实现;

在JVM 的上方是Java的基本类库和扩展类库以及它们的API, 利用Java API编写的应用程序(application) 和程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java 的平台无关性。

JVM在它的生存周期中有一个明确的任务,那就是运行Java程序,因此当Java程序启动的时候,就产生JVM的一个实例;当程序运行结束的时候,该实例也跟着消失了。

二、Jvm结构

1、类加载器(ClassLoader):负责从文件系统或者网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中可能还会存放运行时常量池信息,包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)

2、方法区(Method Area):用于存储类结构信息的地方,包括常量池、静态变量、构造函数等。虽然JVM规范把方法区描述为堆的一个逻辑部分, 但它却有个别名non-heap(非堆),所以大家不要搞混淆了。方法区还包含一个运行时常量池。

3、java堆(Heap):在虚拟机启动的时候建立,它是java程序最主要的内存工作区域;几乎所有的java对象实例都存放在java堆中;方法区和堆是被所有java线程共享的。

4、jvm栈(Stack):线程私有的内存空间;每当创建一个线程时,JVM就会为这个线程创建一个对应的jvm栈;

5、本地方法栈(Native Method Stack):用于支持native方法的执行,存储了每个native方法调用的状态;jvm栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务;

6、程序计数器(PC Register):线程私有,用于保存当前线程执行的内存地址。由于JVM程序是多线程执行的(线程轮流切换),所以为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)

7、执行引擎:负责执行class文件中包含的字节码指令;

  •  java堆

存放对象实例;完全自动化管理的,通过垃圾回收机制,垃圾对象会被自动清理,而不需要显示的释放;

常见构成:新生代和老年代,Enden区和两个Survivor区(From和to);Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可;一般按照可扩展来实现的(通过-Xmx和-Xms控制)

在绝大多数情况下,对象首先分配在eden区,在一次新生代回收之后,如果对象还存活,则进入s0或者s1,

每经过一次新生代回收,对象如果存活,它的年龄就会加1。当对象的年龄达到一定条件后,就会被认为是老年对象,从而进入老年代。

java堆、方法区和java栈之间的关系

 package com.jvm;
public class SimpleHeap {
  private int id;
  public SimpleHeap(int id){
    this.id = id;
  }
  public void show(){
    System.out.println("My id is "+id);
  }   public static void main(String[] args) {
    SimpleHeap s1 = new SimpleHeap(1);
    SimpleHeap s2 = new SimpleHeap(2);
    s1.show();
    s2.show();
  }
}

该代码声明了一个类,并在main函数中创建了两个SimpleHeap实例。此时,各对象和局部变量的存放情况如图:

SimpleHeap实例本身分配在堆中,描述SimpleHeap类的信息存放在方法区,main函数中的s1 s2局部变量存放在java栈上,并指向堆中两个实例。

  • java栈

线程私有的内存空间;先进后出的数据结构;主要内容为栈帧(至少包含局部变量表、操作数栈和帧数据区几个部分);每一次函数调用,都会有一个对应的栈帧被压入java栈,每一个函数调用结束,都会有一个栈帧被弹出java栈(进栈出栈)

当前正在执行的函数所对应的帧就是当前帧(位于栈顶),它保存着当前函数的局部变量、中间计算结果等数据;

每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

两种异常状况:

如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常(增大-Xss的值);

如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。

 public static void recursion(){
    count++;
    recursion();
}

局部变量表是栈帧的重要组成部分之一;表中的槽位可以重用;

它用于保存函数的参数以及局部变量,局部变量表中的变量只在当前函数调用中有效,当函数调用结束,随着函数栈帧的弹出销毁,局部变量表也会随之销毁。

由于局部变量表在栈帧之中,因此,如果函数的参数和局部变量很多,会使得局部变量表膨胀,从而每一次函数调用就会占用更多的栈空间, 死循环下,函数的嵌套调用次数减少;

局部变量表中的变量也是垃圾回收根节点,只要被局部变量表中直接或者间接引用的对象都是不会被回收的。

可回收:方法结束变量失去引用后的方法外部,方法内变量被置null失去强引用,变量离开作用域并且再定义新变量复用空间;(销毁变量即可回收)

小问小答

类加载 http://blog.csdn.net/boyupeng/article/details/47951037

概念问题 https://www.toutiao.com/a6421302542316241154/

调优问题 https://www.toutiao.com/a6511998857537126925/

GC问题 https://www.toutiao.com/a6493469044564296205/

JAVA总结--jvm的更多相关文章

  1. java内功 ---- jvm虚拟机原理总结,侧重于虚拟机类加载执行系统

    参考书籍:<深入理解java虚拟机>,三天时间用了八个小时看完,像读一本武侠小说,挺爽. 另外需声明:图片都是从我自己的csdn博客转载,所以虽然有csdn标识,但都是我自己画的图片. j ...

  2. Java虚拟机JVM学习07 类的卸载机制

    Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...

  3. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  4. Java虚拟机JVM学习05 类加载器的父委托机制

    Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...

  5. Java虚拟机JVM学习04 类的初始化

    Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...

  6. Java虚拟机JVM学习03 连接过程:验证、准备、解析

    Java虚拟机JVM学习03 连接过程:验证.准备.解析 类被加载后,就进入连接阶段. 连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去. 连接阶段三个步骤:验证.准备和解析. 类 ...

  7. Java虚拟机JVM学习02 类的加载概述

    Java虚拟机JVM学习02 类的加载概述 类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对 ...

  8. Java虚拟机JVM学习01 流程概述

    Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...

  9. Dalvik VM (DVM) 与Java VM (JVM)之间有哪些区别?

    Dalvik虚拟机存在于Android系统,JVM是java虚拟机,两者都是虚拟机,本文就对两者进行比较,讲述它们的不同. Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的 ...

  10. JAVA的JVM虚拟机工作原理.V.1.0.0

    注意:一下内容纯属个人理解,如有错误,欢迎批评指正. (90度弯腰)谢谢. java在JVM上的运行过程: 1,编辑好的java代码(IDE无报错,测试运行无错误): 2,java源代码通过javac ...

随机推荐

  1. bzoj4129 Haruna’s Breakfast 树上带修莫队+分块

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...

  2. AGC009题解

    为了1天4题的flag不倒所以开新坑... B. 考虑把这棵树直接建出来,f[i]表示i最少的比赛次数,然后按照定义转移就行了. //Love and Freedom. #include<cst ...

  3. div中放入一个img元素导致div高度会多出几个像素

    在写代码的时候经常遇到这样一个问题,如果div里嵌套一个img元素且div的高度是由img的高度来撑开,那么div的高度总会比img的高度多3px.好了,废话不多说,直接给大家上代码. html代码: ...

  4. 多个excel文件内容合并到一个excel文件的多个sheet的小程序

    # -*- coding:utf-8 -*- import xlrd, xlsxwriter # 待合并excelallxls = ["D:\\excelcs\\***.xlsx" ...

  5. Docker(三):Docker入门教程-CentOS Docker 安装

    CentOS Docker 安装 Docker支持以下的CentOS版本: CentOS 7 (64-bit) CentOS 6.5 (64-bit) 或更高的版本 前提条件 目前,CentOS 仅发 ...

  6. APIO2019解题报告

    「APIO 2019」奇怪装置 题目描述 有无限个二元组,每个二元组为\(((t+\left\lfloor\frac{t}{B} \right\rfloor)\%A,t \% B)\),给出一些区间, ...

  7. UOJ418. 【集训队作业2018】三角形

    http://uoj.ac/problem/418 题解 考虑激活每个节点时,它的每个儿子都是放满的. 那每一次的操作我们可以用一个二元组来表示\((w_i-\sum w_{son},\sum w_{ ...

  8. PowerDesigner相关总结

    1.PowerDesigner 工具生成数据库Report指导 摘自:https://www.cnblogs.com/zycblog/archive/2010/05/11/1732918.html 1 ...

  9. React Native商城项目实战12 - 首页头部内容

    1.HomeTopView为首页头部内容,HomeTopListView为HomeTopView子视图. 2.HomeTopView.js /** * 首页头部内容 */ import React, ...

  10. DAY 6 上午

    如果不是割点,答案减少2(n-1) 如果删去割点,删去之后整个图分成多个连通块 每一个联通块的大小*其他连通块的大小之和 先求出缩点之后的树 加尽可能少的边使树变成一个边双 找出树上的所有叶子节点(度 ...