2014年12月10日 星期三

Ubuntu 14.04 闔上螢幕的動作設定

在 Ubuntu 14.04 如果需要使用命令列模式設定闔上螢幕的動作,可以依照下面的方法進行。

以任意文字編輯器編輯 /etc/systemd/logind.conf,並尋找 HandleLidSwitch 這個屬性,並且依照需要設定以下的其中一個值。
poweroff	闔上螢幕時關機
hibernate	闔上螢幕時待命
lock		闔上螢幕時鎖定
ignore		闔上螢幕不做任何動作

設定完以後,重新啟動對應的服務。
sudo restart systemd-logind

參考資料:
1、Ubuntu 14.04笔记本如何在合上盖子时关机

2014年10月28日 星期二

自行架設 Wiki 引擎(二):變更預設字體

在 Foswiki 上,預設的字體可以從開發者工具中看出,CSS 上的字體設定如下。
html body {
  font-family: arial,verdana,sans-serif;
  font-size: small;
}
不過如果要在 Foswiki 上寫一些中英文夾雜的條目,預設的字體其實蠻不好閱讀的!
因此就想要變更 Foswiki 預設使用的網頁字體。

自行架設 Wiki 引擎(一):使用 Debian 安裝 Foswiki

現在市面上有很多免費的 Wiki 引擎 [1],可以讓使用者自行架設需要的 Wiki 系統
因為我的需求主要是希望有至少還 OK 的 WYSIWYG 介面,並且希望能夠直接針對 Wiki 內容做 HTML 編輯
因此選擇了 Foswiki [2] 作為目標。

2014年10月24日 星期五

設定 OpenStack Neutron 並讓 VM 取得外部連結

簡單說明一下環境,本篇文章中用的 OpenStack 是使用 Fuel 5.1 [1] 佈署出來的 Mirantis OpenStack
因為佈署時不想影響到其他實體網路,因此將 OpenStack 移至虛擬區網的網段,IP 位址為 10.5.*.*。

Fuel 5.1 佈署時的設定如下。

Public Network -- 聯外的實體網路。這個網路區段是讓被 Fuel 佈署的節點取得可被外部存取的 public IP,必須搭配節點佈署時的網路介面設定。
IP Range: Start 10.5.4.2, End 10.5.4.254
CIDR: 10.5.0.0/16
Use VLAN tagging: false
Gateway: 10.5.0.1

Management Network -- 內部溝通的區域網路。Fuel 佈署出來的節點會使用這個網段做溝通,例如 Compute Node 的 Nova 嘗試連接 Controller Node 的 AMQP 服務時,就會透過這個網段連接。
CIDR: 192.168.101.0/24
Use VLAN tagging: false

Storage Network -- 內部溝通的區域網路。照名字來看是被 Cinder、Swift 或者 Ceph 等儲存服務使用的網路..吧。
CIDR: 192.168.102.0/24
Use VLAN tagging: false

Neutron L3 Configuration -- OpenStack 佈署後的 Neutron 設定。此處的設定會反應在 OpenStack 佈署完後,預設建立出來的虛擬路由器的設定。
Internal network CIDR: 192.168.111.0/24
Internal network gateway: 192.168.111.1
Floating IP ranges: Start 10.5.5.2, End 10.5.5.254
DNS Servers: 8.8.4.4, 8.8.8.8

針對 Neutron L3 Configuration 的部份記錄一下,Fuel 佈署完的 OpenStack 預設會先產生好一個虛擬路由器
虛擬路由器會有兩個介面,一個是內部網路,IP 位址的分配會被 Internal network 的設定所限制;
另一個則是外部閘道,IP 位址的分配為 Floating IP ranges 設定的範圍。

2014年10月23日 星期四

透過 Java 讀取、分析封包攔截記錄 (2):即時封包擷取

續上篇文章「透過 Java 讀取、分析封包攔截記錄 (1):使用 jNetPcap 函式庫讀取封包擷取記錄
上篇文章主要是讓 Wireshark 軟體事先擷取好封包,將擷取記錄儲存成 *.pcap 檔之後,再寫程式去分析 *.pcap 檔的記錄內容。
不過有些狀況會希望能夠即時擷取網卡上的資料,這時就可以利用 jNetPcap 函式庫提供的 openLive() 方法了。

2014年10月22日 星期三

在 Windows 上修改網卡的優先順序

