网上流传着一段挺有意思的话……

对于从事C或C++的开发人员来说,他们既是内存管理的最高权力的皇帝,也是最基础的劳动人民,担负着每一个对象生命开始到终结的维护工作,有点光杆司令的赶脚。

但对于java程序员来说,在虚拟机自动内存管理机制的帮助下,不需要手动维护,也不容易出现内存泄漏和溢出的问题。但是如果不了解JVM,一旦出现问题,你就会变得无从下手……

一、JVM

  Java Virtual Machine(java虚拟机),一种虚构的计算机,通过在实际计算机上模拟各种计算机功能实现的。

JVM结构基本上由三大部分组成:类加载器(ClassLoader subsystem),执行引擎(Execution Engine),内存区(Runtime data areas)。

1、类加载器

在JVM启动或类运行时将需要的class字节码(下图的*.class文件)加载到JVM中。

初始类加载器有三个层次:根类、扩展类和系统类加载器。

1)Bootstrap ClassLoader(根类)

2)Extension ClassLoader

3)System ClassLoader

2、执行引擎

负责执行class文件中的指令,得到执行结果。

本质是执行一个个方法串起来的流程,对应操作系统中的一个java线程。

3、内存区

在执行引擎执行前、执行中,都需要存储一些东西,这就用到了java的内存管理,他将内存划分为若干区来模拟实际机器上的存储、记录和调度功能模块。

具体的内存管理内容下面再介绍。

二、工作原理

java语言的跨平台性离不开JVM的作用,下图是编译执行的简化过程。JVM屏蔽了各个计算机平台相关的软件或硬件之间的差异,使得java不需要再考虑平台不同的问题,直接交给JVM就可以了。

三、内存区域

在java虚拟机规范中将java运行时数据划分为以下几种:



1)线程共享

即上图左侧蓝色内容,这两块内容是线程共享的,而不是线程私有的。

堆

堆是储存对象实例的地方,几乎所有的对象实例都是在这里分配的,是JVM管理对象的核心存储区域。

因为在栈中存储的变量等数据都是随线程或方法结束而消失的,但堆中并不是这样,再加上对象实例一般占用内存也比较大,因此Java堆是垃圾收集器管理的主要区域,有时也被成为“GC堆”Garbage Collected Heap。

在实际回收的过程中,如果每次回收都将堆中的对象实例“检查”一遍,看是不是需要回收的话,这样效率太慢了,执行起来太费事了。现在流行的分代收集算法就解决了这一问题,大概意思就是划分出不同的“年代”区域,不同的区域内回收的频率不同,如果多次检查一个实例都不需要释放回收,那我们就把他挪到下一个年代中去。

java堆还可以细分为:新生代和老年代。新生代还可以细分为:Eden、From Survival,To Survival等。详情见下图。

方法区

方法区用于存储类结构信息,包括类信息、常量、静态变量等。在HotSpot虚拟机中,方法区中为“永久代”。因此,垃圾回收器很少光顾这部分区域,这部分比老年代的回收频率更低。

方法区中比较常用的是运行时常量池( Runtime Constant Pool),代表运行时每个class文件中的常量表,位于方法区中。

2)其他


内存区域图中的右侧内容,该部分是线程私有的。

程序计数器

指示当前线程所执行的字节码的行号,但如果执行的native方法,计数器值为空。

很多Native方法都是用C语言实现的,通常叫他C栈,直接放入本地方法栈中执行。

Java虚拟机栈

java栈是线程私有的,每启动一个新线程,java虚拟机就会给他分配一个(以帧为单位的)java栈。他的生命周期和线程相同。执行的操作有两种:压栈和出栈。

四、实例分析

补充了这么多理论知识,是时候该来个例子巩固一下了……

public class Person {

    private Integer id;
private String name;
private String password; public Person(Integer id, String name, String password) {
super();
this.id = id;
this.name = name;
this.password = password;
} //get和set方法省去 } //测试类
public class Test {
public static void main(String[] args) {
Test test=new Test();
int id=1;
Person p1=new Person(2,"Sherry","123");
Person p2=new Person(3,"yang","456"); test.change(id);
} public void change(int i){
i=8;
}
}

Step1:

main()方法是程序的入口,当执行完main方法的前两行代码之后,内存中的情况大致如下图所示:

注意:

图中的“xxx”代表持有引用的地址。

虽然在上面的内存图中,左侧为堆右侧为栈,但为了更清楚的表示引用关系,这里就把栈画在左侧,堆在右侧。

Step2:

执行完第四行代码时

注意:此时test和id的内存块并不会释放,因为对象还未死,或者说引用还在。使用new创建的对象实例保存在堆中,但变量p1、p2在栈中,持有着实例的地址,即图中的“xxx”。

Step3:

第五行代码调用change(),此时需要创建一个新的栈帧。当调用结束之后,变量i的内存块和change()方法的栈帧一并消失。

小结

这篇博客只是对jvm进行了简单的介绍,很多东西只是提了一下,没有深入了解,后续会进行补充和完善。如果哪里理解的不合理,还请交流指正。

JVM(1)——简介的更多相关文章

