当你从c&c++转到一门具有垃圾回收功能的语言时,程序员的工作就会变得更加容易,因为你用完对象,他们会被自动回收,但是,java程序员真的不需要考虑内存泄露吗? 其实不然

1.举个例子-看你能否找出内存泄漏

import java.util.Arrays;

public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
} public void push(Object e) {
ensureCapacity();
elements[size++] = e;
} public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
} private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}

1.1原因分析

上述程序并没有明显的错误,但是这段程序有一个内存泄漏,随着GC活动的增加,或者内存占用的不断增加,程序性能的降低就会表现出来,严重时可导致内存泄漏,但是这种失败情况相对较少。

代码的主要问题在pop函数,下面通过这张图示展现

假设这个栈一直增长,增长后如下图所示



当进行大量的pop操作时,由于引用未进行置空,gc是不会释放的,如下图所示

从上图中看以看出,如果栈先增长,在收缩,那么从栈中弹出的对象将不会被当作垃圾回收,即使程序不再使用栈中的这些队象,他们也不会回收,因为栈中仍然保存这对象的引用,俗称过期引用,这个内存泄露很隐蔽。

1.2解决方法

public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null;
return result;
}

一旦引用过期,清空这些引用,将引用置空。

2.缓存泄漏

内存泄漏的另一个常见来源是缓存,一旦你把对象引用放入到缓存中,他就很容易遗忘,对于这个问题,可以使用WeakHashMap代表缓存,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值

2.1代码示例