簡易記錄~電腦同時插了兩張以上的網卡,而且都有連上網的時候
想要設定網卡的優先順序,以確保網路在最佳配置下運作。
在 Windows 7 上面可以直接參考 [1] 中第二篇回覆(原作者自己的回覆)
在網路設定頁面中按 F10 打開工具列,然後按照說明調整介面順序。

參考資料:
1、《分享》雙網卡修改路由優先順序
2、修改 Windows 網路卡的自動公制設定

2014年10月21日 星期二

在 ubuntu 14.04 設定 VNC 遠端桌面(2015-05-06 修正)

以前在用 ubuntu 12.04 時,使用 x11vnc 都很正常,但升級到 ubuntu 14.04 之後 VNC 就變成一片黑
後來只好整個重裝一次,重新設定 VNC 的環境。

ubuntu 本身雖然有內建 vino server 這個 VNC 服務,啟用方法也很簡單
但測試了之後發現似乎必須要先在 ubuntu 上登入過一次,之後才有辦法透過 VNC 進行連線。
試了一段時間仍然沒有解答之後,又回頭去尋找 x11vnc 的設定方法,而最後找到可用的方式如 [1] 的步驟。

2014年10月17日 星期五

透過 Java 讀取、分析封包攔截記錄 (1):使用 jNetPcap 函式庫讀取封包擷取記錄

如果想要在電腦上攔截網卡發出的封包,一般直覺會想到的就是 Wireshark 這個軟體
它在攔截了一些封包之後,可以透過另存新檔的方式,將攔截下來的內容儲存成一個檔案(*.pcap)
接著還想用程式化的方式自動分析封包的話,在 Java 上可以使用 jNetPcap 函式庫 [1] 來分析攔截下來的封包內容了。

2014年9月24日 星期三

使用 HttpURLConnection 時的記憶體問題

以前同事寫的 HttpClient 套件,實作是靠 Java 原生的 HttpURLConnection
不過最近又發生了使用該 HttpClient 套件時,出現 OutOfMemoryError 的訊息
發生原因是因為透過該 HttpClient 傳輸的資料太大,把 JVM 的記憶體撐爆了。

花了一些時間搜尋後,同事發現在 HttpClient 裡面加上 HttpURLConnection.setChunkedStreamingMode(0) 後問題似乎就解決了。
而關於為什麼有這個問題、以及為什麼呼叫這個方法後就可以解決,原因大概可以參考 [1] 的描述。
以下節錄 [1] 文章開頭的兩段話:
post請求的OutputStream實際上不是網絡流,而是寫入內存,在getInputStream中才真正把寫道流裡面的內容作為正文與根據之前的配置生成的http request頭合並成真正的http request,並在此時才真正向服務器發送。

HttpURLConnection.setChunkedStreamingMode函數可以改變這個模式,設置了ChunkedStreamingMode後,不再等待OutputStream關閉後生成完整的http request一次過發送,而是先發送http request頭,正文內容則是網路流的方式實時傳送到服務器。實際上是不告訴服務器http正文的長度,這種模式適用於向服務器傳送較大的或者是不容易獲取長度的數據,如文件。

參考資料:
1、Http学习之使用HttpURLConnection发送post请求深入
2、HttpUrlConnection.setChunkedStreamingMode()

2014年9月23日 星期二

實作 Java 的套件系統(Plugin System):以 jspf 框架為例

在開發比較大一點的系統時,常會有個想法是想要做到可以讓使用者動態下載套件,然後系統就能夠即時把套件套用到系統上
在 Java 上這個概念可以透過 ClassLoader 的技巧來實現。
雖然網路上也有一些文章教導如何自行建立簡單的套件系統,不過現在其實也有一些 Open Source 的專案可以利用了~。

2014年9月18日 星期四

MongoDB 監控:使用 MongoDB Management Service

MongoDB 官方有提供 MongoDB Management Service (MMS) 這個服務
可以用來監控指定的 MongoDB 資料庫,並且畫出還蠻詳細的曲線圖供使用者分析自己的資料庫運作狀況。


MMS 主要有提供監控和備援的能力,其中監控的部份是免費的、備援則是必須付費。
同時 MMS 提供了雲端版的服務和獨立安裝版,前者可以直接把統計資料送到 MongoDB 營運的 MMS 服務,後者則是自己維護一台自有的 MMS 主機。
對前者來說,使用者只需要註冊一個 MMS 的帳號,然後在能夠存取想監控的 MongoDB 的一台主機上安裝監控的代理人程式即可。
不過如果有些監控的功能想使用(例如 profiling 功能,會送出每個 MongoDB 接受的指令到 MMS 上),但又不希望這些資料被送上雲端
就可以改用後者,自己安裝自己的 MMS 囉。

