可以作为GC Roots的对象

一、名词解释

根搜索算法是JVM用来的判断对象是否存活的算法,此算法基本思路为通过一系列的“GC Roots”对象作为起始点,从这些节点往下搜索,当一个对象和GC Roots不可达时,则该对象是无用的,可被回收的。如下图所示:object5、object6、object7虽然互相有关联,但是他们到GC Roots是不可达的,因此他们都可以被回收。

在java中,可作为GC Roots的对象有:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  2. 方法区中的类静态属性引用的对象;
  3. 方法区中常量引用的对象;
  4. 本地方法栈中JNI(即一般说的Native方法)中引用的对象

二、验证可作为GC Roots的对象

此处只做最简单的验证,不涉及很复杂的GCRoots引用链。

1.验证虚拟机栈(栈帧中的局部变量)中引用的对象作为GC Roots

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* GCRoots 测试:虚拟机栈(栈帧中的局部变量)中引用的对象作为GCRoots
* -Xms1024m -Xmx1024m -Xmn512m -XX:+PrintGCDetails
*
* 扩展:虚拟机栈中存放了编译器可知的八种基本数据类型,对象引用,returnAddress类型(指向了一条字节码指令的地址)
*/
public class TestGCRoots01 {
private int _10MB = 10 * 1024 * 1024;
private byte[] memory = new byte[8 * _10MB];

public static void main(String[] args) {
method01();
System.out.println("返回main方法");
System.gc();
System.out.println("main-GC完成");
}

public static void method01() {
TestGCRoots01 t = new TestGCRoots01();
System.gc();
System.out.println("method01-GC完成");
}
}

控制台打印日志:

