lizongbo at 618119.com 工作,生活,Android,前端,Linode,Ubuntu,nginx,java,apache,tomcat,Resin,mina,Hessian,XMPP,RPC

2008年03月8日

慎用ByteBuffer.allocateDirect

Filed under: Java — 标签:, , — lizongbo @ 14:06

Apache MINA 2.0.0-M1 试用体会 里我提到了使用 org.apache.mina.transport.socket.apr.AprSocketAcceptor

代替 org.apache.mina.transport.socket.nio.NioSocketAcceptor 遇到的问题,

后来在 AprIoProcessor的 protected int read(AprSession session, IoBuffer buffer) 和

protected int write(AprSession session, IoBuffer buf, int length)方法里加上了System.out,然后瞎改代码,

后面终于看到错误码为:-120002 和-730054,在网上google一番,也没有头绪,后面静下心来,增加对IoBuffer的方法调用,

慢慢摸索。

联想到前面ProtocolDecoder所犯下用把while用成if的错误,想想这么容易出现问题的话,应该不是bug,Trustin Lee 这样的牛人不可能留下这么大的bug就发布 Apache MINA 2.0.0-M1。

通过多次定位,终于发现了问题所在,

我在 ProtocolEncoder的 public void encode(IoSession session, Object message,
ProtocolEncoderOutput out)里面写了

IoBuffer buf = IoBuffer.allocate(16, true);

这行代码最终调用的是ByteBuffer.allocateDirect这个方法:

参考:

http://gceclub.sun.com.cn/Java_Docs/jdk6/html/zh_CN/api/java/nio/ByteBuffer.html#allocateDirect(int)

先前瞎迷信自以为 直接字节缓冲区 的性能会好些,而且先前使用IoBuffer.allocate(16, true);时就曾经遇到过服务端返回的内容不对头的问题,可惜当时没在意,就半罐子水折腾。

再仔细阅读 javaDoc里的说明:

直接 非直接缓冲区

字节缓冲区要么是直接的,要么是非直接的。如果为直接字节缓冲区,则 Java 虚拟机会尽最大努力直接在此缓冲区上执行本机 I/O 操作。也就是说,在每次调用基础操作系统的一个本机 I/O 操作之前(或之后),虚拟机都会尽量避免将缓冲区的内容复制到中间缓冲区中(或从中间缓冲区中复制内容)。

直接字节缓冲区可以通过调用此类的 allocateDirect 工厂方法来创建。此方法返回的缓冲区进行分配和取消分配所需成本通常高于非直接缓冲区。直接缓冲区的内容可以驻留在常规的垃圾回收堆之外,因此,它们对应 用程序的内存需求量造成的影响可能并不明显。所以,建议将直接缓冲区主要分配给那些易受基础系统的本机 I/O 操作影响的大型、持久的缓冲区。一般情况下,最好仅在直接缓冲区能在程序性能方面带来明显好处时分配它们。

allocateDirect

public static ByteBuffer allocateDirect(int capacity)
分配新的直接字节缓冲区。 新缓冲区的位置将为零,其界限将为其容量,其标记是不确定的。无论它是否具有底层实现数组,其标记都是不确定的。
参数:
capacity – 新缓冲区的容量,以字节为单位
返回:
新的字节缓冲区
抛出:
IllegalArgumentException – 如果 capacity 为负整数

再看相关代码:

ByteBuffer 的代码节选:

[code]

public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}

[/code]

DirectByteBuffer 的代码节选:

[code]

DirectByteBuffer(int cap) { // package-private

super(-1, 0, cap, cap, false);
Bits.reserveMemory(cap);
int ps = Bits.pageSize();
long base = 0;
try {
base = unsafe.allocateMemory(cap + ps);
} catch (OutOfMemoryError x) {
Bits.unreserveMemory(cap);
throw x;
}
unsafe.setMemory(base, cap + ps, (byte) 0);
if (base % ps != 0) {
// Round up to page boundary
address = base + ps – (base & (ps – 1));
} else {
address = base;
}
cleaner = Cleaner.create(this, new Deallocator(base, cap));

}

private Deallocator(long address, int capacity) {
assert (address != 0);
this.address = address;
this.capacity = capacity;
}