2014年8月13日 星期三

mei 0000:00:16.0: initialization failed.

在伺服器上安裝 ubuntu 14.04 時,遇到安裝完以後出現這個錯誤訊息,然後伺服器就停止開機了。
mei 0000:00:16.0: initialization failed.

可能的原因如 [1] 中原 PO 自己的回應,mei 似乎是 Intel(R) Management Engine Interface 的驅動程式
如果安裝的主機的 CPU 不支援 Intel® vPro™ 技術,就有可能導致 mei 啟動產生問題。

解決方法是讓 ubuntu 啟動時將 mei 加入黑名單。
sudo echo  "blacklist mei" > /etc/modprobe.d/mei.conf

而在開機時出現問題,沒辦法輸入上述指令時,可以透過 ubuntu recovery 模式中選擇 ROOT 開啟 console 介面
不過在 console 介面預設是唯讀模式,必須先掛載 [2] 之後才能進行檔案操作。
mount -o rw,remount /

參考資料:
1、mei 0000:00:16.0: init hw failure
2、Recovery Console always read-only mode

2014年8月12日 星期二

GPG error: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY

在嘗試安裝 Foxwiki 時,遇到手動加入 deb 位址時,apt-get 無法正確存取,解決方式如 [1] 的回應所說。
例如 Foswiki 出現的錯誤訊息如下:
W: GPG error: http://fosiki.com stable Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 379393E0AAEE96F6
則輸入的指令是:
gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv 379393E0AAEE96F6
gpg --export --armor 379393E0AAEE96F6 | sudo apt-key add -