1
2
3
4
5
6
7
[GC [PSYoungGen: 105513K->616K(458752K)] 105513K->82536K(983040K), 0.0945986 secs] [Times: user=0.17 sys=0.06, real=0.09 secs] 
[Full GC [PSYoungGen: 616K->0K(458752K)] [ParOldGen: 81920K->82430K(524288K)] 82536K->82430K(983040K) [PSPermGen: 2547K->2546K(21504K)], 0.0273364 secs] [Times: user=0.06 sys=0.01, real=0.03 secs] 
method01-GC完成
返回main方法
[GC [PSYoungGen: 15728K->64K(458752K)] 98159K->82494K(983040K), 0.0014739 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC [PSYoungGen: 64K->0K(458752K)] [ParOldGen: 82430K->510K(524288K)] 82494K->510K(983040K) [PSPermGen: 2546K->2546K(21504K)], 0.0118484 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
main-GC完成

method01-GC:

t为局部变量,引用了new出的对象(80M),作为GC Roots,在Minor GC后被转移到老年代中,且Full GC也不会回收该对象,仍保留在老年代中。

main-GC:

method01方法执行完后,局部变量t跟随方法消失,不再有引用类型指向该对象,该对象在Full GC后,被完全回收,老年代腾出该对象之前所占的空间。

2.验证方法区中的静态变量引用的对象作为GC Roots

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 测试方法区中的静态变量引用的对象作为GCRoots
* -Xms1024m -Xmx1024m -Xmn512m -XX:+PrintGCDetails
*
* 扩展:方法区内存与堆一样,是各个线程共享的内存区域,用于存放已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
* */
public class TestGCRoots02 {
private static int _10MB = 10 * 1024 * 1024;
private byte[] memory;

private static TestGCRoots02 t;

public TestGCRoots02(int size) {
memory = new byte[size];
}

public static void main(String[] args) {
TestGCRoots02 t2 = new TestGCRoots02(4 * _10MB);
t2.t = new TestGCRoots02(8 * _10MB);
t2 = null;
System.gc();
}
}

控制台打印日志:

1
2
[GC [PSYoungGen: 138608K->632K(458752K)] 138608K->82552K(983040K), 0.0684508 secs] [Times: user=0.19 sys=0.06, real=0.07 secs] 
[Full GC [PSYoungGen: 632K->0K(458752K)] [ParOldGen: 81920K->82427K(524288K)] 82552K->82427K(983040K) [PSPermGen: 2513K->2512K(21504K)], 0.0162803 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

t2被置为null,Minor GC后t2之前引用的对象(40M)被完全回收;t为静态变量,存放于方法区中,引用了对象(80M),在Minor GC后,被转移到老年代中,且在Full GC后,也不会被回收,继续保留在老年代中。

3.验证方法区中常量引用对象作为GC Roots

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 测试常量引用对象作为GCRoots
* 注意:t修饰符如果只是final会被回收,static final不会被回收,所以static final 才是常量的正确写法
* -Xms1024m -Xmx1024m -Xmn512m -XX:+PrintGCDetails
*/
public class TestGCRoots03 {
private static int _10MB = 10 * 1024 * 1024;
private static final TestGCRoots03 t = new TestGCRoots03(8 * _10MB);
private byte[] memory;

public TestGCRoots03(int size) {
memory = new byte[size];
}

public static void main(String[] args) {
TestGCRoots03 t3 = new TestGCRoots03(4 * _10MB);
t3 = null;
System.gc();
}
}

控制台打印日志:

1
2
[GC [PSYoungGen: 138608K->688K(458752K)] 138608K->82608K(983040K), 0.0514407 secs] [Times: user=0.13 sys=0.02, real=0.05 secs] 
[Full GC [PSYoungGen: 688K->0K(458752K)] [ParOldGen: 81920K->82428K(524288K)] 82608K->82428K(983040K) [PSPermGen: 2515K->2514K(21504K)], 0.0153884 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]

t3被置为null,Minor GC后t3之前引用的对象(40M)被完全回收;t为常量,存放于方法区中,引用了对象(80M),在Minor GC后,被转移到老年代中,且在Full GC后,也不会被回收,继续保留在老年代中。

4.测试成员变量是否可作为GC Roots

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 测试成员变量引用对象是否可作为GCRoots
* -Xms1024m -Xmx1024m -Xmn512m -XX:+PrintGCDetails
*/
public class TestGCRoots04 {
private static int _10MB = 10 * 1024 * 1024;
private TestGCRoots04 t;
private byte[] memory;

public TestGCRoots04(int size) {
memory = new byte[size];
}

public static void main(String[] args) {
TestGCRoots04 t4 = new TestGCRoots04(4 * _10MB);
t4.t = new TestGCRoots04(8 * _10MB);
t4 = null;
System.gc();
}
}

控制台打印日志:

1
2
[GC [PSYoungGen: 138608K->600K(458752K)] 138608K->600K(983040K), 0.0015591 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC [PSYoungGen: 600K->0K(458752K)] [ParOldGen: 0K->507K(524288K)] 600K->507K(983040K) [PSPermGen: 2513K->2512K(21504K)], 0.0144441 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]

t4被置为null,Minor GC后t4之前引用的对象(40M)被完全回收;t为成员变量,也叫实例变量,不同于类变量(静态变量),前面讲到类变量是存储在方法区中,而成员变量是存储在堆内存的对象中的,和对象共存亡,所以是不能作为GC Roots的,从日志中也可看出t在MinorGC后,跟随t4一起被完全回收。不再占用任何空间。

以上为一个非常简单的可作为GC Roots的对象的验证,不涉及较复杂的GC Roots引用链,其实作为使用者来讲,我们只要知道,哪些对象是可作为GC Roots的,在实际开发过程中要特别注意这些对象,不要让无谓的大对象消耗了资源,拖累了性能。

java并发编程系列-第一篇

1. 进程和线程的由来

1.1 进程的由来

操作系统中为什么会出现进程?

计算机制造的早期,是用来解决数学问题的,在最初的时候,计算机只能完成特定的指令。用户输入一个指令,计算机就执行一个操作。如果用户在思考或者输入数据的时候,计算机就会等待。很显然,这样的效率很低下,因为大部分情况下,计算机一直都会处于等待输入指令的状态。

后来,就有人想到,能不能把一系列需要执行的指令预先写下来,形成一个清单,一次性交给计算机。计算机呢,则不断的去读取指令来进行相应的操作。(这就是最早的批处理操作系统,用户可以将程序写到磁带上,然后计算机去逐条读取并执行,将结果输出到另一个磁带上。)

机器学习评价标准

机器学习(ML),自然语言处理(NLP),信息检索(IR)等领域,评估(Evaluation)是一个必要的工作,而其评价指标往往有如下几点:准确率(Accuracy),精确率(Precision),召回率(Recall)和F1-Measure。(注:相对来说,IR的ground truth很多时候是一个Ordered List, 而不是一个Bool类型的Unordered Collection,在都找到的情况下,排在第三名还是第四名损失并不是很大,而排在第一名和第一百名,虽然都是“找到了”,但是意义是不一样的,因此更多可能适用于 MAP 之类评估指标。)

2017年看的书单.md

本篇用来整理我2017年看过的书籍。希望能有助于我坚持下去。不限于技术书,今年的目标是52+本书。加油吧!

序号 书名 作者 链接 读过次数
1 Java8函数式编程 Richard Warburton著,王群锋译 豆瓣 1
2 分布式java应用-基础与实践 林昊著 豆瓣 1
3 美国历史(英汉对照 经典珍藏版 学生版) 爱德华·钱宁(Edward Channing) 著;刘强,高岭,李勇 译 京东 1
4 不可不知的美国常识 左岸 著 京东 1
5 理解美国-美国文化指南 加里·阿尔滕,詹尼特·班尼特 著;曹菁,王颖 译 豆瓣 1
6 腾讯传-中国互联网公司进化论 吴晓波 著 豆瓣 1
7 Apache Kylin权威指南 Apache Kylin核心团队 著 豆瓣 1
8 基于Apache Kylin构建大数据分析平台 蒋守壮 著 豆瓣 1
9 小家越住越大 逯薇 著 豆瓣 1
10 追风筝的人 [美] 卡勒德·胡赛尼 著 豆瓣 1
11 深度学习轻松学:核心算法与视觉实践 冯超 著 豆瓣 1
12 断点:互联网进化启示录 [美]杰夫·斯蒂贝尔 著 师蓉 译 豆瓣 1
13 代码整洁之道:程序员的职业素养 罗伯特·C.马丁 (Robert C.Martin) 著 余晟、章显洲 译 豆瓣 1
14 三体I 刘慈欣 著 豆瓣 1
15 三体II 刘慈欣 著 豆瓣 1
16 三体III 刘慈欣 著 豆瓣 1
17 Python参考手册 第4版 修订版 David M. Beazley 豆瓣 1
18 颠覆者-周鸿祎自传 周鸿祎/范海涛 豆瓣 1
19 Flume:构建高可用、可扩展的海量日志采集系统 【美】Hari Shreedharan 著 , 马延辉 / 史东杰 译 豆瓣 1
数据立方体和OLAP

1. 数据立方体

关于数据立方体(Data Cube),这里必须注意的是数据立方体只是多维模型的一个形象的说法。立方体其本身只有三维,但多维模型不仅限于三维模型,可以组合更多的维度,但一方面是出于更方便地解释和描述,同时也是给思维成像和想象的空间;另一方面是为了与传统关系型数据库的二维表区别开来,于是就有了数据立方体的叫法。所以本文中也是引用立方体,也就是把多维模型以三维的方式为代表进行展现和描述,下面是一个数据立方体的示例图片:

mac osx单机上安装apache-kylin

最近开始调研apache-kylin,关于kylin的介绍往上有很多,本文就不再过多介绍,只讲述如何在mac osx配置测试用的kylin环境。
需要安装及部署的软件包括:hadoop,mysql,hive,zookeeper,hbase,kylin。本篇主要讲述如下版本的安装工作:

  • hadoop-2.7.3
  • mysql-5.6.31
  • hive-2.1.1
  • zookeeper-3.4.8
  • hbase-1.3.0
  • kylin-1.6.0-hbase1.x
mac安装Faster R-CNN

在mac上安装fast-r-cnn时遇到了一些坑。所以整理下,以便对有需要的人有所帮助。

1. 下载代码

1
2
$ cd /Users/ruifengshan/githubRepos/
$ git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git

2. 下载模型

1
2
3
4
5
6
7
8
$ cd /Users/ruifengshan/githubRepos/py-faster-rcnn
$ ./data/scripts/fetch_faster_rcnn_models.sh
Downloading Faster R-CNN demo models (695M)...
...
Unzipping...
faster_rcnn_models/
faster_rcnn_models/ZF_faster_rcnn_final.caffemodel
faster_rcnn_models/VGG16_faster_rcnn_final.caffemodel

国内下载的有点慢。

shell特殊变量

变量名只能包含数字、字母和下划线,因为某些包含其他字符的变量有特殊含义,这样的变量被称为特殊变量。

例如,$$ 表示当前Shell进程的ID,即pid,看下面的代码:

1
$ echo $$

运行结果

1
29949

特殊变量列表

变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(“ “)包含时,与 $* 稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
caffe学习-模型定义

本文用来整理在学习caffe时遇到的一些基础概念。希望通过整理能加深自己的理解。

mac安装caffe

1.安装nvidia驱动

在nvidia官网下载最新驱动,我选择的是网络dmg安装。安装的时候全选所有选项。

如果没有安装homebrew,安装homebrew

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"