ellios's blog

ellios's trivial story.

HotSpot各种GC的输出

| Comments

闲着无事体验下jdk7的一些新特性,先体验下G1,顺手把其他的GC方式也复习下。

用来测试的程序

测试程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package gc;

public class HeapOOM {
    static class OOMObject {

    }

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();
        while(true) {
            list.add(new OOMObject());
        }
    }
}

SerialGC

执行命令如下:

java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC gc.HeapOOM

输出如下

[GC [DefNew: 6919K->1023K(9216K), 0.0184790 secs] 6919K->4907K(19456K), 0.0185330 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC [DefNew: 9215K->1024K(9216K), 0.0220750 secs] 13099K->10753K(19456K), 0.0221190 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
[GC [DefNew: 8510K->8510K(9216K), 0.0000280 secs][Tenured: 9729K->7736K(10240K), 0.0590890 secs] 18240K->16044K(19456K), [Perm : 2364K->2364K(21248K)], 0.0592060 secs] [Times: user=0.05 sys=0.00, real=0.05 secs] 
[Full GC [Tenured: 7736K->7730K(10240K), 0.0548170 secs] 16044K->16038K(19456K), [Perm : 2364K->2362K(21248K)], 0.0548950 secs] [Times: user=0.06 sys=0.00, real=0.06 secs]

Parallel GC

执行命令如下:

java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseParallelGC gc.HeapOOM

输出如下:

[GC [PSYoungGen: 6893K->1017K(9216K)] 6893K->4937K(19456K), 0.0185000 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 
[GC [PSYoungGen: 9209K->1008K(9216K)] 13129K->10470K(19456K), 0.0256190 secs] [Times: user=0.03 sys=0.01, real=0.02 secs] 
[Full GC [PSYoungGen: 1008K->187K(9216K)] [ParOldGen: 9462K->10237K(10240K)] 10470K->10425K(19456K) [PSPermGen: 2367K->2365K(21248K)], 0.2739010 secs] [Times: user=0.34 sys=0.00, real=0.28 secs] 

Concurrent Mark Sweep

执行命令如下:

java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC gc.HeapOOM

输出如下:

[GC [ParNew: 6904K->1024K(9216K), 0.1083590 secs] 6904K->6785K(19456K), 0.1084710 secs] [Times: user=0.15 sys=0.01, real=0.11 secs] 
[GC [ParNew: 9216K->9216K(9216K), 0.0000500 secs][CMS: 5761K->8649K(10240K), 0.0645400 secs] 14977K->13591K(19456K), [CMS Perm : 2365K->2363K(21248K)], 0.0647080 secs] [Times: user=0.06 sys=0.00, real=0.06 secs] 
[GC [1 CMS-initial-mark: 8649K(10240K)] 13708K(19456K), 0.0081840 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[Full GC [CMS[CMS-concurrent-mark: 0.023/0.023 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
 (concurrent mode failure): 8649K->8649K(10240K), 0.0681890 secs] 13708K->13606K(19456K), [CMS Perm : 2363K->2363K(21248K)], 0.0682770 secs] [Times: user=0.07 sys=0.00, real=0.07 secs] 
[Full GC [CMS: 10239K->10240K(10240K), 0.0688260 secs] 19455K->17275K(19456K), [CMS Perm : 2366K->2366K(21248K)], 0.0689230 secs] [Times: user=0.07 sys=0.00, real=0.07 secs] 
[GC [1 CMS-initial-mark: 10240K(10240K)] 17430K(19456K), 0.0111890 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[CMS-concurrent-mark: 0.027/0.027 secs] [Times: user=0.05 sys=0.00, real=0.03 secs] 
[Full GC [CMS[CMS-concurrent-preclean: 0.025/0.025 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
 (concurrent mode failure): 10240K->10240K(10240K), 0.0884470 secs] 19412K->19412K(19456K), [CMS Perm : 2366K->2366K(21248K)], 0.0885610 secs] [Times: user=0.09 sys=0.00, real=0.09 secs]

G1

执行命令如下:

java -verbose:gc -Xms20M -Xmx20M -XX:+PrintGCDetails -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC gc.HeapOOM

G1的输出好大一坨,这里就主要描述它的各个阶段,详细的内容就略过了,有兴趣的话,自己测把。

[GC pause (young), 0.07679200 secs]
   [Parallel Time:  76.4 ms]
      [GC Worker Start (ms):  126.0  126.1
       Avg: 126.1, Min: 126.0, Max: 126.1, Diff:   0.1]
      [Ext Root Scanning (ms):  0.8  0.7
       Avg:   0.8, Min:   0.7, Max:   0.8, Diff:   0.1]
      [Update RS (ms):  7.6  8.0
       Avg:   7.8, Min:   7.6, Max:   8.0, Diff:   0.4]
         [Processed Buffers : 3 10
          Sum: 13, Avg: 6, Min: 3, Max: 10, Diff: 7]
      [Scan RS (ms):  18.0  11.1
       Avg:  14.5, Min:  11.1, Max:  18.0, Diff:   6.9]
      [Object Copy (ms):  49.9  56.5
       Avg:  53.2, Min:  49.9, Max:  56.5, Diff:   6.6]
      [Termination (ms):  0.0  0.0
       Avg:   0.0, Min:   0.0, Max:   0.0, Diff:   0.0]
         [Termination Attempts : 1 1
          Sum: 2, Avg: 1, Min: 1, Max: 1, Diff: 0]
      [GC Worker End (ms):  202.4  202.4
       Avg: 202.4, Min: 202.4, Max: 202.4, Diff:   0.0]
      [GC Worker (ms):  76.3  76.2
       Avg:  76.3, Min:  76.2, Max:  76.3, Diff:   0.1]
      [GC Worker Other (ms):  0.1  0.2
       Avg:   0.1, Min:   0.1, Max:   0.2, Diff:   0.1]
   [Clear CT:   0.1 ms]
   [Other:   0.3 ms]
      [Choose CSet:   0.0 ms]
      [Ref Proc:   0.1 ms]
      [Ref Enq:   0.0 ms]
      [Free CSet:   0.0 ms]
   [Eden: 7168K(7168K)->0B(3072K) Survivors: 0B->1024K Heap: 10138K(20M)->8858K(20M)]
 [Times: user=0.11 sys=0.00, real=0.08 secs] 
[GC pause (young) (initial-mark), 0.05340800 secs] 
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0015220]
[GC concurrent-mark-start]
[GC pause (young), 0.04182800 secs]
[Full GC 13M->10M(20M), 0.0579320 secs]
 [Times: user=0.07 sys=0.00, real=0.06 secs] 
[GC concurrent-mark-abort]
[GC pause (young) (to-space overflow), 0.18594400 secs]
[GC pause (young) (initial-mark), 0.02209700 secs]
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0000130]
[GC concurrent-mark-start]
[Full GC 17M->15M(20M), 0.0831100 secs]
 [Times: user=0.09 sys=0.01, real=0.08 secs] 
[GC pause (young), 0.00407500 secs]
[GC concurrent-mark-abort]
[Full GC 15M->15M(20M), 0.0741120 secs]
 [Times: user=0.08 sys=0.00, real=0.07 secs] 
[Full GC 15M->15M(20M), 0.0801960 secs]
 [Times: user=0.08 sys=0.00, real=0.08 secs] 

参考资料

http://blog.csdn.net/firecoder/article/details/7225654

Java常用单例

| Comments

单例是最常用到的一个设计模式,java的单例实现方式还是挺多的,总结下遇到的一些单例的实现

一. 最简单的单例

最简单的单例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public class Singleton {

      private static Singleton instance = null;
  
      private Singleton() {
      }
  
      public static Singleton getInstance() {
          if (instance == null) {
              instance = new Singleton();
          }
          return instance;
      }
  }

这种有并发问题,为了避免并发问题需要在判断的时候加锁。于是有了下面的实现。

二. 加同步的单例

加同步的单例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public class Singleton {

      private static Singleton instance = null;
  
      private Singleton() {
      }
  
      public synchronized static Singleton getInstance() {
          if (instance == null) {
              instance = new Singleton();
          }
          return instance;
      }
  }

这种方式在每次获取对象的时候都要先获取锁,如果多次获取对象的话,会造成一些性能开销。考虑到只有在第一次创建对象时才存在并发问题,于是便有了双重判断的实现方式。

三. 双重判断的同步的单例

双重判断的同步的单例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 public class Singleton {

      private static volatile Singleton instance = null;

      private Singleton() {
      }

      public static Singleton getInstance() {
          if (instance == null) {
              synchronized(Singleton.class){
                  if(instance == null)
                      instance = new Singleton();
              }

          }
          return instance;
      }
    }

java的同步有很多陷阱,考虑到JMM的指令重排问题,instance被声明为volatile,这能够避免一部分问题,但是仍然会有一些并发的陷阱,比如CPU内部流水线也会做些指令的重排,这可不是受JVM指令控制的。如果我们创建一个非常大的单例对象,有可能会出现这种小概率事件。于是,干脆将同步问题扼杀在摇篮里。

四. 典型饥饿模式的单例

典型饥饿模式的单例
1
2
3
4
5
6
7
8
9
10
11
 public class Singleton {

      private static Singleton instance = new Singleton();

      private Singleton() {
      }

      public static Singleton getInstance() {
          return instance;
      }
  }

JVM在对类做初始化时,会做同步处理,以保证一个类只被初始化一次。一般,饥饿模式的单例已经能满足大多数的需求,如果你非常渴望延迟加载,而又不想自己去做同步的话。可以试试第5种方式。

五. 非同步延迟单例

非同步延迟单例
1
2
3
4
5
6
7
8
9
10
11
12
13
 public class Singleton {

      private static class SingletonHolder{
          static Singleton instance = new Singleton();
      }

      private Singleton() {
      }

      public static Singleton getInstance() {
          return SingletonHolder.instance;
      }
  }

这种方式利用JVM初始化的机制来达到延迟加载的目的,个人比较喜欢这种单例实现。不过具体实现的时候还是可能会有各种问题。比如构造类的时候可能出现异常,或者在初始化的时候出现死锁等问题。 最近看到有人用枚举来实现单例,也挺巧妙的。

六. 枚举单例

枚举单例
1
2
3
4
5
6
7
 enum Singleton {
        INSTANCE;

        public static Singleton getInstance(){
            return INSTANCE;
        }
  }

觉得这种方式比较容易引起歧义,没太想好它的应用场景。不过保证单例是没啥问题。

最近看python的一些设计模式,看到一些观点,认为其实各种单例的实现方式或多或少都有些问题,主张大家少用单例。如果要达到单例的效果,可以把对象提前构造出来,弄成一个类似全局变量的东东来用。个人还是比较赞同的,纯天然的总比再加工的更让人放心点。

参考资料

http://www.blogjava.net/xylz/archive/2009/12/18/306622.html

DBCP源码分析

| Comments

Why 连接池

一般我们进行一个数据库操作时,都要进行下面的步骤

  1. 客户端与服务器端建立连接
  2. 执行数据库操作
  3. 释放连接

频繁的数据库的连接和释放会占用大量的时间和资源,于是就有必要重复利用数据库连接,这便要用到连接池技术。

DBCP的使用和配置

DBCP的使用

一个简单的使用示例,但是代码还是有点长,这里放个传送门,有兴趣的可以点进去看看。 DBCPDemo

DBCP的配置

配置信息看这里把,传送门DBCP Configuration

DBCP源码分析

DBCP其实就是一个存储数了据库连接的Object Pool,Object Pool是利用了commons-pool实现的。下面从BasicDataSource开始逐步分析DBCP的代码。 BasicDataSource类结构图 从上图可以看出,BasicDataSource可以看成是一个Adapter模式的实现,其封装了真正实现连接池pool的PoolingDataSource,而PoolingDataSource实现了获 取数据库连接的getConnection方法。

getConnection
1
2
3
4
5
 Connection conn = (Connection)(_pool.borrowObject());
    if (conn != null) {
      conn = new PoolGuardConnectionWrapper(conn);
    }
    return conn;

_pool就是ObjectPool,其实现是GenericObjectPool,这就是连接池的核心,真正实现Object Pool的地方。PoolGuardConnectionWrapper对Connection做了简单封装,如果通过该连接对数据库进行操作时,连接已经关闭,就会抛出异常。

下面我们重点分析GenericObjectPool的代码,GenericObjectPool的类结构图如下图所示。 GenericObjectPool类结构图

GenericObjectPool有三个内部类,分别是Config,Evictor和Latch.Config类包含了各种默认配置信息,如maxActive,maxWait(单位毫秒)等。Evictor类是清道夫,对于pool里过期的Idle对象会进行清理。Latch封装了真实的对象,这里为什么要对真实的对象进行封装,主要是拿它用来排队的,以保证请求的公平性,先来先拿。PoolableObjectFactory是生成对象的工厂接口,在使用pool前需要将其实现(这里是PoolableConnectionFactory)赋给pool的_factory。

GenericObjectPool主要的接口有两个,分别是borrowObject和returnObject。先看下borrowObject的逻辑,代码太长。这里只贴一些主要的代码,有兴趣的可以自己去看。

再看下returnObject,逻辑简单了好多。

话说DBCP和common-pool的代码好老,最近看了下bonecp,据说比DBCP快了30被,以后分析下他的代码。

Python程序打包成exe

| Comments

帮朋友用wxpython写了一个小程序,为了方便他使用,需要打包成exe。记得py2exe可以,看了下它的文档,写了一个简单的打包程序setup.py。

setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import sys
from distutils.core import setup
from glob import glob
import py2exe

sys.path.append("C:/Program Files/Microsoft \
Visual Studio 10.0/VC/redist/x86/Microsoft.VC100.CRT")
data_files = [("Microsoft.VC100.CRT", glob(r'C:/Program Files/Microsoft \
Visual Studio 10.0/VC/redist/x86/Microsoft.VC100.CRT/*.*'))]

setup(
      data_files=data_files,
      console=["xxx.py"]
      )

我的python是2.7版本的,其他版本的打包程序可能具体还有些不同。打包的时候需要使用VC来编译,所以需要预装VC2008以上的版本,我装的是VC2010.运行程序

python setup.py py2exe

就会生成一个dist的目录,里面就有生成的exe文件和一大堆的pyd,dll,以及一些VC的运行时库文件。文件很多,py2exe有些参数,可以对文件数进行压缩。具体参数大家可以看文档。

参考资料

java版Berkeley Db安装

| Comments

下载源码包db-4.5.20.tar.gz 执行下面的命令,编译源码

tar -xzf db-4.5.20.tar.gz
cd db-4.5.20/build_unix
../dist/configure --prefix=/opt/apps/berkeleydb --enable-java
make && make install

将动态库加到系统查找路径

echo ‘/usr/local/berkeleydb/lib/’ >> /etc/ld.so.conf
ldconfig

或者

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/apps/berkeleydb/lib

顺便提下windows下的安装 下载db-4.5.20.msi,安装。 将安装目录下的bin/libdb_java45.dll,bin/libdb45.dll和bin/msvcp71.dll拷贝到系统的system32目录下。 db.jar是java的接口类库,可以通过他来访问dbd

参考资料

Jnotify

| Comments

eclipse装了aptana,结果报

JNotifyAdapterLinux.registerToSubTree : warning, failed to register /opt/workspace/django/django/contrib/localflavor/locale/ar/.svn/tmp/prop-base :Error watching /opt/workspace/django/django/contrib/localflavor/locale/ar/.svn/tmp/prop-base : No space left on device

查了下,aptana使用了jnotify,而jnotify使inotify的java封装,inotify对每个进程能够观察的文件数使是有限制的。可以把限制加大一些来解决这个问题。

su
echo 32000 > /proc/sys/fs/inotify/max_user_watches

顺便发掘了下jnotify,对文件的增删改等事件进行监听的java库,使用也很简单。

参考文档

硬盘安装ubuntu11.04

| Comments

每次重装系统,都要查一堆的文章,常用的几个命令以及一些常见的问题就是记不住。实在有必要写一下备忘了。

现有的系统winxp, win7,要装的系统是ubuntu 11.04.

Ubuntu Install

| Comments

重装了ubuntu,这里记录下软件的安装过程 安装的是ubuntu 11.04,装好后提示升级,于是升级到11.10。话说oneiric变化还是满大的,使用了新的unity界面,而且不能切换回旧的gnome3的界面,登录界面也从GDM换成了LightDM。刚开始使用起来还是有些不习惯。

  1. 更新软件源 之前用的一直是官方默认的源。这次想专门测试下各种源的速度,于是想安装apt-spy。
     sudo apt-get install apt-spy 
    
    提示找不到软件。折腾了半天没有找到安装方法,遂作罢,弄了163的源,修改/etc/apt/sources.list。更新源
     sudo apt-get update
    
  2. 升级软件
     sudo apt-get upgrade
    
  3. 安装chrome
     wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add
     sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' 
     sudo apt-get update  
     sudo apt-get install google-chrome-stable
    
  4. 安装flash,MP3解码。。。
     sudo apt-get install ubuntu-restricted-extras
    
  5. 安装7z
     sudo apt-get install p7zip-full p7zip-rar
    
  6. 安装synergy synergy可以使用一套键盘鼠标来控制多台机器。
     sudo apt-get install synergy 
    

    安装好后要修改下/etc/lightdm/lightdm.conf,在最后加上greeter-setup-script=/usr/bin/synergyc {ip}。以上是synergy作为客户端的配置,如果作为服务器端的话,可能要稍微麻烦些。

  7. 安装tsokc
     sudo apt-get install tsocks
    
    对于某些只能用http代理的应用,可以用他帮忙把socks的代理转一下。

    参考文档