  1. 老李分享:jvm结构简介 1

    老李分享:jvm结构简介     poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9088214 ...

  2. 老李分享:jvm结构简介 2

    2.2.4 Program counter regsiters:程序计数器 类似于PC寄存器,是一块较小的内存区域,通过程序计数器中的值寻找要执行的指令的字节码,由于多线程间切换时要恢复每一个线程的当 ...

  3. java语言与jvm虚拟机简介

    一.java语言 1.1 支持面向对象编程oop 强调支持,因为java同样可以面向过程编程. oop的三大特性是:封装.继承.多态. 封装主要针对成员变量而言,oop的思想要求成员变量均为私有,不应 ...

  4. JVM锁简介:偏向锁、轻量级锁和重量级锁

    转自:https://www.aimoon.site/blog/2018/05/21/biased-locking/ 比较复杂,简略见另一篇:https://www.cnblogs.com/twohe ...

  5. JVM性能优化, Part 1 ―― JVM简介

    JVM性能优化这些列文章共分为5章,是ImportNew上面翻译自Javaworld: 第1章:JVM技术概览 第2章:编译器 第3章:垃圾回收 第4章:并发垃圾回收 第5章:可伸缩性 众所周知,Ja ...

  6. Java JVM、JNI、Native Function Interface、Create New Process Native Function API Analysis

    目录 . JAVA JVM . Java JNI: Java Native Interface . Java Create New Process Native Function API Analys ...

  7. Java内存管理-初始JVM和JVM启动流程(二)

    勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分享了什么是程序,以及Java程序运行的三个阶段.也顺便提到了Java中比较重要 ...

  8. 一个性能较好的JVM参数配置

    一个性能较好的web服务器jvm参数配置: -server//服务器模式-Xmx2g //JVM最大允许分配的堆内存,按需分配-Xms2g //JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次 ...

  9. 一个性能较好的JVM参数配置(转)

    一个性能较好的web服务器jvm参数配置: -server//服务器模式-Xmx2g //JVM最大允许分配的堆内存,按需分配-Xms2g //JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次 ...

  10. JVM CPU Profiler技术原理及源码深度解析

    研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程序运行行为和性能瓶颈.Profiling技术是一种在应用运行时收集程序相关信息的动态分析手段,常用的JVM Profiler可以从多个方面对程 ...

随机推荐

  1. Apache httpd Server 配置正向代理

    背景 代理(Proxy),位于客户端与实际服务端之间,当客户端需要请求服务端内容时,先向代理发起请求,代理将请求转发到实际的服务器,再原路返回.也可以在代理服务器设置缓存,将实际服务器上不常变化的内容 ...

  2. Asp.Net Core 生成图形验证码

    前几天有朋友问我怎么生成图片验证码,话不多说直接上代码. 支持.NET CORE开源.助力.NET Core社区发展. using System; using System.IO; using Sys ...

  3. python中string,time,datetime三者之间的转化

    这里time特指import time中的对象,datetime 特指from datetime import datetime中的对象,string指python自带的字符数据类型. 从使用的情况来 ...

  4. latex01-LaTeX环境的安装与配置

    以Tex Live (跨平台的发行版软件)为例. 1.官网下载iso镜像文件 2.用advanced.bat 安装(管理员权限) 选择要安装的包(主要是去掉多余的语言包) 测试Tex Live 是否正 ...

  5. GDOI DAY1游记

    今天,是本蒟蒻的第一次参加GDOI,真激动! 今天,是GDOI第一天,昨天熬夜打代码,今天早上状态十分不好,于是... 进入了考场,叫我们自由打一会代码,于是...打了一坨AC机,重要的是错了(额.. ...

  6. windows 安装 .net core 环境

    windows 安装 环境说明 window10系统 .net core 1.0.1 visual studio code 安装 .net core Windows系统下安装软件基本上属于傻瓜式安装, ...

  7. STL 入门 (17 暑假集训第一周)

    快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...

  8. python2.7练习小例子(八)

        8):题目:输出 9*9 乘法口诀表.     程序分析:分行与列考虑,共9行9列,i控制行,j控制列.     程序源代码: #!/usr/bin/python # -*- coding: ...

  9. 用intellij Idea加载eclipse的maven项目全流程

    eclipse的maven项目目录 全流程 加载项目 打开intellij Idea file -> new -> module from existing Sources  选择.pom ...

  10. easyui 验证动态添加和删除问题

    $.extend($.fn.validatebox.methods, { remove: function(jq, newposition){ return jq.each(function(){ $ ...