Feb 23

JVM内存模型以及垃圾收集策略解析

 

 一 JVM内存模型

1.1 Java栈

Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程。它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文。栈空间随着线程的终止而释放。

StackOverflowError:如果在线程执行的过程中,栈空间不够用,那么JVM就会抛出此异常,这种情况一般是死递归造成的。 Continue reading

Dec 29

Java JNI学习

    07年的时候就用过JNI这东西了,那时候是为了给项目的J2EE应用写一个授权功能,通过调用vc写的读取硬件id的dll使得cdkey能够跟机器一一对应起来,从而做到控制一个cdkey只能装到一台机器上上。那会儿用的dll是别人写的,java中调用dll也是用的小日本儿写的一个叫jcom的组件,这次决定自己做一遍整个流程.

  1. 编写java文件
    /**
     * Copyright (C), 2009-2010
     * File Name: jni.WinMessage.java
     * Encoding UTF-8
     * Version: 1.0
     * Date: Dec 29, 2009
     * History:	
     */
    package jni;
    
    /**
     *
     * @author (bestirwiny@gmail.com)
     * @version Revision: 1.00 2:12:24 PM
     */
    public class WinMessage
    {
    	static{
    		System.loadLibrary("WinMsgDll");
    	}
    	public native void showMsgBox(String msg);
    }
    

    loadLibrary用于load一个dll,该dll应该在java.library.path定义的路径下啊。

  2. 用javac编译该文件,不用讲。
  3. javah -jni WinMessage,会生成一个jni_WinMessage.h的头文件,下面要做的工作就是dll的编写了。
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include "jni.h"
    /* Header for class jni_WinMessage */
    
    #ifndef _Included_jni_WinMessage
    #define _Included_jni_WinMessage
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     jni_WinMessage
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_jni_WinMessage_showMsgBox
      (JNIEnv *, jobject, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    
  4. 创建一个win32动态连接库的工程,将$JAVAHOME/include,$JAVA_HOME/include/win32目录加入到工程需要引用的头文件路径中。
    #include "tchar.h"
    #include "stdlib.h"
    #include "stdio.h"
    #include "AtlBase.h"
    #include "AtlConv.h"
    #include "windows.h"
    #include "jni_WinMessage.h"
    
    /*
     * Class:    
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_jni_WinMessage_showMsgBox
      (JNIEnv * env, jobject jobj, jstring str){
    	const char * msg;
    	msg = env->GetStringUTFChars(str,0);
    
    	WCHAR* strA;
        int i= MultiByteToWideChar ( CP_UTF8 , 0 ,msg ,-1 ,NULL,0);
    	strA = new WCHAR[i];
    	MultiByteToWideChar ( CP_UTF8 , 0 ,( char * ) msg, -1, strA , i );
    
    	USES_CONVERSION;
    	MessageBox(NULL,strA,_T("Java invoke "),MB_OK);
    	env->ReleaseStringUTFChars(str,msg);
    }
    

    由于win32变成才开始学,所以这个东西弄了好久才弄好,网上的例子中通过GetStringUTFChars取回的msg直接传到MessageBox中用,可我用的是VS2008,直接用会报错误,大致是说不能将const char *转换为LPCWSTR * ,
    LPCWSTR是long pointer constant wide string的意思,是一种wchar_t类型,char类型占用一个byte,而wchar_t占用两个byte,所以这边就要用一个转换 函数,网上查好久才查到MutiByteToWideChar函数,才解决了中文乱码的问题。

  5. 编译完会成成一个dll文件,拷贝到java.library.path下,我是拷贝到了c:\windows下。
  6. 编写一个java类调用上面的WinMessage
    /**
     * Copyright (C), 2009-2010
     * File Name: jni.TestWinMessage.java
     * Encoding UTF-8
     * Version: 1.0
     * Date: Dec 29, 2009
     * History:	
     */
    package jni;
    
    /**
     *
     * @author (bestirwiny@gmail.com)
     * @version Revision: 1.00 4:54:25 PM
     */
    public class TestWinMessage
    {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args)
    	{
    		WinMessage wm = new WinMessage();
    		wm.showMsgBox("MC Hotdog,哈狗帮!");
    	}
    }
    
  7. ok,这下就完成了从java程序中调用win32 API弹出windows原生的窗口了 。
Dec 29

VC++ Data Type Ranges

 

Type Name

Bytes

Other Names

Range of Values

int

4

signed

–2,147,483,648 to 2,147,483,647

unsigned int

4

unsigned

0 to 4,294,967,295

__int8

1

char

–128 to 127

unsigned __int8

1

unsigned char

0 to 255

__int16

2

short, short int, signed short int

–32,768 to 32,767

unsigned __int16

2

unsigned short, unsigned short int

0 to 65,535

__int32

4

signed, signed int, int

–2,147,483,648 to 2,147,483,647

unsigned __int32

4

unsigned, unsigned int

0 to 4,294,967,295

