一 JVM内存模型
1.1 Java栈
Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程。它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文。栈空间随着线程的终止而释放。
StackOverflowError:如果在线程执行的过程中,栈空间不够用,那么JVM就会抛出此异常,这种情况一般是死递归造成的。 Continue reading
一 JVM内存模型
Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程。它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文。栈空间随着线程的终止而释放。
StackOverflowError:如果在线程执行的过程中,栈空间不够用,那么JVM就会抛出此异常,这种情况一般是死递归造成的。 Continue reading
下面是Java Collections Framework的类图,没有将current包底下的内容加入。 Continue reading
07年的时候就用过JNI这东西了,那时候是为了给项目的J2EE应用写一个授权功能,通过调用vc写的读取硬件id的dll使得cdkey能够跟机器一一对应起来,从而做到控制一个cdkey只能装到一台机器上上。那会儿用的dll是别人写的,java中调用dll也是用的小日本儿写的一个叫jcom的组件,这次决定自己做一遍整个流程.
/** * 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定义的路径下啊。
/* 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
#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函数,才解决了中文乱码的问题。
/** * 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,哈狗帮!"); } }
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上看到,截取下来以备后用。
1 引言
线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux。
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)."
开门见山,B/S架构应用程序的安装程序无非就是拷贝一些文件,检查一下环境配置,注册服务,启动服务之类的了。拷贝文件就没什么好说的了。下面着记录一下如下几点:
1. 配置应用的方式有两种:1)在host下配置context。2)在$CATALINA_HOME/conf/[enginename]/[hostname]下新建一个应用描述文件,其中描述Context。
前天偶然访问了下自己的blog,发现主机被停域名被抢注,杯具…. 郁闷了好久。今天碰见阿清,找他弄了个空间跟二级域名算是又重新把blog弄起来了,把wordpress的默认编辑器换成老李弄的fckeditor插件了,用起来比wordpress自带的happy多了。
武汉的生活节奏比厦门还是要紧凑些,今天看了下之前的blog,回来后都很少写blog了,几个月都写不到一篇,一方面是没有心情,一方面是没有时间。有时候偶尔看看以前记录的些东西感觉还是蛮好的,也算是对自己的生活的一个记录,以后还是得勤更新下blog。
这两天经常听到同事说我们的系统运行一两个小时过后就会报Java HeapSpace OutOfMemory的异常,一开始我还没怎么在意这个问题,还以为是在eclipse中用debug状态运行tomcat导致的,后来又出现了几次,觉得事情有点儿不对了,检查了我的代码,基本没有什么地方会出现内存泄漏,该释放资源的地方也都释放了。一开始懒得去看同事的代码,就找了jconsole工具来分析,这不看不知道,一看才吓了一跳。查看内存占用发现大致每隔两分钟左右内存就会有一个飙升,线程数跟内存占用一样每当内存波动的时候线程数就有一个飙升,而且一上去了就不下来,查看具体的线程堆栈,发现增加的线程全部是一个snmp4j中的一个类型。这一块恰好是我那同事实现的,于是没办法只有看看他的代码了(貌似搞开发的都不愿意看别个的代码…). 在我们的系统中有一个轮询操作,在这个轮询操作中会使用到snmp4j api,查看snmp4j api发现用到的一个类中会持有socket资源并创建内部线程,这个socket会中断在那块儿,而俺那同事的实现是在每次轮询的时候都会新建一个该对象,而且在使用过后也没有close掉。查看snmp4j的源码发现该类的内部实现是有从一个内部线程池中取得一个线程,然后在该线程中用到socket,于是由于线程中的socket为关闭一直阻塞,这条新建的线程 也就没办法释放了。问题就算是找到了,下面的解决办法就很容易了,将这个地方实现为一个单例模式,最后测试的结果也很好,运行三四个小时,线程数始终保持在估计的范围内。
等有时间了,再好好写一篇jconsole的使用方法,发现这玩意儿还挺好玩儿的。