在C++领域,关于C++的内存存储,结构等等,有一本书:深度探索C++对象模型,讲解的非常透彻。

而Java确把这一工作交给了虚拟机来处理。

我们首先来看看关于内存的问题。

1.问题:

1)java 的局部变量存在那里,类型怎么存放的?

2)static 变量

3)final 变量

4)method是存放的那里的

5)class类 & 内部类 是如何存放

2.java虚拟机运行时数据区

2.1程序计数器

线程隔离数据,记录当前线程执行的位置。

PC计数器

由于Java虚拟机的多线程,是由线程轮换的方式分配CPU的。所以线程切换后,需要恢复到原来执行的地方

所有线程都需要一块内存来记录这个执行位置,此内存是线程私有的。这块内存称为Program Counter Registers

2.2Java虚拟机栈

这个栈就是我们常见的java 面试题中一般会问 heap & stack 的区别。 这里的stack就是我们说的虚拟机栈。

这个栈是存放每个method执行的时候的局部变量表,动态连接,方法出口等信息。这个栈也是线程私有的。每个方法执行过程,对应

一个栈帧在虚拟机栈的入栈和出栈过程。

局部变量表存放:已知基本类型的变量,对象引用,也就是指向对象的指针,或者句柄,和retuanaddress地址。

栈中可以理解为存放对象的引用,而对象本身存放在堆。

当然64位的double & long会占据2个Slot。其余的数据占据1个。

如果申请的内存不够,就会OOM。

2.3本地方法栈

这个东西同Java虚拟机栈非常类似,这里存放这native方法的一些信息。

2.4Java堆

千呼万唤始出来,对象实例就是存放在这个地方。也是java内存最大的地方。

java所有的线程共享这一块内存。此内存的唯一目的就是存放对象实例。

GC的主要工作就是释放这里不用的内存。

这块区域为所有线程共享。所以android就会有activity或者service在非前台状态下,是否低优先级的情况。

2.5方法区

这块地方存放的就是已经加载的类信息,静态变量,常量等。

String abc = “abc”; 这后面的“abc”就存放在这里。

2.5.2 运行时常量区

java在非编译阶段,也可以是一种常量的形式,比如:

String str = "abc"+"d";

它会生成“abcd”常量在运行时候。

运行是常量是方法区的一部分。

3.HotStot虚拟机对象探秘

java对象的创建过程分成2步:

1)加载类信息,存放在方法区

2)根据类信息,分配内存存放对象,内存在堆区。

分配内存的常见方式:

1)假设内存在堆区分为2块,一块是已经在使用的,一块是还没有分配的,这样我只要设置一个指针,来区分这两块区域。

当分配新的内存时,移动指针即可。

2)内存区域是不连续的,这样我只能在空闲的内存中,找到一块足够大的内存来分配,这种为空闲列表的方式。

但是,当分配内存时,会有同步的问题。

要么保证分配操作是原子操作,或者就是给每个线程优先分配一小块内存(Thread Local Allocation Buffer)

这个东西在android looper机制的时候,有所体现。

接下来就是对对象进行设置:

对象是那个类的实例,如何才找到对象的元数据信息,对象的hash表,对象的GC分布年龄等。

从程序员的角度看,一个对象在内存中已经创建,但是init的方法还没有执行。对象还没有按照程序员的意愿进行初始化。

3.1 对象的内存布局

在HotStot中,对象的布局可以分为3块:对象头,实例数据,和对其填充。

对象头根据虚拟机的位数,32bit或者64bit。

这部分被以极限的算法,来存储不少的信息。

实例数据部分,存的是真正有效的信息,这部分会存父类的信息和子类的信息。

3.2对象的访问方式

reference 指向的是另一个类的对象,所以它指向的实际是堆中的另一块内存而已。

HotSopt使用的是第二种方式。

5.几个问题的答案

1)java 的局部变量存在那里,类型怎么存放的?

java的局部变量存放在虚拟机栈中的 该线程的栈帧,里面的局部变量表里面。

class对象的引用存放在局部变量表里。对象实例存放在java堆中。对象类型或者类信息存放在方法区。

2)static 变量

也存放在方法区内。

3)final 变量

final只是修饰变量的赋值行为,对变量的内存没有影响。所以有没有final不影响变量的存放位置。

4)method是存放的那里的

方法的内容 也就是code,所有的method都在class类中,或者是类信息,所以存放在方法区内。

5)class类 & 内部类 是如何存放

一个普通的类 & 内部类本质上是一样的,所以就是1)问题中描述的情况。

对象引用句柄或指针,存放在每个线程的局部变量表内。

对象实例存放在java堆中,

对象类加载信息存放在方法区中。

6)一个类的成员属性,它的内存是那块?

类的成员属性,某种意义上和C++/C 里面的全局变量类似。但是JVM其实没有全局变量这样一个概念。

成员属性的对应的内存可以肯定是在堆中,可以肯定成员变量的基本信息是在类信息中的。所以成员属性

的相关内存都在java堆中。

参考:

《深入理解Java虚拟机》  周志明