public void run() {
if (address == 0) {
// Paranoia
return;
}
unsafe.freeMemory(address);
address = 0;
Bits.unreserveMemory(capacity);
}

}

[/code]

可以看到java使用的是本地方法在管理相对应的内存:
public native long allocateMemory(long _long);
public native void setMemory(long _long, long _long1, byte _byte);
public native void copyMemory(long _long, long _long1, long _long2);
public native void freeMemory(long _long);

而Apr也是使用本地方法管理内存,可能这里目前存在一些没处理好的地方,因此导致了我遇到的问题。,

避免这个问题的办法就很简单了

direct使用false,即 ProtocolEncoder 中使用 IoBuffer buf = IoBuffer.allocate(16, false);。

当然 AprIoProcessor,的write方法已经做了buf.isDirect() 这样的判断,按理说是可以使用DirectByteBuffer的,

在没有完全明白其中缘由前,暂时先慎用ByteBuffer.allocateDirect以避免产生问题。

2007年10月23日

tomcat启用apr的情况下使用非自签名证书进行ssl双向认证配置

Filed under: Tomcat — 标签:, , , , , — lizongbo @ 08:47

Tomcat的apr组件是使用JNI用来提升Tomcat的系统性能,在启用apr特性之后,Tomcat的 https功能不能使用JSSE的证书配置,
而需要使用OpenSSL,对于clientAuth的双向认证配置,也与一般方式不同,经过试验,摸索出配置步骤如下:

证书文件的制作步骤如下:

下载并安装openvpn,然后在
C:\Program Files\OpenVPN\easy-rsa下根据readme指导的步骤生成根证书,服务器证书(非自签名证书),客户端证书.

我的具体步骤:
1.命令行下进入 C:\Program Files\OpenVPN\easy-rsa
首先运行init-config.bat
当前目录下会生成openssl.cnf和vars.bat
2.编辑vars,bat,修改以下变量,保存文件.
set KEY_SIZE=2048
set KEY_COUNTRY=CN
set KEY_PROVINCE=GD
set KEY_CITY=ShenZhen
set KEY_ORG=zongbo.Inc
set KEY_EMAIL=lizongbo@618119.com

3.命令行下运行
vars.bat
clean-all
4.创建ca证书
1. vars
2. build-ca
5.创建服务器公匙密码
(由于KEY_SIZE设置成了2048,因此可能需要很长的是时间才能创建,此时可以改回1024)
1. vars
2. build-dh

6.创建服务器证书和key.
1. vars
2. build-key-server www

7.创建客户端证书(创建可导入的格式)
1. vars
2. build-key-pkcs12 lizongbo

以下是整个命令执行的过程

C:\Program Files\OpenVPN\easy-rsa>init-config

C:\Program Files\OpenVPN\easy-rsa>copy vars.bat.sample vars.bat
已复制 1 个文件。

C:\Program Files\OpenVPN\easy-rsa>copy openssl.cnf.sample openssl.cnf
已复制 1 个文件。

C:\Program Files\OpenVPN\easy-rsa>vars.bat

C:\Program Files\OpenVPN\easy-rsa>clean-all
系统找不到指定的文件。
已复制 1 个文件。
已复制 1 个文件。

C:\Program Files\OpenVPN\easy-rsa>vars

C:\Program Files\OpenVPN\easy-rsa>build-ca
Loading ‘screen’ into random state – done
Generating a 2048 bit RSA private key
…………………………………..+++
……………………………………………………………………..
……………………………………………………………………..
…………………….+++
writing new private key to ‘keys\ca.key’
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [CN]:CN
State or Province Name (full name) [GD]:GD
Locality Name (eg, city) [ShenZhen]:ShenZhen
Organization Name (eg, company) [zongbo.Inc]:zongbo.Inc
Organizational Unit Name (eg, section) []:lzb.Inc
Common Name (eg, your name or your server’s hostname) []:ca.lizongbo.com
Email Address [lizongbo@618119.com]:lizongbo@618119.com

C:\Program Files\OpenVPN\easy-rsa>vars

