Changing proxy settings of IE is a frequent requirement of mine. Then I got the idea of writing a tool by myself, at last. I have not found clear instructions on this. Many articles recommend to modify registry directly, but unfortunately their instruction is not enough. Most of them direct me to modify the following values in registry :-
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings]
"ProxyEnable"=dword:00000001
"ProxyServer"=":"
"ProxyOverride"=""
"DisablePasswordCaching"=dword:00000001
I tested it and find that it does not work at least on my computer.( I access internet by ADSL connection.) So I backed up registry and modified proxy settings via Internet Explorer, finding that [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections] is also changed. So I wrote the following code snippet to change proxy settings:
void ShowError(long lerr) { LPVOID lpMsgBuf; if (!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lerr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL )) { return; } MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); LocalFree( lpMsgBuf ); } void CieproxyDlg::OnBnClickedOk() {//set proxy server UpdateData(); GetDlgItemText(IDC_EDIT1,m_sIEProxy); HKEY hk; LONG lret=RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", NULL,KEY_WRITE|KEY_SET_VALUE,&hk); if(lret==ERROR_SUCCESS&&NULL!=hk) { TCHAR* pbuf=m_sIEProxy.GetBuffer(1); lret=RegSetValueEx( hk,"ProxyServer",NULL,REG_SZ,pbuf,m_sIEProxy.GetLength()); DWORD dwenable=1; lret=RegSetValueEx(hk,"ProxyEnable",NULL,REG_DWORD, (LPBYTE)&dwenable,sizeof(dwenable)); RegCloseKey(hk); } const TCHAR* keyname3=_T( "software\\Microsoft\\windows\\currentversion\\Internet Settings\\Connections"); lret=RegOpenKeyEx(HKEY_CURRENT_USER,keyname3,NULL, KEY_READ|KEY_WRITE|KEY_SET_VALUE,&hk); if(lret==ERROR_SUCCESS&&NULL!=hk) { DWORD dwtype; char pbuf[256]; DWORD dwlen=sizeof(pbuf); constchar* valname="Connection to adsl3"; lret=RegQueryValueEx(hk,valname,NULL,&dwtype,pbuf,&dwlen); if(lret!=ERROR_SUCCESS) { ShowError(lret); } pbuf[8] = 3;//enable proxy pbuf[4]=pbuf[4]+1; constchar* p=m_sIEProxy.GetBuffer(1); memcpy(pbuf+16,p,m_sIEProxy.GetLength()); char c=0; for(int i=m_sIEProxy.GetLength();i<20;i++) pbuf[16+i]=c; m_sIEProxy.ReleaseBuffer(); lret=RegSetValueEx(hk,valname,NULL,REG_BINARY,pbuf,dwlen); RegCloseKey(hk); } DWORD dwret; SendMessageTimeout(HWND_BROADCAST,WM_SETTINGCHANGE,NULL,NULL, SMTO_NORMAL,1000,&dwret); } void CieproxyDlg::OnBnClickedDisableProxy() { UpdateData(); GetDlgItemText(IDC_EDIT1,m_sIEProxy); HKEY hk; LONG lret=RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", NULL,KEY_WRITE|KEY_SET_VALUE,&hk); if(lret==ERROR_SUCCESS&&NULL!=hk) { DWORD dwenable=0; lret=RegSetValueEx(hk,"ProxyEnable",NULL,REG_DWORD, (LPBYTE)&dwenable,sizeof(dwenable)); RegCloseKey(hk); } const TCHAR* keyname3=_T( "software\\Microsoft\\windows\\currentversion\\Internet Settings\\Connections"); lret=RegOpenKeyEx(HKEY_CURRENT_USER,keyname3, NULL,KEY_READ|KEY_WRITE|KEY_SET_VALUE,&hk); if(lret==ERROR_SUCCESS&&NULL!=hk) { DWORD dwtype; char pbuf[256]; DWORD dwlen=sizeof(pbuf); constchar* valname="Connection to adsl3"; lret=RegQueryValueEx(hk,valname,NULL,&dwtype,pbuf,&dwlen); if(lret!=ERROR_SUCCESS) { ShowError(lret); } pbuf[8] = 1;//enable proxy pbuf[4]=pbuf[4]+1; lret=RegSetValueEx(hk,valname,NULL,REG_BINARY,pbuf,dwlen); RegCloseKey(hk); } DWORD dwret; SendMessageTimeout(HWND_BROADCAST,WM_SETTINGCHANGE,NULL,NULL,SMTO_NORMAL, 1000,&dwret); }
Problem with above code is that existing Internet Explorer instances don't know the change of settings. What is more, changing registry directly is not an elegant method. Then the following must be more attractive :
BOOL SetConnectionOptions(LPCTSTR conn_name,LPCTSTR proxy_full_addr) { //conn_name: active connection name. //proxy_full_addr : eg "210.78.22.87:8000" INTERNET_PER_CONN_OPTION_LIST list; BOOL bReturn; DWORD dwBufSize = sizeof(list); // Fill out list struct. list.dwSize = sizeof(list); // NULL == LAN, otherwise connectoid name. list.pszConnection = conn_name; // Set three options. list.dwOptionCount = 3; list.pOptions = new INTERNET_PER_CONN_OPTION[3]; // Make sure the memory was allocated.if(NULL == list.pOptions) { // Return FALSE if the memory wasn't allocated. OutputDebugString("failed to allocat memory in SetConnectionOptions()"); return FALSE; } // Set flags. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; // Set proxy name. list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; list.pOptions[1].Value.pszValue = proxy_full_addr;//"http://proxy:80";// Set proxy override. list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; list.pOptions[2].Value.pszValue = "local"; // Set the options on the connection. bReturn = InternetSetOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); // Free the allocated memory.delete [] list.pOptions; InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0); InternetSetOption(NULL, INTERNET_OPTION_REFRESH , NULL, 0); return bReturn; } BOOL DisableConnectionProxy(LPCTSTR conn_name) { //conn_name: active connection name. INTERNET_PER_CONN_OPTION_LIST list; BOOL bReturn; DWORD dwBufSize = sizeof(list); // Fill out list struct. list.dwSize = sizeof(list); // NULL == LAN, otherwise connectoid name. list.pszConnection = conn_name; // Set three options. list.dwOptionCount = 1; list.pOptions = new INTERNET_PER_CONN_OPTION[list.dwOptionCount]; // Make sure the memory was allocated.if(NULL == list.pOptions) { // Return FALSE if the memory wasn't allocated. OutputDebugString("failed to allocat memory in DisableConnectionProxy()"); return FALSE; } // Set flags. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT ; // Set the options on the connection. bReturn = InternetSetOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); // Free the allocated memory.delete [] list.pOptions; InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0); InternetSetOption(NULL, INTERNET_OPTION_REFRESH , NULL, 0); return bReturn; }
The usage is very straightforward:
//set proxy const char* connection_name="Connection to adsl3"; SetConnectionOptions(connection_name,"62.81.236.23:80"); //disable proxy DisableConnectionProxy(connection_name);
Existing Internet Explorer instances are notified by INTERNET_OPTION_SETTINGS_CHANGED
and INTERNET_OPTION_REFRESH
Written by Halatu Hubisi
約定:
1.讀者應具備一定JAVA的知識.
2.本文中的JVM選項均以SUN公司發布的HotSpot JVM 5為準(不過大多數的選項在JVM1.3,JVM1.4中也是可用的).
3.以JAVA_HOME下demo/jfc/SwingSet2/SwingSet2.jar為例進行說明.
4.閱讀本文需要一些關于GC的知識,可以到附錄A中了解這些知識。
關鍵字:
JVM(java虛擬機),調優,GC(垃圾回收)
JVM GC調優
為了能夠將JVM GC的調優能夠使用在具體的實踐當中,下面將利用若干個例子來說明GC的調優.
例1:Heap size 設置
JVM堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啟動的時候會自動設置Heap size的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。
當在JAVA_HOME下demo/jfc/SwingSet2/目錄下執行下面的命令。
java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar
系統輸出為:
Exception in thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 3" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 1" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 2" java.lang.OutOfMemoryError: Java heap space
除了這些異常信息外,還會發現程序的響應速度變慢了。這說明Heap size 設置偏小,GC占用了更多的時間,而應用分配到的執行時間較少。
提示:在JVM中如果98%的時間是用于GC且可用的Heap size 不足2%的時候將拋出此異常信息。
將上面的命令換成以下命令執行則應用能夠正常使用,且未拋出任何異常。
java -jar -Xmn4m -Xms16m -Xmx32m SwingSet2.jar
提示:Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置為相同,而-Xmn為1/4的-Xmx值。
例2:Young Generation(-Xmn)的設置
在本例中看一下Young Generation的設置不同將有什么現象發生。
假設將Young generation 的大小設置為4M ,即執行java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar,屏幕輸出如下(節選)
[GC [DefNew: 3968K->64K(4032K), 0.0923407 secs] 3968K->2025K(32704K), 0.0931870 secs]
[GC [DefNew: 4021K->64K(4032K), 0.0356847 secs] 5983K->2347K(32704K), 0.0365441 secs]
[GC [DefNew: 3995K->39K(4032K), 0.0090603 secs] 6279K->2372K(32704K), 0.0093377 secs]
[GC [DefNew: 3992K->23K(4032K), 0.0057540 secs] 6325K->2356K(32704K), 0.0060290 secs]
[GC [DefNew: 3984K->27K(4032K), 0.0013058 secs] 6317K->2360K(32704K), 0.0015888 secs]
[GC [DefNew: 3981K->59K(4032K), 0.0023307 secs] 6315K->2422K(32704K), 0.0026091 secs]
將程序體制并將Young Generation的大小設置為8M,即執行java -jar -verbose:gc -Xmn8m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar,屏幕輸出如下(節選)
[GC [DefNew: 7808K->192K(8000K), 0.1016784 secs] 7808K->2357K(32576K), 0.1022834 secs]
[GC [DefNew: 8000K->70K(8000K), 0.0149659 secs] 10165K->2413K(32576K), 0.0152557 secs]
[GC [DefNew: 7853K->59K(8000K), 0.0069122 secs] 10196K->2403K(32576K), 0.0071843 secs]
[GC [DefNew: 7867K->171K(8000K), 0.0075745 secs] 10211K->2681K(32576K), 0.0078376 secs]
[GC [DefNew: 7970K->192K(8000K), 0.0201353 secs] 10480K->2923K(32576K), 0.0206867 secs]
[GC [DefNew: 7979K->30K(8000K), 0.1787079 secs] 10735K->4824K(32576K), 0.1790065 secs]
那么根據GC輸出的信息(這里取第一行)做一下Minor收集的比較。可以看出兩次的Minor收集分別在Young generation中找回3904K(3968K->64K)和7616K(7808K->192K)而對于整個jvm則找回1943K(3968K->2025)和5451K(7808K->2357K)。第一種情況下Minor收集了大約50%(1943/3904)的對象,而另外的50%的對象則被移到了tenured generation。在第二中情況下Minor收集了大約72%的對象,只有不到30%的對象被移到了Tenured Generation.這個例子說明此應用在的Young generation 設置為4m時顯的偏小。
提示:一般的Young Generation的大小是整個Heap size的1/4。Young generation的minor收集率應一般在70%以上。當然在實際的應用中需要根據具體情況進行調整。
例3:Young Generation對應用響應的影響
還是使用-Xmn4m 和-Xmn8m進行比較,先執行下面的命令
java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime SwingSet2.jar
屏幕輸出如下(節選)
Application time: 0.5114944 seconds
[GC [DefNew: 3968K->64K(4032K), 0.0823952 secs] 3968K->2023K(32704K), 0.0827626 secs]
Total time for which application threads were stopped: 0.0839428 seconds
Application time: 0.9871271 seconds
[GC [DefNew: 4020K->64K(4032K), 0.0412448 secs] 5979K->2374K(32704K), 0.0415248 secs]
Total time for which application threads were stopped: 0.0464380 seconds
Young Generation 的Minor收集占用的時間可以計算如下:應用線程被中斷的總時常/(應用執行總時?L+應用線程被中斷的總時常),那么在本例中垃圾收集占用的時?L約為系統的5%~14%。那么當垃圾收集占用的時間的比例越大的時候,系統的響應將越慢。
提示:對于互聯網應用系統的響應稍微慢一些,用戶是可以接受的,但是對于GUI類型的應用響應速度慢將會給用戶帶來非常不好的體驗。
例4:如何決定Tenured Generation 的大小
分別以-Xmn8m -Xmx32m和-Xmn8m -Xmx64m進行對比,先執行
java -verbose:gc -Xmn8m -Xmx32m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類,命令行將提示(只提取了Major收集)
111.042: [GC 111.042: [DefNew: 8128K->8128K(8128K), 0.0000505 secs]111.042: [Tenured: 18154K->2311K(24576K), 0.1290354 secs] 26282K->2311K(32704K), 0.1293306 secs]
122.463: [GC 122.463: [DefNew: 8128K->8128K(8128K), 0.0000560 secs]122.463: [Tenured: 18630K->2366K(24576K), 0.1322560 secs] 26758K->2366K(32704K), 0.1325284 secs]
133.896: [GC 133.897: [DefNew: 8128K->8128K(8128K), 0.0000443 secs]133.897: [Tenured: 18240K->2573K(24576K), 0.1340199 secs] 26368K->2573K(32704K), 0.1343218 secs]
144.112: [GC 144.112: [DefNew: 8128K->8128K(8128K), 0.0000544 secs]144.112: [Tenured: 16564K->2304K(24576K), 0.1246831 secs] 24692K->2304K(32704K), 0.1249602 secs]
再執行java -verbose:gc -Xmn8m -Xmx64m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類,命令行將提示(只提取了Major收集)
90.597: [GC 90.597: [DefNew: 8128K->8128K(8128K), 0.0000542 secs]90.597: [Tenured: 49841K->5141K(57344K), 0.2129882 secs] 57969K->5141K(65472K), 0.2133274 secs]
120.899: [GC 120.899: [DefNew: 8128K->8128K(8128K), 0.0000550 secs]120.899: [Tenured: 50384K->2430K(57344K), 0.2216590 secs] 58512K->2430K(65472K), 0.2219384 secs]
153.968: [GC 153.968: [DefNew: 8128K->8128K(8128K), 0.0000511 secs]153.968: [Tenured: 51164K->2309K(57344K), 0.2193906 secs] 59292K->2309K(65472K), 0.2196372 secs]
可以看出在Heap size 為32m的時候系統等候時間約為0.13秒左右,而設置為64m的時候等候時間則增大到0.22秒左右了。但是在32m的時候系統的Major收集間隔為10秒左右,而Heap size 增加到64m的時候為30秒。那么應用在運行的時候是選擇32m還是64m呢?如果應用是web類型(即要求有大的吞吐量)的應用則使用64m(即heapsize大一些)的比較好。對于要求實時響應要求較高的場合(例如GUI型的應用)則使用32m比較好一些。
注意:
1。因為在JVM5運行時已經對Heap-size進行了優化,所以在能確定java應用運行時不會超過默認的Heap size的情況下建議不要對這些值進行修改。
2。Heap size的 -Xms -Xmn 設置不要超出物理內存的大小。否則會提示“Error occurred during initialization of VM Could not reserve enough space for object heap”。
例5:如何縮短minor收集的時間
下面比較一下采用-XX:+UseParNewGC選項和不采用它的時候的minor收集將有什么不同。先執行
java -jar -server -verbose:gc -Xmn8m -Xms32m -Xmx32m SwingSet2.jar
系統將輸出如下信息(片段〕
[GC 7807K->2641K(32576K), 0.0676654 secs]
[GC 10436K->3108K(32576K), 0.0245328 secs]
[GC 10913K->3176K(32576K), 0.0072865 secs]
[GC 10905K->4097K(32576K), 0.0223928 secs]
之后再執行 java -jar -server -verbose:gc -XX:+UseParNewGC -Xmn8m -Xms32m -Xmx32m SwingSet2.jar
系統將輸出如下信息(片段〕
[ParNew 7808K->2656K(32576K), 0.0447687 secs]
[ParNew 10441K->3143K(32576K), 0.0179422 secs]
[ParNew 10951K->3177K(32576K), 0.0031914 secs]
[ParNew 10985K->3867K(32576K), 0.0154991 secs]
很顯然使用了-XX:+UseParNewGC選項的minor收集的時間要比不使用的時候優。
例6:如何縮短major收集的時間
下面比較一下采用-XX:+UseConcMarkSweepGC選項和不采用它的時候的major收集將有什么不同。先執行
java -jar -verbose:gc -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar
系統將輸出如下信息(片段〕
[Full GC 22972K->18690K(262080K), 0.2326676 secs]
[Full GC 18690K->18690K(262080K), 0.1701866 secs
之后再執行 java -jar -verbose:gc -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar
系統將輸出如下信息(片段〕
[Full GC 56048K->18869K(260224K), 0.3104852 secs]
提示:此選項在Heap Size 比較大而且Major收集時間較長的情況下使用更合適。
例7:關于-server選項 在JVM中將運行中的類認定為server-class的時候使用此選項。SUN 的Hot Spot JVM5 如果判斷到系統的配置滿足如下條件則自動將運行的類認定為server-class,并且會自動設置jvm的選項(當沒有手工設置這選項的時候〕而且HOTSPOT JVM5提供了自動調優的功能,他會根據JVM的運行情況進行調整。如果沒有特別的需要是不需要太多的人工干預的。SUN形象的稱這個機制為“人體工學”(Ergonomics〕。具體可以參考http://java.sun.com/docs/hotspot/gc5.0/ergo5.html
*.具有2個或更多個物理的處理器
*.具有2G或者更多的物理內存
提示:此選項要放在所有選項的前面。例如:java -server 其他選項 java類
附錄A:預備知識
.JVM中對象的劃分及管理
JVM根據運行于其中的對象的生存時間大致的分為3種。并且將這3種不同的對象分別存放在JVM從系統分配到的不同的內存空間。這種對象存放空間的管理方式叫做Generation管理方式。
1。Young Generation:用于存放“早逝”對象(即瞬時對象)。例如:在創建對象時或者調用方法時使用的臨時對象或局部變量。
2。Tenured Generation:用于存放“駐留”對象(即較長時間被引用的對象)。往往體現為一個大型程序中的全局對象或長時間被使用的對象。
3。Perm Generation:用于存放“永久”對象。這些對象管理著運行于JVM中的類和方法。
.JVM選項的分類
JVM有這么幾種選項供使用.
1.供-X選項使用的項目,又稱為非標準選項,不同廠商的此類型選項是有所不同的。例如:IBM的JVM用的一些選項在Sun的JVM中就不一定能生效。這種選項的使用方式如下:
java -Xmn16m -Xms64m -Xmx64m java類名
2.供-XX選項使用的項目,這種類型的選項可能要求有對系統信息訪問的權限。所以要慎用。這種選項的使用方式如下:
java -XX:MaxHeapFreeRatio=70 -XX:+PrintGCDetails java類名
3.java選項(即在命令行執行java后提示的選項).
java -server -verbose:gc -d64 java類名
.垃圾收集分類
在JVM中有兩種垃圾方式,一種叫做Minor(次收集),另一種叫做Major(主收集)。其中Minor在Young Generation的空間被對象全部占用后執行,主要是對Young Generation中的對象進行垃圾收集。而Major是針對于整個Heap size的垃圾收集。其中Minor方式的收集經常發生,并且Minor收集所占用的系統時間小。Major方式的垃圾收集則是一種“昂貴”的垃圾收集方式,因為在Major要對整個Heap size進行垃圾收集,這會使得應用停頓的時間變得較長。
.GC信息的格式
[GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs]
<collector> GC為minor收集過程中使用的垃圾收集器起的內部名稱.
<starting occupancy1> young generation 在進行垃圾收集前被對象使用的存儲空間.
<ending occupancy1> young generation 在進行垃圾收集后被對象使用的存儲空間
<pause time1> minor收集使應用暫停的時間長短(秒)
<starting occupancy3> 整個堆(Heap Size)在進行垃圾收集前被對象使用的存儲空間
<ending occupancy3> 整個堆(Heap Size)在進行垃圾收集后被對象使用的存儲空間
<pause time3> 整個垃圾收集使應用暫停的時間長短(秒),包括major收集使應用暫停的時間(如果發生了major收集).
.GC信息的選項
-XX:+PrintGCDetails 顯示GC的詳細信息
-XX:+PrintGCApplicationConcurrentTime 打印應用執行的時間
-XX:+PrintGCApplicationStoppedTime 打印應用被暫停的時間
提示:1.":"后的"+"號表示開啟此選項,如果是"-"號那么表示關閉此選項。
?????2.在不同的選項和不同的收集方式和類型下輸出的格式會有所不同。
附錄B:HotSpot JVM 選項
請參考JavaTM HotSpot VM Options
附錄C:其他資源
http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html
http://java.sun.com/docs/hotspot/gc5.0/ergo5.html
String strs = request.getParameter("yourstrs");關于tomcat4.0配置digest認證注意事項:
byte b[] = strs.getBytes("ISO-8859-1");
strs = new String(b);
簡潔寫法:
String convert = new String(request.getParmater("inputname").trim().getBytes("ISO8859_1"), "GBK");
????似乎是數位少年作家的嶄露頭角,讓人們開始注目“80后”。而當在人們眼中的“80后”還是代表著浮躁和反叛時,這個詞卻在悄悄地與財富畫上連接符號,一批極為年輕的財富新貴的出現似乎是一夜之間,同時顛覆了人們心目中
企業家
的傳統印象。
???
???也正由于他們的年紀之輕和擁有的財富之重,這段時間來,他們不斷受到媒體和公眾的追捧。
????看看上述這些代表人物從事的行業就知道,這批“80后”財富新貴的共同特點是夾了一本叫“互聯網”的大課本匆匆上路了。互聯網這座虛擬時空里的“大學”,在很多層面上反叛著以一間講堂、一套書本、一種方言、一個系統為依托的傳統 教育 。
????在李想看來,這正是“80后”的一代人所具有的互聯網精神:完全不顧忌那些別人認為是必須去做的傳統,破除墨守成規,只做最正確的事。
????和李想說話,你會發現他始終思路清晰、方向明確,回答每個問題不超過3句話,也挑不出一點廢話。“我的方向和目標很明確,一開始我就知道我的事業方向就是互聯網,然后我會確定每一個階段的目標,一個一個去實現,所以我不會受到誘惑去燒錢,也不會因為碰到困難就放棄。”
????“像李想、戴志康這批‘80后’創業家的優勢就在于他們創新能力很強,敢于嘗試,想了就做。不像70年代的人干什么都思前想后,以致錯過很多機會。”中華英才網總裁、著名人力資源專家張建國說:“但他們的問題是自我意識太強,而管理企業是要靠組織體系和團隊協作的,因此,靠一個好的創意可以成就一個企業,但企業做大以后怎么管理好,這可能是‘80后’企業家應該注意的問題。”
????和張建國基本同齡的戴光對于兒子戴志康也有類似的擔心,“你可以憑一項技術創業,但公司做大以后,如何從一個技術天才的角色中脫離出來,完成一個管理者的轉型,是一個大問題”。
這些擔心已經是李想們正在思考并一直著力解決的問題。
????“2003年時我的性格還是典型的‘80后’,太自我,不太考慮他人的感受。這給了我很多教訓,讓我慢慢改變,慢慢學會跳出來觀察自己,學會了解每一個員工的性格和想法。”李想說,“而且我開始嘗試用心跟別人溝通,而不是用腦子。用腦子太累,大家互相猜來猜去,我喜歡直截了當,怎么想的就怎么說。后來我發現其實大部分人都喜歡這種溝通方式,包括那些很有名的CEO們。所以規則不是不可以改寫的,關鍵是你去不去做。”
????這正是“80后”財富新貴的共同特點,他們擁有與年齡不相符的成熟和老練。
????本期,我們走近“80后”財富新貴中的兩位:李想和戴志康,也走訪了其中一位的父親,希望能從父輩的教育方式上對這批財富新貴的成功緣由有所挖掘。
????一個沒有上過大學,一個做了大學的“半路逃兵”,李想和戴志康都沒有受過完整的高等教育,但他們卻創造了奇跡。
????這批沒有接受正規高等教育卻創業成功的年輕企業家的崛起,再次引發對現行高等教育的爭議,中國高校究竟該培養什么樣人才的問題又一次被提起。
????在關注他們成長的同時,我們也期待他們在今后的路上走得更加穩健和長久。
????見到25歲的PCPOP網首席執行官李想時,他的公司一片忙亂,所有的會議室都被騰出來接待面試者,李想準備繼續擴大已有的100多人的團隊,而他們2004年還顯得空蕩的公司變得擁擠不堪。李想說他已經在中關村一個新建的寫字樓里租下了比現在大一倍的“新家”,馬上就要搬家了。
????作為中國第三大中文 IT 專業網站——PCPOP網的創始人,李想持有公司50%以上的股份,身家在1億元以上,網站去年的營業額收入近兩千萬元,利潤一千萬元,取20倍的市盈率,市場價值兩億元。但李想的野心決不僅限于此,“今年的營業額要達到去年的2.5倍,明年要超過1億元,然后2008年達到一個上市的標準,這是我們未來幾年發展的一個方向。”
????這個野心勃勃的年輕人8年前還是一個上不起網的高中生,當時一小時8元的上網費外加一小時4元的電話費對于一個孩子來說實在昂貴,后來上網費用降到只需一小時1元,他就是那時候開始接觸互聯網的,“我一碰互聯網馬上就迷上了,當時很單純,就是因為可以在網上跟志同道合的人交流、學習知識”。
李想很快就開始做自己的IT資訊網站,網站的訪問量很快就達到五六千人。當達到一萬人時,就有
廣告
商開始找他,要做廣告,訪問量一千次10元,‘我當時想,閑著也是閑著,就給他掛上了”。
????沒有在意的李想兩個月后收到了廣告商6000元的付款,“我當時也很吃驚,這比我父母一個月加起來掙的還多。”不經意間挖到自己的第一桶金,本來心思就不在讀書上的李想終于在高三畢業時作出了一個大膽決定:放棄考大學,自己創業。
????與李想同歲、同樣靠互聯網起家的康盛世紀科技有限公司CEO戴志康卻是個從小和電腦泡到大的人。戴志康出生在大慶一個高級知識分子家庭,父親戴光是大慶石油學院的博士后。還在上小學的戴志康沒事就去鼓搗家里的電腦,從286到586,家里的電腦一次次為他升級,戴志康編程的本事也越來越高。
????2000年,戴志康竟然經過高考前一個月的突擊準備考進一所知名大學的 通信 工程專業,這讓老師同學大跌眼鏡。然而進入大學一年級后,戴志康便很少在學校,而是自己在外創業。“我當時在外面租了個月租300塊錢的房子,一天差不多15個小時都泡在電腦前面,悶頭開發Discuz!”。
????Discuz!是一套能自動生成社區的軟件,能讓不懂技術的人也能管理自己設計的網絡社區。剛開始研發時,戴志康并沒打算以此創業,“我想畢業后找個好工作,所以開始研發Discuz!時只是興趣,就想證明自己的能力。但在研發過程中,當我產生以此掙錢的念頭時,就不再想找工作了。”
????現在,Discuz!已經是社區軟件領域的老大,戴志康也開始進行公司的轉型,把產品免費供應給客戶,轉而從為客戶提供服務中獲取收入。這個仍習慣于吃學校食堂、穿地攤衣服卻開著銀灰色 寶馬 的年輕人,談起自己公司的發展方向頭頭是道,老練得讓人有些超出想像。
????寬松的家庭教育造就了創業素質
????戴志康的辦公室立著一個空空的書架,“我不喜歡看書,我認為書是用來查的,不是用來翻的,我討厭被動地接收信息,我喜歡從生活中掘取信息”。戴志康的學習與常人理解的不同,他既不靠學校也不靠書本,而是從生活的細節中學習。
????經常和朋友聊天到凌晨的戴志康,從中“偷學”到不少東西。
“另外,我喜歡獨立思考。只有獨立的人才會堅強。當遇到看似解決不了的困難時,不獨立的人馬上想到的是尋求幫助。但在一個商業社會里如果沒有利益的關聯,沒有人會幫你,你獲得了別人的幫助也就意味著自己商業利益的損失。”戴志康說,“再有,勇氣和執著是創業必須的基本素質,而這兩點獨立的人很容易獲得。”
????戴志康把這種獨立思考能力的養成歸功于家庭教育,“我父母的教育方式比較西化,給我很大的空間。當然,父母同時也要我自己負責任,什么都靠自己,不到萬不得已他們不會伸手幫忙。而且我父母都是老師,每天和年輕人接觸,心態也比較年輕。”
????戴志康的父親戴光在向筆者總結他的教育方式時說,對孩子的培養不能限制得太死,要給孩子建議而不是命令,孩子覺得對的要采納,要讓他自己思考,不能給現成的答案,這樣孩子才能有自信、有想法,不是一塊只會跟著別人的木頭。
????“我覺得戴志康之所以能取得一些成就,是他發揮了自己的特長,大學里就有了自己的產品,他的創造能力和創新思維特別強,又有敢想敢干的冒險精神,還有就是這孩子是個踏踏實實干事的人,能容得下事、容得下人。”戴光這樣評價自己的兒子。
????無獨有偶,李想同樣來自一個環境寬松的家庭,他也把自己最重要的創業素質歸結為“獨立思考和總結能力強”以及不斷學習的能力。“我小學時父母給的是命令,初中時給的是建議,高中時是從朋友的角度提出參考,到了高中以后就是信任了。父母給了我很多獨立思考的機會,我基本沒有受過什么束縛。”李想說。
????財富新貴引發教育新思考
????“因為出了我們這樣一批人而在社會上引起什么‘高等教育無用論’,純屬瞎扯。現實是大學里沒有目標、隨波逐流的人太多了,所以我們這樣目標明確并堅持下來的人才顯現出來。
????”沒有上過大學的李想說。
????李想坦言,沒有上大學的確是自己的一個遺憾,因為人生中缺少了一份體驗。“如果你有明確的目標,大學絕對是一個非常好的學習場所。但相對于上學來說,更重要的是一個人要有目標和方向。”
????李想把現在的大學生分為兩類:畢業后可以挑單位的和畢業后“海投”簡歷也找不到工作的,“凡是可以挑單位的學生,絕對是從大一起就有明確的目標并一直為之努力。現在很多大學生或者是迷茫,或者雖有目標,但一遇到困難,就‘喜新厭舊’,常立志而不立長志。”
????上了重點大學卻半路“逃跑”的戴志康這樣看待自己4年的大學生活:“我考通信專業時本來以為會學到數字通信,接觸到一些大型的 交換機 ,結果到大三才學到收音機原理,大四才學了黑白 電視 機原理。大學的課程設置太落后于時代,與用人單位的實際需求太脫節。”
????本身就是大學教授的戴光坦言,現在大學的課程設置的確存在滯后問題。“雖然現在高等教育已進入 大眾 化時代,但很多老師和高校管理者的思維還停留在精英教育上。精英教育是細線條的,什么都要講到,是培養理論家的,而大眾教育是粗線條的,應該給學生一定的空間,應該多一些應用性的東西。”
????清華大學科技園副主任、被譽為清華“創業之父”的羅建北認為,像戴志康、李想這樣的人,在現有的大學體系中很難培養出來,因為在應試教育模式下,很難把創業所需的一些素質加入到教學中,“創業素質的培養和應試教育就是一對矛盾,因為你要學生多了解社會,從而發現市場的需求和商機,這都需要時間來實踐,那考試怎么辦?”
合肥留學生創業園 劉濤 ?