阿里巴巴突然来了个面试邀请电话,问了些java底层的东西,不知所措,所以专门花了些时间做了下学习,顺便记录下,好记性不如烂笔头。

一、对JAVA的垃圾回收机制(GC)的理解

  不同于C/C++需要手工释放对象所占的内存,JAVA全部委托给了GC进行处理,能更有效的防止内存泄漏的情况。一个程序对应着一个JVM,每个JVM会单独有一个堆,java中创建的对象与数组是存放在堆中的,堆中的内存由GC进行管理(栈中存储引用变量、局部变量一级基本数据类型,超出作用域就会立即释放内存)。

  当一个对象没有再被引用时就会被GC标记为可回收状态,然后在一个不确定的时间对其进行回收(一般是在应用程序空闲或者java堆内存不足是被调用),当然在对一个对象进行回收时,首先会执行其finalize()方法,在finalize()方法中你可再次将该对象变为活跃状态,阻止其回收。  

  一个对象还有没有再被引用一般有两种判断方式:

  1、(JDK1.2之前)每个对象都有一个引用计数器,每多一个引用,计数器+1,少一个则-1,当计数器为0时,则表示该对象没有再被引用了。

  2、根搜索算法。这里要盗一张图了:

    

  从GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。  

  java中可作为GC Root的对象有:

    1.虚拟机栈中引用的对象(本地变量表)

    2.方法区中静态属性引用的对象

    3. 方法区中常量引用的对象

    4.本地方法栈中引用的对象(Native对象)

  GC在回收这些空闲对象时会采用标记-复制算法处理:

    

    标记从根节点出发的所有在用对象,然后按顺序复制到一块新内存上,然后再回收旧内存。这样就不会造成造成内存碎片,但是需要一块额外的内存交换空间来进行复制。

二、对HashMap的理解

  HashMap结构其实是一个数组+链表的结构。HashMap有一个叫做Entry的内部类,它用来存储key-value对。如下图:

      

