JVM内存管理之杂谈(借此也论一论obj=null)
作为一个程序猿,修炼的过程就犹如玄幻小说中的主角,不仅需要练习各种武技,内气的修炼的一样重要。虽然武技可以迅速的提升主角的实力,但是在内气太差的情况下,根本发挥不出武技的十之一二。
因此,在介绍过设计模式这一类外功之后,LZ就直接转战内气修炼,和各位猿友探讨一下JVM的内容。
本来这一章应该是介绍与GC相关的内容,不过在此之前,LZ准备先和各位探讨一下一个编程的小技巧。当然,这个小技巧其实也是与GC密切相关的。
不知道各位猿友有没看过一些JAVA内存相关的文章,里面在罗列建议的时候,经常会写出这样一条建议。
第XX条、请在使用完对象之后,显示的将对象设置为null。
原话不一定如此,但意思是一样的。话里所描述的意思,就是说我们以后写代码应该这么写。
Object obj = new Object();
//to do something
obj = null;
这段代码有点C/C++的风格,obj=null代替了C/C++中的delete obj或者是free(obj),相当于在提示我们,就算有了GC,我们也要像没有GC一样,使用完对象就得将其赋为空值。
首先,LZ这里要说明的是,将obj赋为空值,与C/C++中的delete其实有着天壤之别,LZ之所以说它们代替了delete和free,仅仅是因为它们出现在代码中的位置类似而已。
obj=null只做了一件事,就是将obj这个引用变量与new Object()创造的实例的关联断开,实际上,实例所占用的内存空间依然没有释放。
在提出这个建议的时候,很多博主或者图书的作者(因为有不少博主估计也是从书上看的)的本意,是想尽快消除引用与实例的关联,从而诱发GC在进行垃圾回收时,将实例所占用的内存释放。在某些时候,这么做也是为了消除内存泄露。
LZ个人觉得,许多博主或者是图书作者,提出这个建议的初衷,主要是针对一些没有接触过GC原理以及内存管理的程序猿而建议的,因为在不明白相关知识的前提下,很容易掌握不好变量的作用域,从而导致不必要的内存浪费(个人觉得这个并不是主要目的,因为只要没有发生内存泄露,内存终究是要被GC释放的),甚至是内存泄露。
所以为了安全起见,有些高人们就提出了这么一个建议。
有鉴于此,LZ个人觉得,在各位掌握了相关知识之后,完全可以忽略这个建议,而且这么做明显会降低代码的清晰度以及增加编码的负担,然而所换来的好处,却只是为了避免那根本不一定存在的内存泄露。
这里解释一下为何在有些时候不将对象赋为空值会造成内存泄露,我们考虑下面一段代码。
import java.util.Arrays; public class Stack { private static final int INIT_SIZE = 10; private Object[] datas; private int size; public Stack() {
super();
datas = new Object[INIT_SIZE];
} public void push(Object data){
if (size == datas.length) {
extend();
}
datas[size++] = data;
} public Object pop(){
if (size == 0) {
throw new IndexOutOfBoundsException("size is zero");
}
return datas[--size];
} private void extend(){
datas = Arrays.copyOf(datas, 2 * size + 1);
} }
这段代码是一个简单的长度可伸缩的栈实现,在你写一段测试代码去测试它的时候,会发现它毫无问题。但是不好意思,这里面就有一个明显的“内存泄露”,这就是因为一些对象或者说引用没有设置为空值所造成的。
如果你还没看出来,LZ稍微提示一下,各位就会意识到了。这段代码里面,数组里的对象只会无限增长,而不会随着栈中元素的弹出而减少,减小的仅仅是对外展示的栈的大小size。考虑一个极端的场景,假设你曾经往栈中放入了100万个对象,最后使用了99万9千9百9十9个,从外部看来,栈中还只剩一个可用对象了,但是我们的栈依然持有着100万个对象的引用。如果JVM可以活过来的话,想必一定会把你蹂躏到死的。
我们缺少的就是将对象赋为null值的那一步,所以pop方法应该改为下面的方式,而且各位可以去看一下ArrayList中remove方法的源码,也是类似的思路。
public Object pop(){
if (size == 0) {
throw new IndexOutOfBoundsException("size is zero");
}
Object data = datas[--size];
datas[size] = null;
return data;
}
这个内存泄露是非常隐蔽的,而且实际使用当中不一定就能发现,因为随着Stack对象的回收,整个数组也会被回收,到时内存泄露就被掩盖了。
所以个人觉得上述的那个建议是完全没有必要的,就算遵从了上面的建议,如果对内存管理不熟悉的话,也不会想到上面这个代码中的问题。如果想彻底的避免内存泄露的发生,机械式的主动将对象赋为空值,并不是一个可以从根本上解决问题的办法。
真正能够解决问题的办法,就是掌握好GC的策略与原理,定义一个变量时多注意变量的作用域,如此才可以更好的避免内存泄露。
所以学好GC原理还是很有必要的,希望准备走JAVA之路的朋友,尤其是从培训机构出来的猿友们(此处没有鄙视培训机构出来的猿友们的意思,因为LZ本人也是半路出家,从培训机构走上编程之路的程序猿之一),一定不要只专注于各个框架的使用以及业务的深入,虽然这些事很有必要,但并不是全部。
follow me and go the memory world 吧(语法都是浮云)。
http://www.cnblogs.com/zuoxiaolong
JVM内存管理之杂谈(借此也论一论obj=null)的更多相关文章
- JVM内存管理------垃圾搜集器参数精解
本文是GC相关的最后一篇,这次LZ只是罗列一下hotspot JVM中垃圾搜集器相关的重点参数,以及各个参数的解释.废话不多说,这就开始. 垃圾搜集器文章传送门 JVM内存管理------JAVA语言 ...
- JVM内存管理之垃圾搜集器参数精解
本文是GC相关的最后一篇,这次LZ只是罗列一下hotspot JVM中垃圾搜集器相关的重点参数,以及各个参数的解释.废话不多说,这就开始. 垃圾搜集器文章传送门 JVM内存管理------JAVA语言 ...
- Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收
很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...
- JVM内存管理及垃圾回收
一.JVM内存的构 Java虚拟机会将内存分为几个不同的管理区,这些区域各自有各自的用途,根据不同的特点,承担不同的任务以及在垃圾回收时运用不同的算法.总体分为下面几个部分: 程序计数器(Progra ...
- JVM内存管理及垃圾回收【转】
很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...
- JVM内存管理(二)
JVM内存管理 JVM在执行java程序的过程中,会把内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖 ...
- 现代JVM内存管理方法的发展历程,GC的实现及相关设计概述(转)
JVM区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...
- java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...
- java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)
概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...
随机推荐
- Java内存状况查看方法和分析工具
Java本身提供了多种丰富的方法和工具来帮助开发人员查看和分析GC及其JVM内存的状况,同时开源界也有一些工具用于查看和分析GC和JVM内存的状况. 通过这些分析,可以排查程序中内存泄露的问题及调优程 ...
- watch和computed的用法区别是什么?
在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作.模板是为了描述视图的结构.在模板中放入太多的逻辑会让模板过重且难以维护.这就是为什么 Vue.js 将绑定表达式限制为一个表达式.如果需 ...
- java程序设计基础篇 复习笔记 第二单元
1原始数据类型(primitive data type) == 基本类型 (fundamental type)byte short int long float double char boolean ...
- js获取来源网址
举例: 1. a.html文件内容如下: <a href="b.html">浏览b.html </a> 2. b.html文件中的内容如下: <bod ...
- TeamView
1.TeamView TeamViewer是一个能在任何防火墙和NAT代理的后台用于远程控制,桌面共享和文件传输的简单且快速的解决方案.为了连接到另一台计算机,只需要在两台计算机上同时运行 TeamV ...
- 从头搭建一个React应用
node,webpack这些就不一一介绍怎么安装了,默认大家都知道. 一.npm install -g create-react-app 首先全局安装react的脚手架工具 create-react- ...
- NamedParameterJdbcTemplate常用方法总结
数据库结构 1.插入/修改/删除数据,使用update方法 插入数据1 API: int update(String sql, Map< String, ? > paramMap) 示例: ...
- 【机器学习PAI实践十】深度学习Caffe框架实现图像分类的模型训练
背景 我们在之前的文章中介绍过如何通过PAI内置的TensorFlow框架实验基于Cifar10的图像分类,文章链接:https://yq.aliyun.com/articles/72841.使用Te ...
- tensorflow windows
conda create -n py35 python=3.5 activate py35 pip install --ignore-installed --upgrade https://stora ...
- linux给一个文件夹开启权限
假如要给一个叫做xiaobang的文件夹权限,CD到这一级目录 chmod -R 777 xiaobang