一直很想知道WeakHashMap的使用场景,想来想去只能用在高速缓存中,而且缓存的数据还不是特别重要,因为key(key不存在被引用的时候)随时会被回收

所以研究了一下WeakHashMap的回收时机

呵呵,现在可以重视 String str = "abc" 跟 String Str = new String("abc") 的区别了,因为涉及到收回问题

String str = "abc" //这属于编译时生成的字面量,会放入运行时常量池,这个区域的收回条件非常苛刻,所以一般不会被回收,所以哪怕不存在引用,WeakHashMap的这个key也不容易被回收

String Str = new String("abc") //会放入堆内存,GC着重处理这个区

/**
*
* @author ZhenWeiLai
*
*/
public class TestWeakHashMap { static WeakHashMap<String,String> map = new WeakHashMap<>();
//会被回收因为 map 的 key 用 new String 实例化了一个对象 保存在堆里,虽然是线程共享,但是并没有任何引用指向这个key
/**
* 这里补充一下,Java heap 是被所有线程共享的一块内存区域
* 几乎所有的对象实例都在这里分配内存,这里说几乎,是因为随着JIT编译器的发展与逃逸分析技术逐渐成熟
* 栈上分配,标量替换等优化技术将导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么绝对
*/
static {
map.put(new String("a"),new String("abc"));
map.put(new String("b"),new String("abc"));
map.put(new String("c"),new String("abc"));
map.put(new String("d"),new String("abc"));
map.put(new String("e"),new String("abc"));
map.put(new String("f"),new String("abc"));
map.put(new String("g"),new String("abc"));
} //会被回收
static WeakHashMap<String,String> map4 = new WeakHashMap<>();
static {
map4.put(new String("a"),"abc");
map4.put(new String("b"),"abc");
map4.put(new String("c"),"abc");
map4.put(new String("d"),"abc");
map4.put(new String("e"),"abc");
map4.put(new String("f"),"abc");
map4.put(new String("g"),"abc");
} static WeakHashMap<String,String> map2 = new WeakHashMap<>();
//不会被收回,因为存在 方法区(以前也叫永久代,JAVA8已经不存在永久代) - 常量池
/**
* (Method Area 别名 Non-Heap) 与Java Heap 一样,是各个线程共享的内存区域,
* 以前这个区域也叫作 永久代,因为几乎不会被回收
* 它用于存储已被虚拟机加载的类信息,常量,静态变量.即时编译后的代码等数据
*/
/**
* map2的key 是存在 运行时常量池,运行时常量池是 Method Area的一部分
* Java并不要求常量一定只有在编译期才能产生,运行期间也可能将新的常量放入池中,具有代表性的就是String的intern()方法
*/
static {
map2.put("a","abc");
map2.put("b","abc");
map2.put("c","abc");
map2.put("d","abc");
map2.put("e","abc");
map2.put("f","abc");
map2.put("g","abc");
} public static void main(String[] args) throws InterruptedException {
while(true){
/**
* 解开注释,map,map4的key将不会被回收
* 我理解为,在栈(也叫线程私有栈,或者工作内存)中,每个线程会将共享数据拷贝到栈顶进行运算,
* 这份数据其实是一个副本.(如果栈内部所包含的"局部变量"是引用,则仅仅是引用值在栈中,而且会占用一个引用本身的大小,具体的对象还是在堆当中,即对象本身的大小与栈空间的使用无关)
* 所以这个map存在一个引用,就不会去回收它的key
*/
// System.out.println("map:"+map.size());
// System.out.println("map2:"+map2.size());
// System.out.println("map4:"+map4.size()); //模拟被一个线程调用,然后休眠5秒,会随机被回收
new Thread(()->{
System.out.println("map:"+map.size());
System.out.println("map2:"+map2.size());
System.out.println("map4:"+map4.size());
System.out.println("-------------------");
}).start();
TimeUnit.SECONDS.sleep(5);
}
}
}

