前言

要了解Java虚拟机首先要知道的基础就是内存。虚拟机存在的意义就是对内存进行管理,因为不用人为的去管理每个对象的内存,所以才让java使用起来那么方便,不用像c、c++那样去free。

运行时数据区

Java所管理的内存划分为不同的区域,每个区域都有自己的用处。

1、程序计数器PC

如果你学过汇编的话就很好理解,在计算机中指令是一条条执行的,PC就是记住当前执行到哪一行了。需要注意的是,每条线程都需要一个独立的PC,且互相之间不影响。

2、虚拟机栈

栈是一个在程序设计的时候很常见的一个数据结构,有一定计算机基础的话,你知道递归的实现其实就是利用栈,也知道递归的深度过大会导致栈溢出。而在Java虚拟机中栈是描述Java方法执行的内存模型,每个方法的执行就是虚拟机中一个入栈出栈的过程。

3、本地方法栈

这个栈和虚拟机栈一样,只是这个栈是一个VIP,只有native方法才会使用到这个栈,那什么是native方法呢?java方法可能会调用到非java-code的方法,如c的方法,这样的方法称为native方法。

4、堆

堆是最重要的一块也是比较复杂的一块区域,因为几乎所有的对象实例都在堆里分配内存。堆是垃圾回收的主要区域,因为很多用过之后没有用的对象都在这里了,它们所占用的内存都需要被回收。

5、方法区

用于存储已经被虚拟机加载的类信息、常量、静态变量等。看到它的功能基本可以想象到,它存放的东西基本上都属于那种不可改变而且一直存在的量,所以这个区域有时被称为“永久代”但是记住它们不一定都是永久的,这个区域也会被回收,只是相对来说没有像堆那样。

对象创建

内存是用来存放对象的,那么java是如何创建一个对象的呢?首先我们知道创建一个对象就是new出来,虚拟机在new之前还要做的事情是确定这个类是否已经被正确加载了。

接下来就是去分配内存了,当类被加载完成之后,我们就知道这个对象需要多大的内存了。如果内存是完整的,那就像切蛋糕一样切出一块来,如果内存是分散的,那就需要找一块足够大的切了。而内存是分散的还是完整的取决于垃圾回收的算法。

然后设置对象的参数,如这个对象是哪个类的实例,哈希码,GC分代年龄等。

最后再执行对象的init方法给每个需要的字段进行赋值,然后根据这个对象的构造方法进行初始化。

对象的访问

那么我们创建了一个对象之后,我们如何访问这个对象呢?这个时候就用到了我们的栈了,栈记录了一个对象的引用reference。这里有两种方式,第一种是这个引用数据保存了句柄数据然后堆中有一个句柄池其中记录了对象实例数据的指针,我们通过引用找到句柄池中的位置,再通过指针找到对象。第二种是指针访问,也就是直接储存了对象的地址。句柄的好处是,对象移动时reference不用改变,指针的好处是速度快。

感受虚拟机

我们运行两个程序来直观感受一下虚拟机到底做了什么事情

首先运行下面这个程序

import java.util.ArrayList;
import java.util.List; /**
* @author LinkinStar
*/
public class T {
static class A {
} public static List<A> list = new ArrayList<>(); public static void main(String[] args) {
while (true) {
list.add(new A());
}
}
}

需要注意的是,需要调整一下虚拟机的参数

Xms是JVM初始分配的堆内存

Xms是JVM最大允许分配的堆内存

然后运行就能看见异常Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

然后在相同的条件下我们运行第二个程序

/**
* @author LinkinStar
*/
public class T {
static class A {
} public static void main(String[] args) {
while (true) {
new A();
}
}
}

你会发现没有什么异常,然后你需要做的是,对比两个程序,看看这两个程序有什么不一样,这样的不一样为什么会导致这样的结果。理解了,你就知道java虚拟机到底在做什么事情了。

上面的测试是模拟了堆溢出的情况,还有方法区溢出,常量池溢出,栈溢出等,出现StackOverflowError或者OutOfMemoryError。

我们所要知道的是出现这样错误是什么样的原因导致的,以上就是在内存方向上虚拟机相关。