C:\Program Files\OpenVPN\easy-rsa>build-dh
Loading ‘screen’ into random state – done
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
………………………………………………..+……………..+…..
……………………………………………………………..+……..
……………………………………………………………………..
………………….+…………………………………………………
……………………………………………………………………..
……………………………………………………………………..
…………………..+…………………………………………..+…..
…………………………………+………………………..+……….
……………………………………………………………..+……..
………………………………………………………….+…………
………………………….+…………………………………………
……………………………………………………………+……….
……………………………………………………………………..
…+…………………………………+………..+……………………
………………………………+…………………………………….
……………………………………………………………………..
.+………………………………………………………………+…..
……………………………………………………………………..
………………………………………………………….+…………
…………………………………………
C:\Program Files\OpenVPN\easy-rsa>vars

C:\Program Files\OpenVPN\easy-rsa>build-key-server www
Loading ‘screen’ into random state – done
Generating a 2048 bit RSA private key
……….+++
…………………………….+++
writing new private key to ‘keys\www.key
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [CN]:CN
State or Province Name (full name) [GD]:GD
Locality Name (eg, city) [ShenZhen]:ShenZhen
Organization Name (eg, company) [zongbo.Inc]:zongbo.Inc
Organizational Unit Name (eg, section) []:lzb.Inc
Common Name (eg, your name or your server’s hostname) []:www.618119.com
Email Address [lizongbo@618119.com]:lizongbo@618119.com

Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:lizongbo
An optional company name []:lzb.cmp
Using configuration from openssl.cnf
Loading ‘screen’ into random state – done
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName :PRINTABLE:’CN’
stateOrProvinceName :PRINTABLE:’GD’
localityName :PRINTABLE:’ShenZhen’
organizationName :PRINTABLE:’zongbo.Inc’
organizationalUnitName:PRINTABLE:’lzb.Inc’
commonName :PRINTABLE:’www.618119.com
emailAddress :IA5STRING:’lizongbo@618119.com
Certificate is to be certified until Sep 17 02:27:21 2017 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

C:\Program Files\OpenVPN\easy-rsa>vars

C:\Program Files\OpenVPN\easy-rsa>build-key lizongbo
Loading ‘screen’ into random state – done
Generating a 2048 bit RSA private key
……………+++
……………………+++
writing new private key to ‘keys\lizongbo.key’
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [CN]:CN
State or Province Name (full name) [GD]:GD
Locality Name (eg, city) [ShenZhen]:ShenZhen
Organization Name (eg, company) [zongbo.Inc]:zongbo.Inc
Organizational Unit Name (eg, section) []:lzb.Inc
Common Name (eg, your name or your server’s hostname) []:lizongbo
Email Address [lizongbo@618119.com]:lizongbo@618119.com

Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:lizongbo
An optional company name []:lzb.cmp
Using configuration from openssl.cnf
Loading ‘screen’ into random state – done
DEBUG[load_index]: unique_subject = “yes”
Check that the request matches the signature
Signature ok
The Subject’s Distinguished Name is as follows
countryName :PRINTABLE:’CN’
stateOrProvinceName :PRINTABLE:’GD’
localityName :PRINTABLE:’ShenZhen’
organizationName :PRINTABLE:’zongbo.Inc’
organizationalUnitName:PRINTABLE:’lzb.Inc’
commonName :PRINTABLE:’lizongbo’
emailAddress :IA5STRING:’lizongbo@618119.com
Certificate is to be certified until Sep 17 02:28:38 2017 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

C:\Program Files\OpenVPN\easy-rsa>

证书文件的安装步骤如下:

在IE中 :
在资源管理其中,双击easy-rsa\keys\ca.crt,导入根证书.双击www.crt,导入服务器证书,双击lizongbo.p12,导入客户端证书.

在Firefox中:

主菜单–>工具–>选项–>加密,察看证书–>证书机构->导入,选择ca.crt,导入之后,选中刚导入的证书,然后点”编辑”,将三项新任设置全部打上钩.

切换面板到”web站点”,导入,选择www.crt,导入之后,选中刚导入的证书,然后点”编辑”,选择”信任此证书的认证”

切换到”您的证书”,导入,选择lizongbo.p12, 输入生成证书时设置的密码,导入成功.
(Firefox中如果不首先导入根证书,Firefox会提示-12227错误,”接收到错误或未期望的消息,错误号-12227 “, 与IE的表现不同)
(more…)

Powered by WordPress