/**
* Created by liuroy on 2017/2/25.
*/
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit; public class Test {
static Map wMap = new WeakHashMap();
static Map map = new HashMap();
public static void init(){
String ref1= new String("obejct1");
String ref2 = new String("obejct2");
String ref3 = new String ("obejct3");
String ref4 = new String ("obejct4");
wMap.put(ref1, "chaheObject1");
wMap.put(ref2, "chaheObject2");
map.put(ref3, "chaheObject3");
map.put(ref4, "chaheObject4");
System.out.println("String引用ref1,ref2,ref3,ref4 消失"); }
public static void testWeakHashMap(){ System.out.println("WeakHashMap GC之前");
for (Object o : wMap.entrySet()) {
System.out.println(o);
}
try {
System.gc();
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("WeakHashMap GC之后");
for (Object o : wMap.entrySet()) {
System.out.println(o);
}
}
public static void testHashMap(){
System.out.println("HashMap GC之前");
for (Object o : map.entrySet()) {
System.out.println(o);
}
try {
System.gc();
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("HashMap GC之后");
for (Object o : map.entrySet()) {
System.out.println(o);
}
}
public static void main(String[] args) {
init();
testWeakHashMap();
testHashMap();
}
}
/** 结果
String引用ref1,ref2,ref3,ref4 消失
WeakHashMap GC之前
obejct2=chaheObject2
obejct1=chaheObject1
WeakHashMap GC之后
HashMap GC之前
obejct4=chaheObject4
obejct3=chaheObject3
Disconnected from the target VM, address: '127.0.0.1:51628', transport: 'socket'
HashMap GC之后
obejct4=chaheObject4
obejct3=chaheObject3
**/



上面代码和图示主演演示WeakHashMap如何自动释放缓存对象,当init函数执行完成后,局部变量字符串引用weakd1,weakd2,d1,d2都会消失,此时只有静态map中保存中对字符串对象的引用,可以看到,调用gc之后,hashmap的没有被回收,而WeakHashmap里面的缓存被回收了。

监听器和回调

内存泄漏第三个常见来源是监听器和其他回调,如果客户端在你实现的API中注册回调,却没有显示的取消,那么就会积聚。需要确保回调立即被当作垃圾回收的最佳方法是只保存他的若引用,例如将他们保存成为WeakHashMap中的键。

java程序员--小心你代码中的内存泄漏的更多相关文章

  1. Java程序员如何在竞争中保持优势

    Java程序员入门容易,进阶很难,想要在竞争中保持优势,脚踏实地的同时也要仰望星空规划自己的未来.时间在流逝,年龄在增加,你期望的薪水也在不断增多,你总得让自己能力持续增加以配得上想要的收入吧. 从初 ...

  2. java程序员图文并茂细说Unity中调用Android的接口

    http://bbs.csdn.net/topics/391876421 最近做一个项目,为同事提供接口,能使他在Unity中调用Android中的函数来实现QQ登陆并获取用户信息.按照一些书上和一些 ...

  3. 2017年 Java 程序员,风光背后的危机

    不得不承认,经历过行业的飞速发展期,互联网的整体发展趋于平稳.为什么这么说?为什么要放在 Java 程序员的盘点下说? 的确,对于进可攻前端,后可守后端大本营的 Java 程序员而言,虽然供应逐年上涨 ...

  4. 【Python】Java程序员学习Python(二)— 开发环境搭建

    巧妇难为无米之炊,我最爱的还是鸡蛋羹,因为我和鸡蛋羹有段不能说的秘密. 不管学啥,都要有环境,对于程序员来说搭建个开发环境应该不是什么难题.按顺序一步步来就可以,我也只是记录我的安装过程,你也可以滴. ...

  5. Android java程序员必备技能,集合与数组中遍历元素,增强for循环的使用详解及代码

    Android java程序员必备技能,集合与数组中遍历元素, 增强for循环的使用详解及代码 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 For ...

  6. Java中基本数据类型的存储方式和相关内存的处理方式(java程序员必读经典)

    1.java是如何管理内存的 java的内存管理就是对象的分配和释放问题.(其中包括两部分) 分配:内存的分配是由程序完成的,程序员需要通过关键字new为每个对象申请内存空间(基本类型除外),所有的对 ...

  7. 一个10年Java程序员的年终总结,献给还在迷茫中的你

    我越来越担心我作为一个Java程序员的未来. 恍然间,发现自己在这个行业里已经摸爬滚打将近10年了,原以为自己就凭已有的项目经验和工作经历怎么着也应该算得上是一个业内比较资历的人士了,但是今年在换工作 ...

  8. 十年京东Java程序员的工作总结,写给迷茫中的你!

    很多年前,刚刚从大学毕业的时候,很多公司来校招.其中最烂俗的一个面试问题是:“你希望你之后三到五年的发展是什么?”.我当时的标准回答是(原话):“成为在某一方面能够独当一面的技术专家“.后来经历了几家 ...

  9. 作为一名双非本科毕业的Java程序员,我该如何在日益严重的内卷化中避免被裁?

    前言 对一个 Java 程序员而言,并发编程能否熟练掌握是判断他是不是优秀的重要标准之一.因为并发编程在 Java 语言中最为晦涩的知识点,它涉及内存.CPU.操作系统.编程语言等多方面的基础能力,更 ...

随机推荐

  1. IOS开发-UI学习-使用代码创建button

    使用代码创建button分5个步骤,分别是: 1.定义一个按钮,根据定义位置不同可定义为局部变量或者全局变量: 2.初始化按钮,一般使用一个矩形初始化: 3.设置按钮控件的其他属性,如背景图片,或者背 ...

  2. windows Vista-Server 2016系列激活脚本.cmd

    @ECHO OFFTITLE Windows 全版本系统激活ECHO 检测 操作系统版本...SET RQR=REG QUERY "HKLM\SOFTWARE\Microsoft\Windo ...

  3. 安卓Visibility属性

    可见(visible) XML文件:android:visibility="visible" Java代码:view.setVisibility(View.VISIBLE); 不可 ...

  4. MySQL5.6-Tomcat7环境变量的配置

    一.MySQL环境变量配置(zip安装):系统-高级系统设置--环境变量--path添加D:\Mysql\bin 找到mysql解压目录下的my-default.ini文件修改 basedir = D ...

  5. iOS 操作系统整体架构层次讲解

    iOS的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch l ...

  6. IOS 微信

    原文:http://blog.csdn.net/ysy441088327/article/details/8441608 按照常例,列一些网址先: 微信开放平台首页: http://open.weix ...

  7. js验证IP及子网掩码的合法性

    function checkIP(ip) {     obj=ip;    var exp=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0 ...

  8. HDU-1275-两车追及或相遇问题(数学题目)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1275 这题是一个数学题目,知道两个公式那就好办了: 对头相遇时:time*(v1+v2)=d*(2*i ...

  9. AdapterViewFlipper的功能和用法

    AdapterView继承了AdapterViewAnimator,它也会显示Adapter提供的多个View组件,但每次只能显示一个View组件,程序可通过showPrevious和showNext ...

  10. linux:基本命令

    1.显示日期与时间:date 显示2009/08/17形式的格式:date +%Y/%m/%d 显示17:04时间格式:date +%H/%M 2.显示日历:cal 常用的命令:cal 2009:ca ...