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

一、java虚拟机的模型

  话不多说,先上张内存模型图吧:

百度来的图,大概也描述清楚了我们常用的虚拟机的内存模型了,主要分为两大类:线程共享(相当于所有线程都可以访问,如果是单线程程序则对应所有方法都能访问)和线程私有(属于某个线程的数据域),其实我们刚刚接触java的时候,会笼统地将内存分为堆内存和栈内存,前者对应的便是线程共享区,后者对应的便是线程私有区。

二、各个区域存放的数据

  1、方法区:存放静态变量、类相关信息(可以理解为class对象的数据和相关方法字节码等)以及字符串等常量。方法区中有一个常量池,它专门存放常用的常量,包括常见的字符串常量。总而言之,这个区域存放的是和类相关的数据。

  2、堆:存放各种方法(包括new操作符,反射,clone,反序列等)创建的对象的数据,和方法区相比较:它是存放对象相关的数据。

  3、虚拟机栈:存放运行时对应线程的所有方法的数据(当然,根据方法的调用顺序以栈的形式存储,后面详细讲),通俗地将,就是存放该线程运行时的一些方法局部变量,这个其实就是初学者所说的栈区域了。

  这里重点补充下方法栈和栈帧的概念:方法之间的调用关系是通过栈来实现的,而每个栈帧代表的是每个方法的对应栈地址,大概画个图说明下:

该示意图对应一下的代码执行块:

//测试类
class Test implements Runnable{
//方法A
public void methodA(){
System.out.println("A方法");
}
//方法B
public void methodB(){
System.out.println("B方法,我调用了A方法");
methodA();
}
//方法C
public void methodC(){
System.out.println("C方法,我调用了B方法");
methodB();
}
public void run() {
//线程执行入口
Test t = new Test();
t.methodC();
} }

代码和示意图大概的意思是:

  A、早调用的方法位于栈的下端,最后调用的方法位于栈的顶端。

  B、方法栈其实就是方法的执行路径,越先调用,越后执行;

  C、栈帧其实就是存储了当前方法的对应栈中的地址值,在每个方法执行完,它都会改变(其实就是栈顶地址)。

  4、程序计数器区域:每个线程运行其实就是通过方法之间的调用进行,而程序计数器就是控制方法调用的代码,该区域存放对应程序计数器执行相关的数据,一般包括当前执行的方法信息以及下一步执行的方法的信息。

  5、本地方法区:本地方法相对于java程序而言的,它不是java程序,一般是java虚拟机运行所需要的一些方法。

三、虚拟机内存与对象的创建和访问

  1、对象的创建

  每个新对象的产生,都会涉及到所有的内存区域(native先不考虑),具体看下面丑图,它具体地展示了一个新对象产生时内存中发生了什么事情:

    

上面的示意图大概说明了对象产生过程内存中发生了什么事情,然后,线程中的虚拟机栈中的方法如何访问堆中的对象?

  2、对象的访问方式:直接引用访问和句柄访问。

  A、直接引用指向堆内存地址的方式。该方式是方法中的对象引用直接指向对象地址,这样做的好处是访问速度快,节省空间(相对于下面的方法而言);但是它在对象进行空间移动后(一般进行垃圾回收时会发生对象的内存位置改变的情况),需要修改所有应用的地址,这样会损失一定的性能;

  B、通过句柄访问对象。该方法相对于直接引用指向对象的方法而言,它在引用和对象之间多了一个句柄,这个句柄存储有对应某个对象的内存地址,当某个引用变量想访问对象时,只需通过该句柄访问即可。该方法会降低引用访问对对象的速度,同时相对于上面的引用直接访问方法也增加了一定的存储空间性能开销,但是在对象进行地址表更时,只需要修改句柄的地址即可。

java虚拟机的大概模型总结到这里,其实总的来说内容也不多,但是弄懂了虚拟机的内存布局的确对于我们理解java程序挺有帮助的。后面将会简单总结下垃圾回收的相关知识点。

java虚拟机的内存机制的更多相关文章

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

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

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

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

  3. JVM学习001通过实例总结Java虚拟机的运行机制

    JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html 文章转载自:http://www.c ...

  4. java 虚拟机的类加载机制

    Java 虚拟机的类加载机制 关于类加载机制: ​ 虚拟机把描述类的数据从Class 文件加载到内存,并对数据进行效验.转换解析和初始化,最终 形成可以被虚拟机直接使用的Java 类型,就是虚拟机的类 ...

  5. java虚拟机的内存模型

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

  6. Java虚拟机的内存管理

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

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

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

  8. Java虚拟机之内存区域

    原创文章,转载请标明出处! 目录 一.背景 二.运行时内存区域概述 1.官方描述 2.中文翻译 3.内存区域简述 4.运行时数据区简图 5.运行时数据区详图 三.JVM线程 JVM数据区域与线程关系 ...

  9. 【进阶之路】深入理解Java虚拟机的类加载机制(长文)

    我们在参加面试的时候,经常被问到一些关于类加载机制的问题,也都会在面试之前准备的时候背好答案,但是我们是否有去深入了解什么是类加载机制呢?这段时间因为一些事情在家看了些书,这次就和大家分享一些关于Ja ...

随机推荐

  1. You can't specify target table 'e' for update in FROM clause

    UPDATE emp e SET e.salary=e.salary+7 WHERE e.id IN(SELECT e1.id FROM emp e1,dept d WHERE e1.dep_id=d ...

  2. HTML防止input回车提交表单

    原链接:https://blog.csdn.net/ligang2585116/article/details/44699567 自动提交情况说明: 1.默认情况下,单个输入框,无论按钮的type=& ...

  3. CASE语句用法学习

    A. 使用带有 CASE 简单表达式的 SELECT 语句 SELECT ProductNumber, Category = CASE ProductLine WHEN 'R' THEN 'Road' ...

  4. spring利用注解方式实现Java读取properties属性值

    1. 建立properties文件:我在resource下面建立一个config文件夹,config文件夹里面有mytest.properties文件,文件内容如下: sam.username=sam ...

  5. Code Chef January Challenge 2019题解

    传送门 \(div2\)那几道题不来做了太水了-- \(DPAIRS\) 一个显然合法的方案:\(A\)最小的和\(B\)所有连,\(A\)剩下的和\(B\)最大的连 算了咕上瘾了,咕咕咕 const ...

  6. 在myeclipse中有的项目上有个红色感叹号

    之前做项目的时候遇到过这个问题,最后确定原因是项目引用了很多放在D盘或E盘上的jar包,但是我们不小心把这些jar包删除或移动路径了,因此myeclipse识别不了出现红色的感叹号,解决方式是在mye ...

  7. [RHEL] RHEL7.0 下 Postfix + Dovecot 实现邮件发送

    RHEL7.0 下 Postfix + Dovecot 实现邮件发送 一.前言 大家都对邮件服务(mail service)很感兴趣嘛.我在自己 博客站 预言了自己会实战一次,访问量一天到十几(毕竟平 ...

  8. 继承Runnable 实现Synchronized 同步锁

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  9. Bootstrap Modal 关闭时右侧滚动条消失,页面左移的解决方法

    问题描述:页面在打开Modal之前右侧有滚动条,Modal关闭之后,body中的class="modal-open"和style="padding-right: 17px ...

  10. Ionic2 启动加载优化总结

    1. ionic2通过ionic serve生成的main.js大于4M,必须先build才能部署 npm run ionic:build --prod 之后main.js缩小为大概100K+ 2. ...