WeakHashMap回收时机结合JVM 虚拟机GC的一些理解的更多相关文章

  1. 【JVM虚拟机】(7)---深入理解Class中-属性集合

    #[JVM虚拟机](7)---深入理解Class中-属性集合 之前有关class文件已经写了两篇博客: 1.[JVM虚拟机](5)---深入理解JVM-Class中常量池 2.[JVM虚拟机](6)- ...

  2. 【JVM虚拟机】(8)--深入理解Class中--方法、属性表集合

    #[JVM虚拟机](8)--深入理解Class中--方法.属性表集合 之前有关class文件已经写了两篇博客: 1.[JVM虚拟机](5)---深入理解JVM-Class中常量池 2.[JVM虚拟机] ...

  3. 【JVM虚拟机】(6)---深入理解Class中访问标志、类索引、父类索引、接口索引

    JVM(6)访问标志,类索引 上一篇博客讲[JVM虚拟机](5)---深入理解JVM-Class中常量池 我们知道一个class文件正常可以分为7个部分: 魔数与class文件版本 常量池 访问标志 ...

  4. 【JVM虚拟机】(5)---深入理解JVM-Class中常量池

    深入理解Class---常量池 一.概念 1.jvm生命周期 启动:当启动一个java程序时,一个jvm实例就诞生了,任何一个拥有main方法的class都可以作为jvm实例运行的起点. 运行:mai ...

  5. WeakHashMap回收时机

    import java.util.ArrayList; import java.util.List; import java.util.WeakHashMap; public class TestWe ...

  6. 深入理解JVM——虚拟机GC

    对象是否存活 Java的GC基于可达性分析算法(Python用引用计数法),通过可达性分析来判定对象是否存活.这个算法的基本思想是通过一系列"GC Roots"的对象作为起始点,从 ...

  7. 深入理解JVM虚拟机6:深入理解JVM类加载机制

    深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...

  8. 学习JVM虚拟机原理总结

    0x00:JAVA虚拟机的前世今生 1991年,在Sun公司工作期间,詹姆斯·高斯林和一群技术人员创建了一个名为Oak的项目,旨在开发运行于虚拟机的编程语言,允许程序多平台上运行.后来,这项工作就演变 ...

  9. JVM虚拟机深入理解+GC回收+类加载

    旭日Follow_24 的CSDN 博客 ,全文地址请点击: https://blog.csdn.net/xuri24/article/details/81455449 一,前言 本文章是读了“深入理 ...

随机推荐

  1. git fetch, git pull 剖析

    真正理解 git fetch, git pull 要讲清楚git fetch,git pull,必须要附加讲清楚git remote,git merge .远程repo, branch . commi ...

  2. Servlet--超链接,表单提交,重定向,转发4种情况的路径

    实际编码中我们经常写路径,写路径既可以写相对路径,也可以写绝对路径.我2年以前我就养成了习惯,只要是写路径我从来都是写绝对路径,因为万一将来我们的项目的目录发生变化,原来要是写相对路径的话就会有路径依 ...

  3. 深入分析java传参

    概述      java中的参数传递问题可以根据参数的类型大致可以分为三类:传递基本类型,传递String类型,传递引用类型,至于最终是否可以归纳为值传递和引用传递,根据每个人的理解不同,答案不同,此 ...

  4. DNS入门

    引言 常见的计网协议通过IP地址来识别分布式应用的主机,然而IPV4(特别是IPV6)的地址太繁琐难以使用和记忆,因此提出了使用主机名称来识别,实质是:主机名称通过称为名称解析的过程转换为IP地址.其 ...

  5. ORACLE SQL脚本能否修改字段名称?

    在看到标题时,你先想想:在ORACLE中能否修改一个表的某个字段名呢?如果能的话,你是否还记得SQL脚本如何写的呢,呵呵,写这个的目的是因为在论坛上看见许多信誓旦旦的说ORACLE中不能修改字段名称, ...

  6. CSS——盒模型

    1.基本概念: 内容:(content)盒子里面的东西: 填充:(padding)怕盒子里面的东西损坏而添加的泡沫元素活抗震材料: 边框:(border)盒子本身 边界:(margin)则说明盒子的摆 ...

  7. css正三角倒三角

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  8. wpf图片浏览器,实现缩放平移操作图片切换等功能

    wpf经常要用到控件来查看图片,尤其是高清图片,于是做了一个例子: 1.定义图片的队列,用list来存. private readonly List<string> files; 2.切换 ...

  9. java 世界中Annotation

    java 世界中Annotation 在github上开始汇总一些自己学习,收集,总结,经验的一些信息,有利于跟踪,修改,提升.如果你感兴趣 可以关注一下,也可以提供自己的内容进来. https:// ...

  10. BZOJ 2565: 最长双回文串 [Manacher]

    2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1842  Solved: 935[Submit][Status][Discu ...