大战Java虚拟机【1】—— 内存的更多相关文章

  1. 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

    程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...

  2. 深入理解java虚拟机【内存溢出实例】

    通过简单的小例子程序,演示java虚拟机各部分内存溢出情况: (1).java堆溢出: Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收 ...

  3. 从Java虚拟机的内存区域、垃圾收集器及内存分配原则谈Java的内存回收机制

    一.引言: 在Java中我们只需要轻轻地new一下,就可以为实例化一个类,并分配对应的内存空间,而后似乎我们也可以不用去管它,Java自带垃圾回收器,到了对象死亡的时候垃圾回收器就会将死亡对象的内存回 ...

  4. Java虚拟机:内存模型详解

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实 ...

  5. 初识:java虚拟机的内存划分

    什么是内存? 内存是计算机中的重要原件,临时存储区域,作用是运行程序.我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存.Java虚拟机要运行程序 ...

  6. java虚拟机的内存模型

    一.为什么要了解java虚拟机的内存模型 java虚拟机作为java代码运行的平台,是java技术的基石.了解java虚拟机的内存模型也就变得十分必要.它能帮助我们更好的了解java代码的运行机制,更 ...

  7. java虚拟机的内存机制

    我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上.所以,对java的学习,离不开对java虚拟机的学习与了解.下面简单整理下j ...

  8. Java虚拟机的内存管理

    众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作. 虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏. 反而,某 ...

  9. 1 - JVM随笔分类(java虚拟机的内存区域分配(一个不断记录和推翻以及再记录的一个过程))

    java虚拟机的内存区域分配   在JVM运行时,类加载器ClassLoader在加载到类的字节码后,交由jvm的执行引擎处理, 执行过程中需要空间来存储数据(类似于Cpu及主存),此时的这段空间的分 ...

  10. JAVA虚拟机:内存各个区介绍

    概述:java应用程序由java虚拟机自动管理程序执行期间内存管理. 优势:1.不再需要程序员去为使用的内存在程序中手动编写释放内存代码. 2.由虚拟机管理内存不容易出现内存泄漏和内存溢出的问题. 缺 ...

随机推荐

  1. MQTT之Mosquitto

    https://mosquitto.org/ Eclipse Mosquitto是一个开源(EPL / EDL许可)消息代理,它实现了MQTT协议版本3.1和3.1.1.Mosquitto重量轻,适用 ...

  2. PC网站转换成手机版

    博客地址:https://www.cnblogs.com/zxtceq/p/5714606.html 一天完成把PC网站改为自适应!原来这么简单! http://www.webkaka.com/blo ...

  3. 引用Excel控件时,无法嵌入互操作类型“Microsoft.Office.Interop.Excel.ApplicationClass”请改用适用的接口

    类型Microsoft.Office.Interop.Excel.ApplicationClass未定义构造函数 无法嵌入互操作类型“Microsoft.Office.Interop.Excel.Ap ...

  4. MongoDB 用Robomong可视化工具操作的 一些简单语句

    一.数据更新 db.getCollection('表名').update({ "字段":{$in:["值"]} }, //更新条件 {$set:{ " ...

  5. ASP.NET C# 实现实时用户在线

    public static class UserOnline { /// <summary> /// 获取或设置在线列表 /// </summary> public stati ...

  6. 你不知道的JS之作用域和闭包(五)作用域闭包

    原文:你不知道的js系列 一个简单粗暴的定义 闭包就是即使一个函数在它所在的词法作用域外部被执行,这个函数依然可以访问这个作用域. 比如: function foo() { var a = 2; fu ...

  7. Springboot搭建SSM+JSP的web项目

    Springboot搭建SSM+JSP的web项目 一:创建项目结构: 项目结构分为三个部分: 1 后端项目开发文件: 包: Util         工具包 Mapper      db层 Serv ...

  8. post数据时报错:远程服务器返回错误: (400) 错误的请求。

    网上查了多种方法,有不少说法,报400说是传的数据格式不对,最后的结论确实是数据格式不对. Content_Type为:application/json,配的数据格式有些麻烦,特别数多层,单层还好.例 ...

  9. lua语言自学知识点----Lua与.Net相互调用

    知识点: LuaInterface作用是用来完成Lua与C#的相互调用. LuaInterface核心库:1.luainterface.dll 用于C#读取lua(放在bin目录同级) 2.luane ...

  10. charles-web端开发者实用功能点

    ##网速模拟功能 throttle功能对于前端来说非常实用,可以看页面在低网速下的表现,从而找出优化的点. 在线上环境通常有些因为网速慢导致的bug,在本机无法重现,那时候就很抓瞎,如果嫌远程麻烦,推 ...