* ###java虚拟机当中 内存划分 * <p> * 区域名称 作用 * 寄存器 给cpu使用, * 本地方法栈 JVM 调用操作系统时 使用的 * 方法区 存储可以运行的 class文件,(常量池,静态域) * 方法栈(stack) 方法运行时使用的 内存, 比如main方法运行, 会进入栈 * 堆 存储 * 程序执行流程: * 1.main方法进入方法栈中执行 * 2.创建数组,jvm会在堆内存中开辟空间,存储数组, * 3.数组在内存当中会有自己的内存地址,以 十六进制表示 * 4.数组当中有三个元素, 默认值为0; * 5.jvm将数组的内存地址 赋值给引用类型的变量arr * 6.变量arr保存的数组是在内存当中的地址,而不是一个具体的数值 * 两个数值的数组 的内存分析图解 * <p> * java的六种存储地址及解释 * 1).寄存器:位于 处理器内部,数量及其有限 , 由编译器进行分配 * 2).栈stack:位于RAM中,栈指针向下移动, 分配新内存,栈指针向上移动,释放内存 * 分配存储 方法 仅次于寄存器, 创建 程序的时候, java编译器编写知道栈中所有数据的确切大小和 * 生命周期 , 对象引用 在堆中,但java对象不存储其中 * 3).堆heap 一种通用的内存池, 用于存放所有的java 对象,堆不用于栈的好处是,编译器 * 不需要知道要从堆分配多少区域,也不知道存储的数据 在堆里存活多长时间, 因此, 在堆里分配存储有很大的灵活性, * 当 创建对象时, 会自动在堆里进行存储分配, 用堆 进行存储 比用栈 存储需要更多的时间 * 4).静态存储 : 这里 的静态 是指固定的位置,静态存储在存放程序运行时一直存在的数据, 使用 关键字static 来 * 标识 一个对象的特定元素是静态的, 但java 对象本身 从来不会存放咋静态存储空间了 * 5). 常量存储 常量值通常直接存放在程序代码内部,这样做是安全的,因为他们永远捕获被改变, 有时, 在嵌入式 * 系统中, 常量本身会和其他部分分割 开,所以在这种情况先, 可以选择将其 放在ROM中 * 需要注意的是,常量池中存储字符 数组只是存储 的是每个字符或字符串 * 为了 * <p> * 6).非 RAM存储,如果数据完全存活于程序之外,那么他不受程序的任何控制,在程序没有运行时也可以存在 * 二 . 堆,栈, 方法区 存储 的内容 * <p> * 堆区, * 1.存储的全部都是对象,每个对象都包含一个与之对应的class 的消息,(class的目的是得到操作指令) * 2.jvm只有一个堆区, 被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 * <p> * 栈区 * 1.每个线程都包含一个栈区,栈中只保存基本数据类型的值 和对象的引用 * 2.每个栈中的数据 (基础数据类型 和对象引用) 都是私有的,其他栈不能访问 * 3.栈分为3个部分, 基本类型变量区 ,执行环境上下文, 操作指令区(存放操作指令) * <p> * 方法区: * 1.又叫静态区,跟堆 一样,被所有的线程共享,方法区包含所有的class和static 变量 * 2.方法区中包含的都是整个程序中永远唯一的元素,如 class ,static 变量 * 3.方法区静态变量 ,一个线程访问时, 另外一个线程只能等待; * <p> * 三。在java 语言里堆和栈的区别 * 1.栈stack 和堆heap 都是java用来在Ram 中存放数据的地方, 和C++不同, java自动管理堆和栈 * 2.栈的优势, 存取速度 比堆 要快, 仅次于 位于cpu 的寄存器, 但缺点是,存在 栈中的数据大小与生命周期 * 必须是确定 的, 缺乏灵活性, 另外, 栈数据可以共享, 堆的优势是可以换动态分配内存大小,生存期也不必事先告诉编译器, * java的垃圾收集器或自动回收走 这些不在使用的数据,但缺点是, 由于要在运行时动态分配内存,存取速度较慢 * 3.java中的数据类型有两种 * 一种是基本数据类型(int,long ,short ,char ,boolean ,float ,double,byte)注意,没有String 类型 , * 这种类型的定义是通过 诸如 int a=3 的形式 定义的,称为自动变量, 自动变量存的是字面值,不是类的实例 * 既不是类的引用,这里没有 类 的存在, 如 int a=3 ; 这里 的a是一个指向int类型 的引用,指向3这个字面值 * 这些字面值 的数据 , 由于大小可知, 生命周期可知, (这些字面值固定定义在某个程序块里面, 程序块退出后, * 字面值就消失,) 由于 追求速度的原因,就存在栈中, * 另外 ,栈有一个很重要的特殊性 ,就是存在栈中的数据可以共享, 如: int a=3 ;int b=3; * 如果 a=4 了, b还是等于3. * 如果是两个类的对象的引用同时指向一个对象, 如果一个对象引用变量 修改了这个变量的内部状态, * 那么另一个对象引用变量也即可反应出这个变化 * <p> * 另一种是包装类数据 , 如Integer, String , Double 等将对应的基本数据类型包装起来的类, 这些类型数据 * 全部存放于堆中, java 用new()语句来显示地告诉编译器, 在运行时才根据 需要动态创建, 因此比较灵活,但缺点是 * 需要占用更多的空间 * 4. * <p> * 》 1. String str="abc";我们创建了String类的对象str, 对象可能没有被创建, 指向String 类的引用被创建了 * 至于这个引用到底指向了一个新的的对象, 要根据上下文判断, 除非 通过new()方法来显要的创建一个新的对象 * 我们创建了一个指向 String 类的对象的引用变量str,这个对象引用变量指向 了某个值为“abc”的String 类 * 2.使用String str=“abc”的方式,可以在一定程度上通过程序的运行速度, 因为jvm会自动根据堆中的数据的 * 实际情况来决定是否有必要创建对象, 而对于String str=new String("abc"),则一概在堆中创建对象 * 这个思想应该是享元模式的思想 * 3.当比较两个包装类 里面的数值是否相等时, 用equals()方法时 * 当比较两个包装类里面的地址值(指向同一个对象是, 用==) * 4.由于String 类的immutable性质, 当String 变量经常变换值是,应该考虑StringBuffer(synchronized修饰) 类, 以提高 * 程序效率, 如果java不能成功分配heap 的空间,就抛出OutOfMemoryError */
数组在jvm中的存储
最新推荐文章于 2024-05-03 17:41:21 发布