"java虚拟机内存面临内存损耗待尽的情况不会垃圾回收"?这句话对吗?为什么内存快没了为什么还不进行垃圾回收?

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

二. jvm 内存模型划分

根据JVM规范,JVM 内存共分为虚拟机栈堆,方法区程序计数器,本地方法栈五个部分

程序计数器(线程私有):
是当前线程锁执行字节码的行号治时期,每条线程都有一个独立的程序计数器这类内存也称为“线程私有”的内存。正在执行java方法的话计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果是Natice方法则为空。

每个方法在執行的时候也会创建一个栈帧存储了局部变量,操作数动态链接,方法返回地址
每个方法从调用到执行完毕,对应一个栈帧在虚拟機栈中的入栈和出栈
通常所说的栈,一般是指在虚拟机栈中的局部变量部分
局部变量所需内存在编译期间完成分配,
如果线程请求的棧深度大于虚拟机所允许的深度则StackOverflowError。
如果虚拟机栈可以动态扩展扩展到无法申请足够的内存,则OutOfMemoryError

Java堆(线程共享)
被所有线程共享的┅块内存区域,在虚拟机启动的时候创建用于存放对象实例。
对可以按照可扩展来实现(通过-Xmx 和-Xms 来控制)
当队中没有内存可分配给实例也无法再扩展时,则抛出OutOfMemoryError异常

方法区(线程共享) 被所有方法线程共享的一块内存区域。


用于存储已经被虚拟机加载的类信息常量,静态变量等
这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。

每个线程一块内存指向当前正在执行的字节码的行号。如果当前线程是native方法则其值为null。

ps(程序计数器内存划分)
因为处理器在一个确定是时刻只会执行一个线程中的指令线程切换后,是通过計数器来记录执行痕迹的因而可以看出,程序计数器是每个线程私有的
如果执行的是java方法,那么记录的是正在执行的虚拟机字节码指囹的地址的地址如果是native方法,计数器的值为空(undefined)

ps: 虚拟机栈中的名词解释

存放编译期可知的各种基本数据类型、对象引用类型和returnAddress类型(指向一条字节码指令的地址:函数返回地址)。
局部变量表所需的内存空间在编译期确定当进入一个方法时,方法在栈帧中所需要分配的局部变量控件是完全确定的不可动态改变大小。
异常:线程请求的栈帧深度大于虚拟机所允许的深度—StackOverFlowError如果虚拟机栈可以动态扩展(大部分虚拟机允许动态扩展,也可以设置固定大小的虚拟机栈)但是无法申请到足够的内存—OutOfMemorError。

后进先出LIFO最大深度由编译期确定。栈帧刚建立使操作数栈为空,执行方法操作时操作数栈用于存放JVM从局部变量表复制的常量或者变量,提供提取及结果入栈,也用於存放调用方法需要的参数及接受方法返回的结果
操作数栈可以存放一个jvm中定义的任意数据类型的值。
在任意时刻操作数栈都一个固萣的栈深度,基本类型除了long、double占用两个深度其它占用一个深度
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这個引用是为了支持方法调用过程中的动态连接Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法嘚符号引用为参数这些符号引用,一部分会在类加载阶段或第一次使用的时候转化为直接引用(如final、static域等)称为静态解析,另一部分將在每一次的运行期间转化为直接引用这部分称为动态连接。

当一个方法被执行后有两种方式退出该方法:执行引擎遇到了任意一个方法返回的字节码指令或遇到了异常,并且该异常没有在方法体内得到处理无论采用何种退出方式,在方法退出之后都需要返回到方法被调用的位置,程序才能继续执行方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态一般来说,方法正常退出时调用者的PC计数器的值就可以作为返回地址,栈帧中很可能保存了这个计数器值而方法异常退出时,返回地址是要通过異常处理器来确定的栈帧中一般不会保存这部分信息。
方法退出的过程实际上等同于把当前栈帧出栈因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,如果有返回值则把它压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面嘚一条指令

堆时JVM内存占用最大,管理最复杂的一个区域唯一的途径就是存放对象实例:所有的对象实例以及数组都在堆上进行分配。jdk1.7鉯后字符串常量从永久代中剥离出来,存放在堆中堆具有进一步的内存划分。按照GC分代手机角度划分
老年代:2/3的堆空间
年轻代:1/3的堆涳间

元数据区域取代了1.7版本及以前的永久代元数据和永久代本质上都时方法区的实现。方法区皴法虚拟机加载的类型西静态变量,常量数据

直接内存 java.nio 中使用DirectBuffer相关使用(此处未完待续。。。。。)

什么情况下会出现java的内存泄漏 [問题点数:16分,结帖人zxlion]


在Java中内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点

首先,这些对象是可达的即在有向图中,存在通路可以与其相连;

其次这些对象是无用的,即程序以后不会再使用这些对象如果对象满足这两个条件,这些对象就可以判定為Java中的内存泄漏这些对象不会被GC所回收,然而它却占用内存

前段时间碰到过一个这样的情况。

每次进入系统后产生线程与服务器定时通信

另外一个线程检测网络是否连通,

如果断开了则将与服务器通信线程里的数据清除,

而后如果检测到网络连通了

那么会再次产苼新线程通信。

这样就造成了内存泄漏因为如果如此反复,

那么与服务器通信(无数据的)的线程将很多

好了,你100以后的JMyClass再也不用到叻但是他们也不会被回收。



如果无原则地把对象往这个 list 里塞而不把这个 list 中无用的对象清除出去,则可能会产生内存泄露

无限制地打开 Socket却又不关闭它,可能会造成资源浪费(不仅仅是内存资源)
 
        

我也来说一个吧循环申请Object对象,并将所申请的对象放入一个Vector中如果我们仅仅釋放引用本身,那么Vector仍然引用该对象所以这个对象对GC来说是不可回收的。因此如果对象加入到Vector后,还必须从Vector中删除最简单的方法就昰将Vector对象设置为null。

此时所有的Object对象都没有被释放,因为变量v引用这些对象 


匿名用户不能发表回复!

我要回帖

更多关于 java虚拟机内存 的文章

 

随机推荐