java 什么时候开辟堆内存 java中实例变量在什么时候被分配内存空间
大家好,今天来为大家分享java 什么时候开辟堆内存的一些知识点,和java中实例变量在什么时候被分配内存空间的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
Java堆内存的10个要点
当我开始学习Java编程时我不知道什么是堆内存或堆空间我甚至不知道当对象创建时它们被放在了哪里当我开始正式写一些程序后我会经常遇到java lang outOfMemoryError的报错之后我才开始关注什么是堆内存或者说堆空间(heap space)对大多数程序员都经历过这样的过程因为学习一种语言是非常容易来的但是学习基础是非常难的因为没有什么特定的流程让你学习编程的每个基础使你发觉编程的秘诀
对于程序员来说知道堆空间设置堆空间处理堆空间的outOfMemoryError错误分析heap dump是非常重要的这个关于Java堆的教程是给我刚开始学编程的兄弟看的如果你知道这个基础知识或者知道底层发生了什么当然可能帮助不是那么大除非你知道了对象被创建在堆中否则你不会意识到OutOfMemoryError是发生在堆空间中的我尽可能的将我所知道的所有关于堆的知识都写下来了也希望你们能够尽可能多的贡献和分享你的知识以便可以让其他人也受益
Java中的堆空间是什么?
当Java程序开始运行时 JVM会从操作系统获取一些内存 JVM使用这些内存这些内存的一部分就是堆内存堆内存通常在存储地址的底层向上排列当一个对象通过new关键字或通过其他方式创建后对象从堆中获得内存当对象不再使用了被当做垃圾回收掉后这些内存又重新回到堆内存中要学习垃圾回收请阅读 Java中垃圾回收的工作原理
如何增加Java堆空间
在大多数位机 Sun的JVM上 Java的堆空间默认的大小为 MB但也有例外例如在未Solaris操作系统(SPARC平台版本)上默认的最大堆空间和起始堆空间大小为 Xms= K和 Xmx= M对于位操作系统一般堆空间大小增加约%但你使用Java的throughput垃圾回收器默认最大的堆大小为物理内存的四分之一而起始堆大小为物理内存的十六分之一要想知道默认的堆大小的方法可以用默认的设置参数打开一个程序使用JConsole(JDK之后都支持)来查看在VM Summary页面可以看到最大的堆大小
用这种方法你可以根据你的程序的需要来改变堆内存大小我强烈建议采用这种方法而不是默认值如果你的程序很大有很多对象需要被创建的话你可以用 Xms and Xmx这两个参数来改变堆内存的大小 Xms表示起始的堆内存大小 Xmx表示最大的堆内存的大小另外有一个参数 Xmn它表示new generation(后面会提到)的大小有一件事你需要注意你不能任意改变堆内存的大小你只能在启动JVM时设定它
堆和垃圾回收
我们知道对象创建在堆内存中垃圾回收这样一个进程它将已死对象清除出堆空间并将这些内存再还给堆为了给垃圾回收器使用堆主要分成三个区域分别叫作New Generation Old Generation或叫Tenured Generation以及Perm space New Generation是用来存放新建的对象的空间在对象新建的时候被使用如果长时间还使用的话它们会被垃圾回收器移动到Old Generation(或叫Tenured Generation) Perm space是JVM存放Meta数据的地方例如类方法字符串池和类级别的详细信息你可以查看 Java中垃圾回收的工作原理来获得更多关于堆和垃圾回收的信息
Java堆中的OutOfMemoryError错误
当JVM启动时使用了 Xms参数设置的对内存当程序继续进行创建更多对象 JVM开始扩大堆内存以容纳更多对象 JVM也会使用垃圾回收器来回收内存当快达到 Xmx设置的最大堆内存时如果没有更多的内存可被分配给新对象的话 JVM就会抛出java lang outofmemoryerror你的程序就会当掉在抛出 OutOfMemoryError之前 JVM会尝试着用垃圾回收器来释放足够的空间但是发现仍旧没有足够的空间时就会抛出这个错误为了解决这个问题你需要清楚你的程序对象的信息例如你创建了哪些对象哪些对象占用了多少空间等等你可以使用profiler或者堆分析器来处理 OutOfMemoryError错误 java lang OutOfMemoryError Java heap space表示堆没有足够的空间了不能继续扩大了 java lang OutOfMemoryError PermGen space表示permanent generation已经装满了你的程序不能再装在类或者再分配一个字符串了
Java Heap dump
Heap dump是在某一时间对Java堆内存的快照它对于分析堆内存或处理内存泄露和Java lang outofmemoryerror错误是非常有用的在JDK中有一些工具可以帮你获取heap dump也有一些堆分析工具来帮你分析heap dump你可以用 jmap来获取heap dump它帮你创建heap dump文件然后你可以用 jhat(堆分析工具)来分析这些heap dump
Java堆内存(heap memory)的十个要点
Java堆内存是操作系统分配给JVM的内存的一部分
当我们创建对象时它们存储在Java堆内存中
为了便于垃圾回收 Java堆空间分成三个区域分别叫作New Generation Old Generation或叫作Tenured Generation还有Perm Space
你可以通过用JVM的命令行选项 Xms Xmx Xmn来调整Java堆空间的大小不要忘了在大小后面加上 M或者 G来表示单位举个例子你可以用 Xmx m来设置堆内存最大的大小为 MB
你可以用JConsole或者 Runtime maxMemory() Runtime totalMemory() Runtime freeMemory()来查看Java中堆内存的大小
你可以使用命令 jmap来获得heap dump用 jhat来分析heap dump
Java堆空间不同于栈空间栈空间是用来储存调用栈和局部变量的
Java垃圾回收器是用来将死掉的对象(不再使用的对象)所占用的内存回收回来再释放到Java堆空间中
当你遇到java lang outOfMemoryError时不要紧张有时候仅仅增加堆空间就可以了但如果经常出现的话就要看看Java程序中是不是存在内存泄露了
lishixinzhi/Article/program/Java/hx/201311/26778java中实例变量在什么时候被分配内存空间
实例变量在内存中分配:
当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的"物理位置"。实例变量的生命周期--当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存
java 为什么 设置堆内存 而不需要设栈内存
本文简明概要地说明了java程序的占用内存构成
对象(Objects)
类(Classes)
线程(Theads)
本地数据结构(Native data structures)
本地代码(Native code)
每个因素对内存占用的影响又会随着应用程序、运行环境和系统的不同而变化,那怎样计算总的内存占用量?是的,想得到一个准确的数字不是那么容易,因为你很难控制本地(Native)部分。你能控制的部分只有堆大小:-Xmx,类占用的内存:-XX:MaxPermSize,还有线程栈:-Xss控制每个线程占用的内存。注意当把栈大小设置的太小时会导StackOverflow异常、程序出错。所以,计算公式为:
(-Xmx)+(-XX:MaxPermSize)+线程数*(-Xss)+其它内存
其它内存部分取决于本地代码占用的内存,如NIO、Socket缓冲区、JNI等。它一般大约是JVM内存的5%左右。所以假设我们有下面的JVM参数和100个线程:
-Xmx1024m-XX:MaxPermSize=256m-Xss512k
那么JVM进程至少会占用内存数量为:1024m+256m+100*512k+(0.05*1330m)=1396.5m
我一般使用(1.5*堆最大值)来作为一个近似值表示一个Tomcat进程会需要的最小内存,如果你有需要增加MaxPermSize到256M以上的应用这个值可以更大些。
谁能解释一下java中的栈内存和堆内存
2.1内存分配策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.
2.2堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:
从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:
在编程中,例如C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快,当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.
堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中,要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点(晕~).
2.3 JVM中的堆和栈
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译原理中的活动纪录的概念是差不多的.
从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
文章到此结束,如果本次分享的java 什么时候开辟堆内存和java中实例变量在什么时候被分配内存空间的问题解决了您的问题,那么我们由衷的感到高兴!