static class Entry implements Map.Entry
{
final K key;
V value;
Entry next;
final int hash;
...//More code goes here
} `

    

    创建一个HashMap时会首先创建一个叫做table的Entry数组:

    

    table的默认大小是16。当往map里面存数据时,也就是执行put方法时,首先会调用key的HashCode()方法,然后进行hash计算,计算出其对应在table的index,如果table的index位置上已经有Entry了,首先会判断该Entry的key与要put的key是否相同,如果相同则会替换,如果不同则会根据链表继续判断,即与当前位置的Entry的next指向的下一个Entry的key进行比较,直到遇到相同的key进行替换或者在链表末尾创建一个Entry。

 /**
* Associates the specified value with the specified key in this map. If the
* map previously contained a mapping for the key, the old value is
* replaced.
*
* @param key
* key with which the specified value is to be associated
* @param value
* value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
* if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return
* can also indicate that the map previously associated
* <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<k , V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}

  从map中取值时也就是执行get()方法也是类似的道理,先计算出key对应table的index,然后在链表上一层一层往下找:

 /**
* Returns the value to which the specified key is mapped, or {@code null}
* if this map contains no mapping for the key.
*
* <p>
* More formally, if this map contains a mapping from a key {@code k} to a
* value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise it returns
* {@code null}. (There can be at most one such mapping.)
*
* </p><p>
* A return value of {@code null} does not <i>necessarily</i> indicate that
* the map contains no mapping for the key; it's also possible that the map
* explicitly maps the key to {@code null}. The {@link #containsKey
* containsKey} operation may be used to distinguish these two cases.
*
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<k , V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}

    备注:

    1、无论你何时实现 equals 方法,你必须同时实现 hashCode 方法。在一个运行的进程中,相等的对象必须要有相同的哈希码。不相等的对象哈希码有可能相同,有同一个哈希值的对象不一定相等。

    2、HashMap有两个参数影响其性能:初始容量加载因子。默认初始容量是16,加载因子是0.75。容量是哈希表中桶(Entry数组)的数量,初始容量只是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,通过调用 rehash 方法将容量翻倍。

希望大家能一起交流,一起学习!

参考文章链接:

http://www.importnew.com/16517.html

http://www.importnew.com/10620.html

http://jbutton.iteye.com/blog/1569746

JVM、GC与HashMap的更多相关文章

  1. 如何避免后台IO高负载造成的长时间JVM GC停顿(转)

    译者著:其实本文的中心意思非常简单,没有耐心的读者建议直接拉到最后看结论部分,有兴趣的读者可以详细阅读一下. 原文发表于Linkedin Engineering,作者 Zhenyun Zhuang是L ...

  2. 【转载】Java性能优化之JVM GC(垃圾回收机制)

    文章来源:https://zhuanlan.zhihu.com/p/25539690 Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我 ...

  3. JVM GC机制

    垃圾收集主要是针对堆和方法区进行. 回收机制: 现在的JVM基本都使用分代回收机制,把堆中内存区域分为新生代,老年代. 新生代: Eden(80%) Survivor0(10%) Survivor1( ...

  4. 深入浅出 JVM GC(3)

    # 前言 在 深入浅出 JVM GC(2) 中,我们介绍了一些 GC 算法,GC 名词,同时也留下了一个问题,就是每个 GC 收集器的具体作用.有哪些 GC 收集器呢? Serial 串行收集器(只适 ...

  5. 深入浅出 JVM GC(2)

    # 前言 在 深入浅出 JVM GC(1) 中,限于上篇文章的篇幅,我们留下了一个问题 : 如何回收? 这篇文章将重点讲述这个问题. 在上篇文章中,我们也列出了一些大纲,今天我们就按照那个大纲来逐个讲 ...

  6. JVM 自带性能监测调优工具 (jstack、jstat)及 JVM GC 调优

    1. jstack:占用最多资源(CPU 内存)的Java代码 https://www.cnblogs.com/chengJAVA/p/5821218.html https://blog.csdn.n ...

  7. 理解JVM GC

    理解JVM GC对于我们把控Java应用有很大的帮助.下面我从运维角度,把网上的JVM相关的资料整理如下,以加深对JVM GC的理解.如有错误的地方,请看官指正. JVM内存使用分类 JVM的内存分区 ...

  8. Java性能优化之JVM GC(垃圾回收机制)

    Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.st ...

  9. JVM gc介绍

    Java语言出来之前,大家都在拼命的写C或者C++的程序,而此时存在一个很大的矛盾,C++等语言创建对象要不断的去开辟空间,不用的时候有需要不断的去释放控件,既要写构造函数,又要写析构函数,很多时候都 ...

  10. 一夜搞懂 | JVM GC&内存分配

    前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习导图 一.为什么要学习GC&内存分配? 时代发展到现在,如今的内存动态分配与内存回收技术已经相当成 ...

随机推荐

  1. 一个GOOD的Idea需要伯乐发觉-致敬错过的IDEA

    类似一个微信电话本

  2. [转载]转载一篇好文章作为Java与面向对象之随感(3)

    关于对象与引用之间的一些基本概念. 初学Java时,在很长一段时间里,总觉得基本概念很模糊.后来才知道,在许多Java书中,把对象和对象的引用混为一谈.可是,如果我分不清对象与对象引用, 那实在没法很 ...

  3. Java原子变量

    实现全局自增id最简单有效的方式是什么?java.util.concurrent.atomic包定义了一些常见类型的原子变量.这些原子变量为我们提供了一种操作单一变量无锁(lock-free)的线程安 ...

  4. MongoDB基础教程系列--第八篇 MongoDB 副本集实现复制功能

    为什么用复制 为什么要使用复制呢?如果我们的数据库只存在于一台服务器,若这台服务器宕机了,那对于我们数据将会是灾难,当然这只是其中一个原因,若数据量非常大,读写操作势必会影响数据库的性能,这时候复制就 ...

  5. php常用的优化手段

    由于工作码成狗,抽闲整理了下内容,以下是网上流传比较广泛的30种SQL查询语句优化方法: 1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. ...

  6. 多云时代,海外微软Azure云与国内阿里云专线打通性能测试

    本文地址:http://www.cnblogs.com/taosha/p/6528730.html 在云计算的大时代,大型客户都有业务全球拓展的需求,考虑到成本,时间因素,一般都是选择云计算,现在云计 ...

  7. 通过virtualbox最小化安装centos 6.3后无法上网解决办法

    通过virtualbox最小化安装centos 6.3后无法上网解决办法 1.设置virtualbox的网络连接方式,如下图使用桥接方式,桥接的网卡为宿主正在上网的网卡,现在我是通过无线来上网的,所以 ...

  8. Unity 检测物体是否在相机视野范围内

    需求: 类似NPC血条,当NPC处于摄像机视野内,血条绘制,且一直保持在NPC头顶. 开始: 网上查找资料,然后编写代码: public RectTransform rectBloodPos; voi ...

  9. Map的迭代

    public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Int ...

  10. netty——私有协议栈开发案例

    netty--私有协议栈开发案例 摘要: 在学习李林峰老师的Netty权威指南中,觉得第十二章<私有协议栈开发>中的案例代码比较有代表性,讲的也不错,但是代码中个人认为有些简单的错误,个人 ...