论 Java 中的内存分配

-------------------------------------------------------------------------

Java内存分配主要包括以下几个区域:

1. 寄存器:我们在程序中无法控制

2. :存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中

3. :存放用new产生的数据

4. 静态域:存放在对象中用static定义的静态成员

5. 常量池:存放常量

6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间

 ------------------------------------------------------------------------------------

一. 寄存器(Registers):

     这是速度最快的存储场所,因为寄存器位于处理器内部,这一点和其他的存储媒介都不一样。不过寄存器个数是有限的。

    在内存中的寄存器区域是由编译器根据需要来分配的。我们程序开发人员不能够通过代码来控制这个寄存器的分配。

    所以说,这第一个存储区域寄存器,我们只能够看看,而不能够对其产生任何的影响。,也没办法在程序里头感觉到寄存器的任何存在迹象。

    JVM只设置了4个最为常用的寄存器。   pc程序计数器   optop操作数栈顶指针   frame当前执行环境指针   vars指向当前执行环境中第一个局部变量的指针   所有寄存器均为32位。   pc用于记录程序的执行。optop,frame和vars用于记录指向Java栈区的指针。

二. 栈(Stack):

 又称堆栈

   位于一般的RAM中。处理器经由指针提供直接支持。

   当程序配置一块新的内存时,stack指针便往后移;释放内存时,指针则往前移。

   这种方式不仅很快,效率也高,速度仅次于寄存器。

   用于存放对象引用以及基本的数据类型对象,不能用于存储Java对象本身。

三. 堆(Heap):    一种通用的内存空间,用来存放Java对象。

   Heap不同于stack之处在于,编译器不需知道究竟得从heap中配置多少空间,也不需知道从heap上配置的空间究竟需要存在多久。

   因此,自heap配置存储空间可以获得高度的弹性。每当你需要产生对象,只需在程序中使用new,那么执行的时候,便会自heap配置空间。

   当然,你得为这样的弹性付出代价:从heap配置空间,比从stack配置,所耗费的时间多了不少。

单论内存空间中的堆和栈:

   1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。Java自动管理栈和堆,程序员不能直接地设置栈或堆。

   2.优缺点:

      栈:

  栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器

  但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据在多个线程或者多个栈之间是不可以共享的,但是在栈内部多个值相等的变量是可以指向一个地址的

 堆:

  堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。

  但缺点是,由于要在运行时动态分配内存,存取速度较慢。

3.栈有一个很重要的特殊性,就是存在栈中的数据可以共享

四. 静态域:

    静态存储区域就是指在固定的位置存放应用程序运行时一直存在的数据,Java在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量,需要明确的一点就是,Java对象是不保存在这个地方的,而只是把对象中的一些特殊元素放置这。

    类变量也叫静态变量,也就是在变量前加了static 的变量; 实例变量也叫对象变量,即没加static 的变量; 区别在于:      类变量和实例变量的区别在于:类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象;

  特点:

这儿的“静态”(Static)是指“位于固定位置”(尽管也在RAM里)。程序运行期间,静态存储的数据将随时等候调用。可用static关键字指出一个对象的特定元素是静态的。但Java对象本身永远都不会置入静态存储空间例:

public class A{
    static int a = 0; //类变量
    private int b = 0; //实例变量
}

public class B{
    public void main (String[] args){
        A a1 = new A();
        A a2 = new A();
        a1.a = 3; // 等同于 A.a = 3;
        a1.b = 4 ;
        System.out.println(a2.a); //结果为3
        //类变量是针对所有对象的,所以a1改变a,a2的a也改变
        System.out.println(a2.b); //结果为0
        //实例只改变自身的,所以a1对象的b改变,不影响对象a2的b变量
    }
} 

五. 常量池:

  常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。

背景:

    在Java对象中还有一类特殊的元素,我们叫做常量。由于常量的值是稳定不变的,如圆周率。为此把他们放在代码的内部是可行的。

    不过有些时候,在进行一些嵌入式系统开发的时候,我们往往不这么做。而是会把常量元素跟代码分开来保存。

    如我们会根据情况把常量的值存放在一些只读存储器中。这主要是为了一些特殊的功能考虑的。

    如出于版权控制的需要。如在打印机上为了保护原装耗材的版权,往往把常量跟代码分开存放

特点:

    在Java程序中,有很多的东西是永恒的,不会在运行过程中变化。

          比如一个类的名字,一个类字段的名字/所属类型,一个类方法的名字/返回类型/参数名与所属类型,一个常量,还有在程序中出现的大量的字面值。

   常数值通常直接置于程序代码内部。这样做是安全的,因为它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。

六.  非RAM存储:

  若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于固定对象,对象保存在磁盘中。

  即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复成普通的、基于RAM的对象

   背景:

有时候,有些程序运行所需要的数据我们还会放置在其他地方。如在一些系统中需要用到流对象,这个对象的数据并没有保存在上面所谈到的任何一个存储区域,这个对象直接被转为为字节流,发送到其他的主机上去了。另外有一种叫做持久化的对象,其是被存储在硬盘中的

七. 论各类型内存的执行速度:

  寄存器 > 堆栈 > 堆 > 其他

(C) 房上的猫 。 保留所有权利。  https://www.cnblogs.com/lsy131479/

如需转载,请注明出处!!!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

C++容器与算法

容器:某一类型数据的集合。 C++标准顺序容器包括:vector,list,queue 容器初始化 vector<int> t; ...

18810
来自专栏xiaoxi666的专栏

状态机编程思想(2):删除代码注释(目前支持C/C++和Java)

之前考虑过正则表达式,但是感觉实现起来相当麻烦。而状态机可以把多种情况归为一类状态再行分解,大大简化问题。本文就是基于状态机实现的。

942
来自专栏Java技术栈

跟我学 Java 8 新特性之 Stream 流(二)关键知识点

我们的第一篇文章,主要是通过一个Demo,让大家体验了一下使用流API的那种酣畅淋漓的感觉。如果你没有实践,我还是再次呼吁你动手敲一敲,自己实实在跑一遍上一篇的...

1274
来自专栏逆向与安全

菜鸟 学注册机编写之 “MD5”

sc_office_2003_pro 高手不要见笑,仅供小菜玩乐,有不对或不足的地方还请多多指教,不胜感激!   

800
来自专栏刘望舒

JNI的实现原理

JNI是Java Native Interface的缩写,它为java提供了调用C和C++代码的能力。java.lang包下的很多类都用到了native方法,比...

2312
来自专栏CSDN技术头条

【问底】静行:FastJSON实现详解

还记得电影《功夫》中火云邪神的一句话:天下功夫,无坚不破,唯快不破。在程序员的世界中,“快”一直是大家苦苦修炼,竞相追逐的终极目标之一,甚至到了“不择手段”、“...

2467
来自专栏C语言及其他语言

[每日一题]C语言程序设计教程(第三版)课后习题4.9

题目描述 输入一个华氏温度,要求输出摄氏温度。公式为 c=5(F-32)/9 输出要求有文字说明,取位2小数。 输入 一个华氏温度,浮点数 输出 摄氏温度,浮点...

2816
来自专栏糊一笑

几个关于js数组方法reduce的经典片段

以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘。 jav...

4109
来自专栏偏前端工程师的驿站

(cljs/run-at (JSVM. :all) "一次说白DataType、Record和Protocol")

前言  在项目中我们一般会为实际问题域定义领域数据模型,譬如开发VDOM时自然而言就会定义个VNode数据类型,用于打包存储、操作相关数据。clj/cljs不单...

1868
来自专栏蛋未明的专栏

php实现twTrCn-简繁转化

1654

扫码关注云+社区