主页

浅入理解JVM(二)—— JVM 垃圾回收机制

Java内存中的线程私有部分(程序计数器、虚拟机栈、本地方法栈)的内存分配与回收都是确定的,它们随方法退出或者线程结束而回收。因此,垃圾回收主要是围绕Java堆和方法区展开的,更确切地说,垃圾回收问题就是对象内存的分配与回收问题。 1.对象可回收判断 垃圾回收需要考虑三件事:哪些内存需要回收?什么时候回收?如何回收? 1.1 引用计数算法 引用计数算法是一种判断对象是否还“存活”的简单算法,它给每个对象添加一个引用计数器,每当有一个地方引用它,计数器就加一;当计数器值为零时,则认为该对象已经“死亡”,可以被回收。 但主流的 Java 虚拟机从未选用过这种方法去管理内存,主要原因在于它无法解决“对象循环引用”问题。考虑下面的这段代码,对象 A 被 objA 引用,而后又被对象 ...

阅读更多

浅入理解JVM(一)

Part1. Java内存区域 1.运行时数据区域 在程序运行过程中,Java 虚拟机会把它所管理的内存区域分为五个部分:程序计数器、虚拟机栈、本地方法栈、堆以及方法区。其中,在JDK 1.7及以前版本,方法区保留在堆中,但在 JDK 1.8 中方法区被转移到了直接内存中并更名为元空间,并且“永久代”这一概念也随之放弃了。 (01)JDK 7 内存区域: (02)JDK 8 内存区域: 1.1 程序计数器 程序计数器又叫行号指示器,它用来指示下一条待执行的字节码指令。而由于在多线程环境下,线程会轮流切换,为了在线程切换后能够正确执行当前线程的下一条指令,需要给每一个线程都配一个独立的程序计数器,因此程序计数器所在内存区域是“线程私有”的。 注意: (01)如果线...

阅读更多

Java集合之HashMap

如果用一句话总结的话:HashMap 由“数组 + 链表/红黑树”组合而成,初始容量为16,扩容方式为“新容量 = 原容量*2”,负载因子为 0.75,支持一个 null 键和多个 null 值,链表和红黑树之间的转换边界为 6 和 8,线程不安全。 1.基本框架 HashMap作为Map家族的代表,它的其他几个“亲戚”都是基于HashMap在一定程度上的模仿、修改得来的,简单认识一下即可。 (01)WeakHashMap:把HashMap的键从强引用变为弱引用,当某个键不再被使用后,WeakHashMap同该键产生的「引用联系」并不阻止垃圾回收器的回收。 (02)HashTable:把HashMap的方法用synchronized关键字包装一遍,通过牺牲大部分性能来实现线...

阅读更多

Java集合之ArrayList

ArrayList和HashMap是集合学习的两座大山,由于其庞杂的体量,很容易让我们初学者在源码中迷失方向。个人认为,学习集合,应该从最基本的数据结构(包含集合的创建与扩容)、常用的增删查改方法、多线程环境的线程安全性三个方面来学习。虽然堪堪入门,但管中窥豹,可见一斑,以后慢慢深入也不迟。 1.数据结构 1.1 底层结构 可以看到,ArrayList底层就是一个名为elementData的动态数组,暂时还没初始化。 transient Object[] elementData; // non-private to simplify nested class access 其中,使用关键字transient修饰的目的是让集合在序列化时只存储实际大小。在这其中的玄机在writ...

阅读更多