系統回應的結果如下:
root@ubuntu:~# gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv 379393E0AAEE96F6
gpg: directory `/root/.gnupg' created
gpg: new configuration file `/root/.gnupg/gpg.conf' created
gpg: WARNING: options in `/root/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/root/.gnupg/secring.gpg' created
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: requesting key AAEE96F6 from hkp server keyserver.ubuntu.com
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key AAEE96F6: public key "Fosiki Software Releases (Release signing user) <Releases@fosiki.com>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
root@ubuntu:~# gpg --export --armor 379393E0AAEE96F6 | sudo apt-key add -                                                                                                        OK

參考資料:
1、How do I fix the GPG error “NO_PUBKEY”?

2014年8月7日 星期四

OpenStack Nova 使用外部 DHCP 的設定方法

最近試了蠻久的 OpenStack 設定,目前最新版的 icehouse 版本有 Neutron 這個網路套件
不過我們實驗了一段時間,一直沒辦法把 Neutron 設定好
後來改嘗試完全不使用 Neutron,而是使用原本 Nova 自帶的 Nova Network 套件。

其中因為我們暫時的目標是要能夠透過 ssh 直接連上 OpenStack 上的虛擬機器,因此設定選用 FlatManager 這個最基本的網路設定。
補充:FlatManager 在某些方面不太被認同,可以參考 [8] 的討論。

2014年7月24日 星期四

使用 log4j 時,讓 Apache HttpClient 的 log 消失

如果有同時使用 log4j 和 HttpClient,應該很多人都有這個慘痛的經驗~
HttpClient 在執行時會把所有發送和接收的資料全部以 debug 等級的 log 輸出到 log4j
一般在做 JSON 處理時還好,這個 log 大概對於 debug 蠻有幫助的
但如果是在實作檔案上傳或者下載時,印出來的 log 等於是把要上傳或下載的檔案全部輸出到 log4j,是相當驚人的文字量
而且有時候會把 eclipse 弄到當機...。

2014年7月18日 星期五

java.lang.ArrayIndexOutOfBoundsException: 48188

莫名其妙遇到的問題....錯誤訊息如下:

嚴重: StandardWrapper.Throwable
java.lang.ArrayIndexOutOfBoundsException: 48188
        at org.objectweb.asm.ClassReader.readClass(Unknown Source)
        at org.objectweb.asm.ClassReader.accept(Unknown Source)
        at org.objectweb.asm.ClassReader.accept(Unknown Source)
        at com.sun.jersey.spi.scanning.AnnotationScannerListener.onProcess(AnnotationScannerListener.java:136)
        at com.sun.jersey.core.spi.scanning.JarFileScanner.scan(JarFileScanner.java:97)
        at com.sun.jersey.spi.scanning.servlet.WebAppResourcesScanner$1.f(WebAppResourcesScanner.java:94)
        at com.sun.jersey.core.util.Closing.f(Closing.java:71)
        at com.sun.jersey.spi.scanning.servlet.WebAppResourcesScanner.scan(WebAppResourcesScanner.java:92)
        at com.sun.jersey.spi.scanning.servlet.WebAppResourcesScanner.scan(WebAppResourcesScanner.java:79)
        at com.sun.jersey.api.core.ScanningResourceConfig.init(ScanningResourceConfig.java:80)
        at com.sun.jersey.api.core.servlet.WebAppResourceConfig.init(WebAppResourceConfig.java:102)
        at com.sun.jersey.api.core.servlet.WebAppResourceConfig.<init>(WebAppResourceConfig.java:89)
        at com.sun.jersey.api.core.servlet.WebAppResourceConfig.<init>(WebAppResourceConfig.java:74)
        at com.sun.jersey.spi.container.servlet.WebComponent.getWebAppResourceConfig(WebComponent.java:668)
        at com.sun.jersey.spi.container.servlet.ServletContainer.getDefaultResourceConfig(ServletContainer.java:415)
        at com.sun.jersey.spi.container.servlet.ServletContainer.getDefaultResourceConfig(ServletContainer.java:582)
        at com.sun.jersey.spi.container.servlet.WebServletConfig.getDefaultResourceConfig(WebServletConfig.java:87)
        at com.sun.jersey.spi.container.servlet.WebComponent.createResourceConfig(WebComponent.java:699)
        at com.sun.jersey.spi.container.servlet.WebComponent.createResourceConfig(WebComponent.java:674)
        at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:203)
        at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:374)
        at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:557)
        at javax.servlet.GenericServlet.init(GenericServlet.java:158)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5210)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5493)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1083)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1880)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

找來找去找不太到相關的資料,好不容易找到 [1],顯示錯誤原因似乎是使用 Maven 時加上了 Jaxen 這個 dependency。
不過這個 dependency 是 dom4j 在操作 XPath 時要用的 ~"~
先記錄一下,也許可能的解法是不要用 XPath 來存取 XML 內容....。

參考資料:
1、较少遇到的错误—严重: StandardWrapper.Throwable—java.lang.ArrayIndexOutOfBoundsException: 48188

2014年7月10日 星期四

透過 Apache jClouds 操作本地檔案系統的 Blob Store

Apache jClouds 是一個可以支援很多不同雲端基礎建設的開源函式庫
其中可以利用它的 Blob Store 的介面,來操作各家雲端基礎建設的儲存服務。
不過其實它也有提供非雲端基礎建設的實作,讓使用者可以適度地把一些沒有要放上雲端的東西,透過它的介面存放在本地的檔案系統。

2014年7月7日 星期一

使用 AES 加密後的資料長度

參考 [1-2],AES 演算法在加密時基本上不會變更檔案長度,所以原始檔案有多長,加密後就有多長。
不過因為 AES 是 block cipher,要加密的對象必須是 16 bytes 的倍數才能正常加密
因此演算法必須搭配 padding 的方法,而 padding 的方法就會影響加密後的長度。

從 [1] 的回應來看,如果 padding 的方法是使用 PKCS5 或 PKCS7 的話,加密後的長度如下:
cipherLen = (clearLen/16 + 1) * 16;

參考資料:
1、Size of data after AES encryption
2、How does PKCS#7 padding work with AES-256, CBC mode?

2014年7月1日 星期二

在 ubuntu 建立 virtual bridge

想要在 ubuntu 上建立 bridge 時,可以透過 bridge-utils 這個套件來達成。

2014年6月24日 星期二

OpenStack Cinder 使用磁碟的概念

在 OpenStack 中,關於儲存的服務有 Cinder(Block Storage)以及 Swift(Object Storage)
其中 Cinder 在定位上強調的是永久並且快速的儲存空間
同時 Cinder 也在運算單元產生虛擬機器時,負責提供虛擬機器所需要的實體空間。

2014年6月16日 星期一

OpenStack Swift 的儲存結構最佳化

當需要使用大型雲端基礎建設時,在國外有蠻多企業選擇 OpenStack 這個開源雲端專案。
OpenStack 裡面又有 Swift(不是 Apple Swift 程式語言 XD)這個 Object Storage 服務,可以提供關於物件儲存的解決方案。
Swift 主要提供的是高可用性且易於擴展的儲存服務~
它的儲存結構中區分為 account、container 以及 object 三個階層
因此想要建構在 OpenStack 之上的應用服務時,也需要稍微思考一下要如何去建構 Swift 的結構。

2014年6月13日 星期五

在 ubuntu 安裝 All-In-One 開發版的 OpenStack

想要安裝 OpenStack 時,一般是可以直接看官方文件一步一步安裝
但因為中間設定很多又很繁雜,開發階段可以用 DevStack 來簡化安裝過程。
要使用 DevStack 來安裝,動作很簡單~
以 ubuntu 來說,只需要在一台剛裝好的 ubuntu 上安裝 git,然後用 git 的指令從 github 上把 DevStack 的安裝包下載下來
最後執行 DevStack 上的安裝指令 [1] 就可以一鍵安裝完成。

2014年6月5日 星期四

system() 執行的路徑帶有空格的解決方法

正常在 C/C++ 呼叫 system() 時,system() 函式在 Windows 上會呼叫 cmd.exe,然後代入 system() 的括號裡給的參數 [1]
不過參數如果帶有空格,例如想執行某個外部的程式,而該程式位在 Program Files 資料夾內時,有可能出現類似這樣的錯誤訊息:
windows找不到'C:\Program' 請確定您輸入的正確名稱,並且重試
而解決方法就是把有空格的部分用 \" 包起來 [2-3],讓 C 語言執行時看到的字串是這樣:
C:\"Program Files"\....
例如:
system("C:\\\"Program Files\"\\Java\\jdk1.7.0_45");

參考資料:
1、c++ system()和WinExec()的区别
2、C語言可以呼叫名字有空格的資料夾嗎???
3、C语言 system()函数打开一个程序,路径有空格的问题

2014年6月4日 星期三

在 eclipse 上開發 JNI:設定 CDT + MinGW 的操作環境

這篇是在記錄使用 eclipse 開發 JNI 時,在 eclipse 上如何開發 C/C++ 的程式(CDT)
以及在 eclipse 上如何建立 JNI 的關連,讓 C/C++ 的 JNI 程式可以透過 eclipse 完成開發。
主要參考對象是 [1-2],其中 [2] 是比較詳細的教學。

2014年5月30日 星期五

安全的 PRNG(亂數產生器)

最近公司引入了一個原始碼掃描的系統 Fortify,在掃描的結果中回報了我們的專案使用了一些 java.util.Random 這個亂數產生器
而這個亂數產生器在亟需安全的環境中並不安全,因為它並不是屬於加密安全(cryptographically secure)的亂數產生器
因此產生的結果很容易被預測。

2014年5月26日 星期一

讓 Javadoc 繼承父類別的文件

一般狀況下,當子類別某個 method 有覆寫 parent 的對應 method(即有寫 @override)時
可以利用 {@inheritDoc} 讓子類別可以繼承父類別的文件,可以參閱 [1]。
不過如果遇到要覆寫的對象是 constructor 時
因為 constructor 不需要也不允許寫 @override,會導致無法利用 {@inheritDoc} 來繼承父類別的文件
這時的作法可以利用 @see 來加上間接的註解 [2]
雖然沒辦法像 {@inheritDoc} 那樣直接連結到父類別,但總算是點一下連結還是看得到。

2014年5月22日 星期四

Sub-process /usr/bin/dpkg returned an error code (1)

遇到一個無聊的小問題~
在我的 ubuntu 機器上,嘗試安裝 openntpd 時出現錯誤,然後就持續錯誤無法安裝也無法移除。
錯誤訊息如下:
user@HTPC:/home$ sudo apt-get install -f
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
升級 0 個,新安裝 0 個,移除 0 個,有 59 個未被升級。
1 個沒有完整得安裝或移除。
此操作完成之後,會多佔用 0 B 的磁碟空間。
正在設定 openntpd (3.9p1+debian-9) ...
Starting openntpd: /etc/openntpd/ntpd.conf: Permission denied
invoke-rc.d: initscript openntpd, action "start" failed.
dpkg:在處理 openntpd (--configure) 時發生錯誤:
 子程序 已安裝的 post-installation script 傳回了錯誤退出狀態 1
在處理時有錯誤發生:
 openntpd
E: Sub-process /usr/bin/dpkg returned an error code (1)

2014年5月5日 星期一

synchronized、ReentrantLock 與 ReentrantReadWriteLock

在多執行緒的環境下,為了避免在多執行緒的狀況中產生資料不一致的結果
常利用上鎖機制去鎖定資源,藉此來控制只能有單一執行緒操作特定資源。
而 Java 7 當中,常用的上鎖的方法大概是 synchronized、ReentrantLock 與 ReentrantReadWriteLock。

以下的內容主要是 [1] 的大綱(雖然 [1] 主要要講的是 Java 8 提供的樂觀鎖 XD)
因此就不重複貼範例程式碼了,內容也僅僅簡要地寫下差異。

2014年4月24日 星期四

在 Spring FrameWork 中做定時執行

在 Spring FrameWork 的環境中,想要做定時執行有好幾種作法,可以參考 [1-2]。
在這邊的範例是 [1-2] 有提到的其中一種作法,主要是利用 Spring 的 scheduled-tasks 搭配 cron expression 來控制執行時間。

2014年4月21日 星期一

(書籤) Java 例外處理

在網路上看到一個系列文,討論 Java 的例外處理~
從為什麼 Java 的例外處理要區分為 checked 跟 unchecked 兩種例外,到對於一個例外需要考慮哪些問題、是否應該處理等等
推薦對於例外處理的本質以及概念還不熟悉的人可以參考看看!

Checked or unchecked exceptions (1)
Checked or unchecked exceptions (2)
Checked or unchecked exceptions (3)
Checked or unchecked exceptions (4A)
Checked or unchecked exceptions (4B)
Checked or unchecked exceptions (5)

參考資料:
1、搞笑談軟工

2014年2月20日 星期四

Vector vs ArrayList vs HashSet

記錄一下在 Java Code Geeks 上看到的文章 [1],主題是做 Vector、ArrayList 跟 HashSet 的比較。

2014年2月14日 星期五

Java 的記憶體配置(Global、Stack、Heap)

在 JVM 中,記憶體區分為 Global、Stack 和 Heap 兩種,各自存放不同的東西
大致來說,Global 存放靜態的變數、Stack 存放 method 以及非 class member 的 primitive type,Heap 則存放所有的物件以及相依於物件的 class member。

2014年2月12日 星期三

設定 MongoDB 中資料的存活時間(TTL)

自從 MongoDB 2.2 以後,開始支援一個算是常用的功能,可以直接在 collection 上設定資料的存活時間
例如假設插入一筆資料後,希望它在兩小時後自動消失,過去的作法是要自己實作 daemon 去檢查
不過在 MongoDB 2.2 開始,MongoDB 會幫忙做這件事,只要在 collection 上做好設定即可。

2014年1月22日 星期三

java.lang.NoClassDefFoundError: Could not initialize class

今天遇到的一個奇怪的問題,把某些類別包裝後原本都用得好好的,但移植到另一個專案時就出現無法初始化類別的問題
後來確認了原因是因為程式碼裡在 static 的區塊中做了某個類別的初始化,於是造成執行時無法正確初始化的問題。

static {
  QueryBuilder db = new QueryBuilder(.....);
  db.execute("key", 1).ensureIndex();
}

真實的原因跟對應的理由還不太了解,因此暫時先做個記錄,也許未來哪天會懂背後的問題...。

參考資料:
1、java.lang.NoClassDefFoundError: Could not initialize class XXX

2014年1月16日 星期四

String 和 StringBuilder 之間的差別

這個議題其實在 Java 當中盛行以久,應該大家都知道使用 String 相加是罪大惡極的行為
不過自從 Java 6 開始,基於各種 JVM 的調整,這個概念似乎有稍微修改的需要。

2014年1月15日 星期三

透過 Java driver 做 MongoDB sharding

在 MongoDB cluster 的環境中,即使 MongoDB 已經做成 Mongos 了,預設資料都還是會全部集中在同一台資料庫上
持續對資料庫做資料寫入時,資料越多速度會越慢,而且也可以發現都是同一台伺服器很忙
主因就是因為沒有做 DB 和 collection 的 sharding。

2014年1月9日 星期四

檢查 Collection 中是否有某個自定義的 Object

一般如果使用 Collection 類別去儲存一系列的某種 Object 時,可以直接利用 Collection.contains(obj) 的方法檢查某個 Object 是否在 Collection 內
不過 Java 預設的 Object 的檢查方式是檢查兩個 Object 是否相等,是依據 Object 所在的記憶體位置判斷的
但有時我們想要的是 Object 內的某些屬性相等,就視這兩個 Object 相等
也就是當使用 Collection.contains(obj) 時,想要的結果其實是當 Collection 內的某個項目特定屬性跟 obj 的特定屬性一樣,就預期要回應 true。