深入理解java虚拟机(1)------内存区域与内存溢出的更多相关文章

  1. 深入理解Java虚拟机:垃圾收集器与内存分配策略

    目录 3.2 对象已死吗 判断一个对象是否可被回收 引用类型 finalize() 回收方法区 3.3. 垃圾收集算法 1.Mark-Sweep(标记-清除)算法 2.Copying(复制)算法 3. ...

  2. 《深入理解Java虚拟机》学习笔记之内存分配

    JVM在执行Java程序的过程中会把它所管理的内存划分若干个不同的数据区域,如下图: 大致可以分为两类:线程私有区域和线程共享区域. 线程私有区域 程序计数器(Program Counter Regi ...

  3. 《深入理解java虚拟机》读书笔记1--java内存区域

    Java内存管理 本文主要介绍Java虚拟机运行时的内存区域是如何划分的.Java对象的创建过程.Java对象的内存布局.Java对象的访问定位 一:运行时区域划分 主要可以分为以下 几个: 程序计数 ...

  4. 《深入理解Java虚拟机》学习笔记之内存回收

    垃圾收集(Garbage Collection,GC)并不是Java语言的半生产物,事实上GC历史远比Java久远,真正使用内存动态分配和垃圾收集技术的语言是诞生于1960年的Lisp语言.经过半个世 ...

  5. 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略

    目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...

  6. 深入理解Java虚拟机二:垃圾收集与内存分配

    垃圾收集:垃圾收集要完成三件事,包括哪些内存需要回收,什么时候回收及如何回收. 1.需要回收的内存判定:没有引用指向原先分配给某个对象的内存时,则该内存是需要回收的垃圾 Java垃圾收集器在对内存进行 ...

  7. 深入理解Java虚拟机之读书笔记三 内存分配策略

    一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配.对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分 ...

  8. 《深入理解Java虚拟机》——垃圾收集器与内存分配策略

    GC需要完成: 哪些内存需要回收 什么时候回收 如何回收 如何确定对象不再使用 引用计数算法 给对象添加一个引用计数器,当有一个地方引用它时,计数器值进行加1操作:当引用失效时,计数器值进行减1操作: ...

  9. 深入理解java虚拟机(3)垃圾收集器与内存分配策略

    一.根搜索算法: (1)定义:通过一系列名为"GC Roots"的对象作为起点,从这些起点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的时 ...

  10. Java内存区域与内存溢出异常——深入理解Java虚拟机 笔记一

    Java内存区域 对比与C和C++,Java程序员不需要时时刻刻在意对象的创建和删除过程造成的内存溢出.内存泄露等问题,Java虚拟机很好地帮助我们解决了内存管理的问题,但深入理解Java内存区域,有 ...

随机推荐

  1. Unity3D 敌人AI 和 动画( Animator )系统的实例讲解

    在这个实例中,我们要做一些敌人AI的简单实现,其中自动跟随和动画是重点,我们要达到的目标如下: 1.敌人能够自动跟随主角 2.敌人模型一共有四个动作:Idle(空闲) Run(奔跑) Attack(攻 ...

  2. Node.js 入门手册:那些最流行的 Web 开发框架

    这篇文章与大家分享最流行的 Node.js Web 开发框架.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编 ...

  3. python编码问题的最终分析

    python初学者,往往因为字符编码的问题而苦恼不已,本人也是阅读了大量的博客,再进行了一定的测试,基本搞清楚了编码问题的前因后果.下面一段代码是在python3.5上的,以它为例进行讲解(请忽略糟糕 ...

  4. 【Spark】---- 在Linux集群上安装和配置Spark

    1 安装JDK   1) 进入JDK官网 2) 下载JDK安装包 3)配置环境变量,在/etc/profile增加以下代码 JAVA_HOME=/home/hadoop/jdk1.6.0_38 PAT ...

  5. servlet、filter、listener、interceptor之间的区别和联系

    一.概念 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层. 2.filter: ...

  6. 【Win10】单元测试中捕获异步方法的指定异常

    温馨提醒:本文需要知道什么是单元测试才能阅读. 在之前 WPF.ASP.NET 中,单元测试要捕捉指定异常,我们是通过 ExpectedExceptionAttribute 来实现的.如下图: 但是, ...

  7. C#使用基类的引用 and 虚方法和覆写方法

    结论:使用基类的引用,访问派生类对象时,得到的是基类的成员. 虚方法和覆写方法

  8. 重构第31天 使用多态替代条件语句( Replace conditional with Polymorphism)

    理解:本文中的”使用多态代替条件判断”是指如果你需要检查对象的类型或者根据类型执行一些操作时,一种很好的办法就是将算法封装到类中,并利用多态性进行抽象调用. 详解:本文展示了面向对象编程的基础之一“多 ...

  9. 【C#】1.2 控制台应用程序学习要点

    分类:C#.VS2015 创建日期:2016-06-14 教材:十二五国家级规划教材<C#程序设计及应用教程>(第3版) 一.要点概述 <C#程序设计及应用教程>(第3版)的第 ...

  10. C#开发中可能会用到的一些小贴士(转)

    转至http://www.cnblogs.com/Ebony-Ivory/p/4380106.html C#篇: 1.目标平台的选择 64位操作系统在编译VS里的程序时,根据需要设置项目属性的“目标平 ...