__int64

8

long long, signed long long

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

unsigned __int64

8

unsigned long long

0 to 18,446,744,073,709,551,615

bool

1

none

false or true

char

1

none

–128 to 127 by default

0 to 255 when compiled with /J

signed char

1

none

–128 to 127

unsigned char

1

none

0 to 255

short

2

short int, signed short int

–32,768 to 32,767

unsigned short

2

unsigned short int

0 to 65,535

long

4

long int, signed long int

–2,147,483,648 to 2,147,483,647

unsigned long

4

unsigned long int

0 to 4,294,967,295

long long

8

none (but equivalent to __int64)

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

unsigned long long

8

none (but equivalent to unsigned __int64)

0 to 18,446,744,073,709,551,615

enum

varies

none

See Remarks.

float

4

none

3.4E +/- 38 (7 digits)

double

8

none

1.7E +/- 308 (15 digits)

long double

same as double

none

same as double

wchar_t

2

__wchar_t

0 to 65,535

 

 

从MSDN上看到,截取下来以备后用。

 

 

Dec 15

linux多线程编程

1 引言

  线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux。

Continue reading

Dec 15

Mutex vs. Semaphore

Mutex:

Is a key to a toilet. One person can have the key – occupy the toilet – at the time. When finished, the person gives (frees) the key to the next person in the queue.

Officially: "Mutexes are typically used to serialise access to a section of  re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section."
Ref: Symbian Developer Library

Semaphore:

Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count – the count of keys – is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue.

Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)."
 

Dec 10

NSIS制作B/S架构安装程序

    开门见山,B/S架构应用程序的安装程序无非就是拷贝一些文件,检查一下环境配置,注册服务,启动服务之类的了。拷贝文件就没什么好说的了。下面着记录一下如下几点:

  1. 端口检查
  2. 读写注册表
  3. 调用外部可执行文件
  4. 注册、启动、停止服务
  5. 注册环境变量

Continue reading

Dec 09

Tomcat6.1X配置详解

 1.         配置应用的方式有两种:1)在host下配置context。2)在$CATALINA_HOME/conf/[enginename]/[hostname]下新建一个应用描述文件,其中描述Context。

2.         配置完全局JNDI资源需要在Context.xml中做资源连接
<ResourceLink name="jdbc/mysql"   global="jdbc/mysql "   type="javax.sql.DataSource"/>
 
3.         Host中配置的虚拟主机目录下,默认目录为ROOT(区分大小写)。
Dec 01

blog终于又重新上线了

    前天偶然访问了下自己的blog,发现主机被停域名被抢注,杯具…. 郁闷了好久。今天碰见阿清,找他弄了个空间跟二级域名算是又重新把blog弄起来了,把wordpress的默认编辑器换成老李弄的fckeditor插件了,用起来比wordpress自带的happy多了。

    武汉的生活节奏比厦门还是要紧凑些,今天看了下之前的blog,回来后都很少写blog了,几个月都写不到一篇,一方面是没有心情,一方面是没有时间。有时候偶尔看看以前记录的些东西感觉还是蛮好的,也算是对自己的生活的一个记录,以后还是得勤更新下blog。

Jun 11

Java HeapSpace OutOfMemory一例分析

        这两天经常听到同事说我们的系统运行一两个小时过后就会报Java HeapSpace OutOfMemory的异常,一开始我还没怎么在意这个问题,还以为是在eclipse中用debug状态运行tomcat导致的,后来又出现了几次,觉得事情有点儿不对了,检查了我的代码,基本没有什么地方会出现内存泄漏,该释放资源的地方也都释放了。一开始懒得去看同事的代码,就找了jconsole工具来分析,这不看不知道,一看才吓了一跳。查看内存占用发现大致每隔两分钟左右内存就会有一个飙升,线程数跟内存占用一样每当内存波动的时候线程数就有一个飙升,而且一上去了就不下来,查看具体的线程堆栈,发现增加的线程全部是一个snmp4j中的一个类型。这一块恰好是我那同事实现的,于是没办法只有看看他的代码了(貌似搞开发的都不愿意看别个的代码…). 在我们的系统中有一个轮询操作,在这个轮询操作中会使用到snmp4j api,查看snmp4j api发现用到的一个类中会持有socket资源并创建内部线程,这个socket会中断在那块儿,而俺那同事的实现是在每次轮询的时候都会新建一个该对象,而且在使用过后也没有close掉。查看snmp4j的源码发现该类的内部实现是有从一个内部线程池中取得一个线程,然后在该线程中用到socket,于是由于线程中的socket为关闭一直阻塞,这条新建的线程 也就没办法释放了。问题就算是找到了,下面的解决办法就很容易了,将这个地方实现为一个单例模式,最后测试的结果也很好,运行三四个小时,线程数始终保持在估计的范围内。

等有时间了,再好好写一篇jconsole的使用方法,发现这玩意儿还挺好玩儿的。