Java内存区域与内存溢出异常---对象的创建

对象的创建

??在语言层面,创建一个对象通常仅仅是一个new关键字而已。在虚拟机层面,虚拟机遇到一个new指令时,首先回去检查这个指令的参数是能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载,解析和初始化过。如果没有那么必须先执行类加载操作。

??在类加载检查通过后,虚拟机将为对象从Java堆上划分出一块内存空间。有两种分配方式:

(1)指针碰撞

??假设Java堆中的内存时规整的,所有用过的内存放在一边,没有用过的内存放在一边,中间放着一个指针作为分界的指示器,那么分配内存仅仅就是将指针向着未使用内存那边挪动一段与对象大小相等的距离,这种分配方式称为指针碰撞。

(2)空闲列表

??Java中的内存空间不是规整的,已使用的内存和未使用的内存相互交错,虚拟机必须维护维护一张表,来记录那些内存块是可用的,在分配时从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。这种分配方式称为"空闲列表法"。

??选择哪种分配方式,只要看Java堆是否规整,而Java堆是否规整又是由垃圾回收算法所决定的,因此在使用Serial,ParNew,等收集器时,系统采用的分配方法是:指针碰撞。而在使用CMS这种基于Mask-Sweep算法的收集器时采用空闲列表法

??还有一个需要考虑的问题就是对象创建在Java堆中是非常频繁的行为,因此在并发的情况下分配内存可能不是线程安全的。解决该问题有两种方案:

??(1)对分配的内存空间动作进行同步处理,实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性。

??(2)把内存分配动作按照线程划分在不同的空间中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB),哪个线程要分配内存就在哪个线程的TLAB上进行分配。

??内存分配完成后,虚拟机将分配到的内存空间都初始化为零值(不包括对象头)。

??接下来虚拟机要对对象进行必要的设置,例如该对象是哪个类的实例,如何才能找到类的元数据信息对象的哈希码对象的GC分代年龄信息。这些信息存放在对象的对象头

???在上面的工作都完成后,从虚拟机的角度来看一个新的对象已经产生。

??但是从java程序角度看,对象的创建才开始-----方法还没有执行,所有的字段都还为0,所以一般来说执行new指令后会接着执行方法,把对象按照程序员的意愿进行初始化,这样一个真正的对象才创建。

原文地址:https://www.cnblogs.com/yjxyy/p/10686225.html

时间: 2024-10-23 01:18:24

Java内存区域与内存溢出异常---对象的创建的相关文章

深入理解java虚拟机系列(一):java内存区域与内存溢出异常

文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了开始.如果有什么错误或者遗漏,欢迎指出. 一.概述 先上一张图 这张图主要列出了Java虚拟机管理的内存的几个区域. 常有人把Java内存区分为堆内存(Heap)和栈内存(Stack),这种分法比较粗糙,Java内存区域的划分实际上远比这复杂,从上图就可以看出了.堆栈分法中所指的"栈"实际上只是虚拟机栈,或者说是虚拟机栈中的局部变量表部分.接下

深入了解Java虚拟机(1)java内存区域与内存溢出异常

java内存区域与内存溢出异常 一.运行时数据区域 1.程序计数器:线程私有,用于存储当前所执行的指令位置 2.Java虚拟机栈:线程私有,描叙Java方法执行模型:执行方法时都会创建一个栈帧,存储局部变量,基本类型变量,引用等信息 3.Java本地方法栈:线程私有,为虚拟机使用到的Native方法服务 4.Java堆:线程共享,是垃圾收集器的主要工作地方:存储对象实例等 5.方法区:线程共享:存储类信息,常量,静态变量等 运行时常量:存放编译时生成的各种字面量和符号引用 6.直接内存:机器的内

《深入理解Java虚拟机》读书笔记---第二章 Java内存区域与内存溢出异常

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来.这一章就是给大家介绍Java虚拟机内存的各个区域,讲解这些区域的作用,服务对象以及其中可能产生的问题. 1.运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 1.1程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型中里,字

Java内存区域与内存溢出异常-内存区域

Java内存区域与内存溢出异常 概述 对于 C 和 C++程序开发的开发人员来说,在内存管理领域,程序员对内存拥有绝对的使用权,但是也要主要到正确的使用和清理内存,这就要求程序员有较高的水平. 而对于 Java 程序员来说,在虚拟机的自动内存管理机制的帮助下,不再需要为每一个 new 操作去写配对的 delete/free 代码,而且不容易出现内存泄漏和内存溢出问题,看起来由虚拟机管理内存一切都很美好.不过,也正是因为 Java 程序员把内存控制的权力交给了 Java 虚拟机,一旦出现内存泄漏和

图解Java内存区域及内存溢出异常

图解 Java 内存区域及内存溢出异常 在阅读 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版) >后,为了加深对 Java 内存区域的印象及理解,特意做成了思维导图. 名词解释 线程共享数据区域 直接内存 并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区.NIO 中使用 Native 函数直接分配堆外内存 方法区 Method Area 用于存放已被虚拟机加载的类信息.常量.静态变量.JIT 编译后的代码等 也称作 永久代,在这块容易遇到 OOM 问题

JVM(一):Java内存区域与内存溢出异常

一.运行时数据区 共分为5块: 程序计数器      (线程私有,当前线程所执行的字节码的行号指示器) Java虚拟机栈  (线程私有,证明周期与线程相同,描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储:局部变量表.操作数栈.动态链接.方法出口等信息) 本地方法栈      (线程私有,本地方法栈类似于虚拟机栈,只不过执行的是Native方法) Java堆        (线程共享的一块内存区域,几乎所有的对象实例以及数组都要在堆上分配) 方法区       

2.1 自动内存管理机制--Java内存区域与内存溢出异常

自动内存管理机制 第二章.Java内存区域与内存溢出异常 [虚拟机中内存如何划分,以及哪部分区域.什么样代码和操作会导致内存溢出.各区域内存溢出的原因] 一.运行时数据区域 Java虚拟机所管理的内存包括以下几个运行时数据区域[虚拟机内存模型]: 1.程序计数器: 可以看作是当前线程所执行的字节码的行号指示器.在虚拟机中,字节码解释器工作时就是通过程序计数器的值来选择下一条需要执行的字节码指令.Java虚拟机中多线程是通过线程轮流切换并分配处理机执行时间的方式实现的,在任何一个确定的时刻,一个处

Java 内存区域与内存溢出异常

一.Java虚拟机内存划分 1.程序计数器 线程私有 可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时是通过改变这个计数器的值来选取下一条需要执行的字节码指令. Java虚拟机是通过多线程轮流切换并分配处理器执行时间的方式实现,为了切换线程后能正确的恢复到执行的位置,每一个线程都有一个独立的程序计数器. 2.Java虚拟机栈 线程私有,与线程的生命周期相同. 虚拟机栈描述的是Java方法执行的内存模型:每个方法创建的时候都要创建一个栈帧,用户存储局部变量表.操作数栈.动态链接.方

1 Java内存区域与内存溢出异常

1 java虚拟机对内存的管理 java虚拟机在执行java程序的时候把内存分为若干个不同的区,这些区各自有不同的用处,以及创建和销毁时间. 有的区随着虚拟机的启动而启动,有的区则依赖用户线程的启动和结束而启动和结束. 根据java虚拟机规范,java虚拟机将内存分为下面几个部分:如下图 下面是对这些区的介绍 1 程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器.字节码解释器就是通过改变该计数器的