阿里巴巴突然来了个面试邀请电话,问了些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

最新文章

  1. 检查sql执行效率
  2. 深入浅出数据仓库中SQL性能优化之Hive篇
  3. 使用paramiko如何连接服务器?
  4. 在dede:arclist、dede:list等标签中调用附加字段
  5. java集合类的学习总结一
  6. 使用Nginx解决IIS绑定域名导致应用程序重启的问题
  7. Tengine:基于Nginx的衍生版
  8. Hive自定义UDAF详解
  9. 【转】Spark是基于内存的分布式计算引擎
  10. poj 1144 Network
  11. 数独 (dfs)
  12. Android Application.java以及它的作用
  13. response.sendRedirect 报 java.lang.IllegalStateException 异常的解决思路
  14. (luogu1704)寻找最优美做题曲线 [TPLY]
  15. HTML DOM - 导航
  16. H264--2--语法及结构
  17. SQL游标在递归是的时候提示 &quot;游标&quot; 名称已经存在的问题
  18. redis---安装和开启和关闭
  19. isinstance,issubclass,内置函数__str__和__repr__,__format__,dir()函数
  20. 多个RS-485设备怎么连接到一台电脑上?可以设置地址,有协议

热门文章

  1. 修改数据库用户名--CMD环境执行有效
  2. Ubuntu 12.4 server 安装 redmine
  3. QQ_SingleTalkClient
  4. Arrays工具类十大常用方法
  5. iOS实现高斯模糊效果(Swift版本)
  6. JS取消浏览器文本选中的方法
  7. 关于Java中继承多接口同名方法的问题
  8. SecureCRT中vim乱码问题
  9. 使用vue-cli构建多页面应用+vux(一)
  10. JQuery插件之Animate.css和 jquery-aniview