2018年2月

关于 JVM 回收中 跨代之间的引用 card marking, dirty card, write barrier

JVM GC 回收对象的时候, 都是先找出 Root 对象, 然后按照引用关系作出引用关系图, 得到live 对象, 剩下的都是 dead 对象, 继而回收掉这些 dead 对象.

分代回收的时候, 先回收年轻代, 为什么回收年轻代那么快? 仅仅因为年轻代比较小吗? 回收年轻代的时候, 要扫描所有的老年代对象吗? 这里就涉及到 dirty card.
年轻代回收的时候, 首先找出 root 对象, 然后对于从老年代到年轻代的引用, 可以有下面几种方式来发现老年代到年轻代的引用:
1) 从 root 对象开始找到从老年代到年轻代的引用关系 - 比较耗时, 相当于整个 heap 都做引用关系图;
2) 不从 root 对象开始, 而是从所有老年代对象开始, 扫描所有老年代对象, 然后找到从老年代到年轻代的引用 - 也挺多的.

openJDK 采用的是上面第二种方式的一个变种. 对老年代 heap 设立一个 dirty card 表. 例如对老年代每256K 映射到 dirty card 中的一个 bit, 如果老年代有对年轻代的引用的时候(老年代对象字段值的修改), 把这个 bit 修改代表 dirty.

一个过程如下:
假如刚做完一次 full GC, 年轻代都是空的, 那么如下:
1) 如果有新分配对象, 它一定在年轻代, 如果有老年代对象指向这个新对象(字段赋值), 那么这个老年代对象所对应内存的对应
dirty card bit 被修改为 dirty;
2) 等到 minor GC 发生的时候, GC 把老年代 dirty card 里面 dirty bit 对应的内存部分的老年代对象和加入到 root 里面, 就可以了. 这样避免了扫描全部. 一旦年轻代 mark 阶段结束, 整个 dirty card 全部恢复为空;
3) 一旦年轻代开始从 eden 和 from survival copy 到 to survival 或者 promote 部分对象到老年代, 那么 dirty card 的 dirty bit 就开始工作了. 有指针引用的就会变成 dirty bit;

同时年轻代比较小, 所以一次能容纳的对象比较少, 所以 dirty card 里面 dirty bit 不会太多.

随便摘要, 更详细信息可以从这里看:
https://www.ibm.com/developerworks/library/j-jtp11253/
http://blog.ragozin.info/2011/06/understanding-gc-pauses-in-jvm-hotspots.html

sony rp1 目录问题

sony rp1 电子书现在的版本里面没有目录导航功能(截止到今天2018年2月23日), 据说在酝酿的下一个版本会有. 不过我发现其实有个小功能可以缓解这个问题.

在一般的 pdf 电子书的目录导航页面, 在每个章节下面都有很多虚线, 你一点, 基本可以直接到那一页;
同样在具体的章节的标题下面,也有虚线, 你一点章节目录, 就能回到目录页面;

也就是说你只要找到最近的章节标题, 点一下, 就回到了目录了.

当然上面还是真对哪些目录功能完好对PDF.

对于很多其它的 pdf 文件, 它的目录功能本来就不是可用的, 这个功能就不好用了. 只能通过现有的页数跳转来实现. 我一般是跳到 15页左右, 这里基本是目录页, 然后在根据目录页给的章节页数, 算出大约要跳到多少页去.

1-static factory - Effective Java 3rd version [学习笔记]

static factory 优点:

  1. have meaningful name;
  2. not required to create new object each time

-- Singleton;
-- Cache object;
-- Return object based on parameters;

  1. return sub-class, not current class;
  2. returned object can vary from call to call, release to release;

缺点:
难找.

可以用 .from, .of, .valueOf, .instance, .getInstance, .create, .newInstance, .getType, .type, .newType.

iterm2 懒人输入密码

使用iTerm2 自带的密码管理器输入密码

  1. 在密码管理器里面预设密码
    打开 iTerm2, 菜单:Window -> Password Manager 打开密码管理器;
    然后点击左下方的 + 号, 然后 添加一个密码
    pwdMgr.png
  2. 设置 trigger
    打开 iTerm2, 菜单 iTerm2 -> Preference 然后开始设置
    Profiles -> 选择你使用的profile,比如Default -> Advanced -> Trigger -> Edit -> 打开 Triggers
    右下角 + 号,
    Regular Expression -> ssh. 或者 password.
    Action: Open Password Manager
    Parameter: 选择你上一步输入的密码管理器的设置的;
    menu.png
    trigger.png

很多情况你可能在第一次ssh 一个新机器的时候会遇到接受认证的消息, 让你接受一个新的认证,给 yes/no, 其实有办法默认接受所有的认证:
编辑 ~/.ssh/config, 若没有,则新建. 改成如下类似, 我这里是如果机器名是 *.tianxiaohui.com, 则默认接受

[xiatian@eric.tianxiaohui.com ~]$ cat ~/.ssh/config
Host *.tianxiaohui.com
    StrictHostKeyChecking no

如果修改了 ~/.ssh/config 之后, 报下面的错:
Bad owner or permissions on /export/home/xiatian/.ssh/config
则修改这个文件的权限:
chmod 600 ~/.ssh/config