2010年1月31日 星期日

java.lang.NoClassDefFoundError 可能的原因

執行 Java 遇到這類問題表示 classpath 沒設好, 可能的幾個問題:

  • 沒有將 jar 檔加入 classpath, 記得用 -cp (或 -classpath) 指定位置, 預設為 -cp .
  • 若指定了 -cp, 記得要加 ".", 不然變成找不到原本目錄下的 class 
  •  不同作業系統 -cp 裡用的分隔字元不同, 有些用 ";", 有些用 ":"
  • -cp 記得加在執行 class name 前面
假設目錄配置如下
bin/: 放編好的執行檔 (*.class)
src/: 原始碼 (*.java)
lib/: 放 jar 檔, 如 junit.jar

一個範例:
cd bin  
java -cp .;../lib/junit.jar AllTests
以下是可能的錯誤範例
java -cp ../lib/junit.jar AllTests
java -cp .:../lib/junit.jar AllTests  # Windows 下用 ;
java AllTests -cp .;../lib/junit.jar 


不得不說 Java 的 -cp 實在是很難用啊。

2010年1月23日 星期六

在 Ubuntu 下裝 git 和 mercurial

我習慣用 aptitude 安裝, 基本上換用 apt-get 應該也沒問題, 兩者的基本參數一樣。

git

注意 package 名稱不是 git
  1. aptitude install git-core
可以用 "aptitude search git" 找到含有 git 字樣的 package, 再用 "aptitude show X" 了解細節, 找出正確的 package。

Mercurial

hg resolve ( merge 失敗時會用到這個指令, 必備指令) 是 2008/12 才有的功能, mercurial v1.1 後才有 , 但 Ubuntu 8.04 的 Mercural 是 0.9.5-3, 所以得用 easy_install 裝新版的 Mercurial。作法:
  1. sudo aptitude install python2.5  # 或 2.6
  2. sudo aptitude install python-dev libc6-dev
  3. sudo aptitude install python-setuptools # or install easy_install's egg
  4. sudo easy_install -U mercurial
  5. hg --version  # 查看版本
接著安裝 bash completion, 這樣打 "hg " 後就可以按 tab 補指令, 如同平時用 bash 指令一般:
  1. sudo aptitude install bash-completion
  2. mkdir ~/.hg_files
  3. wget http://jucr.opensolaris.org/files/1166/3597/ext-source/bash-completion-hg -O ~/.hg_files/bash-completion-hg
  4. echo "source ~/.hg_files/bash-completion-hg" >> ~/.bashrc
我不知道「官方」版的 bash-completion-hg 放那, 這個是我 google "mercurial bash completion" 找到的。

    如何知道目前使用的 linux distribution

    每次查每次忘, 寫在這裡備忘:

    fcamel@andLinux:/etc$ cat /etc/issue
    Ubuntu 9.04 \n \l

    2010年1月18日 星期一

    如何找 linux 指令的原始碼

    上篇時, 為了了解 xargs 如何避開 argument too long 的問題, 我決定找 xargs 的原始碼來看。之前沒有這類經驗, google 一些關鍵字後毫無成果。

    靈機一動, 想到初學者的好朋友 Stackoverflow。果然在那裡一搜 "linux download source code" 馬上找到解答: 在 man page 裡找出該指令屬於那個專案。像 man xargs 會發現文末這段話:
    The best way to report a bug is to use the form at http://savannah.gnu.org/bugs/?group=findutils. The reason  for this is that you will then be able to track progress in fixing the problem. Other comments about xargs(1) and about the findutils package in general can be sent to the bug-findutils mailing list. To join the list, send email to bug-findutils-request@gnu.org.
    於是 google findutils 就會找到它的官網, 裡面提到此專案包含 xargs, 附有下載鏈結。

    在 Ubuntu 的作法

    用 apt-get source PACKAGE 下載原始碼。前置作業如下:
    1. 確定 /etc/apt/sources.list 內有含 deb-src, 比方說加入這兩行:

      deb-src http://us.archive.ubuntu.com/ubuntu jaunty main restricted
      deb-src http://us.archive.ubuntu.com/ubuntu jaunty universe multiverse
    2. sudo apt-get update
    可以用 aptitude show PACKAGE / COMMAND 來查 PACKAGE 名稱, 比方「 aptitude show host 」會告知 host 被包在 dnsutils 裡。或是用 apt-file search FILE 來找 PACKAGE, 像是「 apt-file search /usr/bin/xargs 」會列出 findutils。

    /bin/rm: argument list too long 的解法和原因

    若不小心在一個目錄下產生太多暫存檔, 直接 rm -f *.tmp 會出現這個錯誤訊息:
    /bin/rm: argument list too long
    若不幸的同一目錄下還有其它檔案, 不能一次砍掉整個目錄,這時可以透過 find 和 xargs 解掉這問題:
    find . -name "*.tmp" -print0 | xargs -0 rm
    這樣就會透過 xargs 把檔案名稱傳給 rm。注意,find、xargs 分別加上 -print0 和 -0 是為了避開檔名中含有空白字元, 詳情請 man find 並閱讀 -print0 的部份。

    這篇這篇解釋了為什麼有這個問題, 以及為何 find + xargs 可以避開它。問題的源頭不是 bash 也不是 rm, 而是 kernel 執行命令時會先將參數存到 buffer 裡。buffer 的大小是 MAX_ARG_PAGES * "page 大小" --- 一般而言是 32 * 4k = 128k。

    那為啥 xargs沒這問題呢? 對照 man page 的說法, 以及粗略地 trace過 xargs 的原始碼後, 發覺 xargs 自己有管一個參數 buffer, 一但 buffer 滿了, xargs 就會執行傳給它的指令和起始參數, 接著清空 buffer, 再繼續讀剩下的參數。換句話說, xargs 會分多次執行完所有參數。假設要刪除的檔案是 1, 2, ..., 100000000。xargs 有可能這麼做:
    rm 1 2 ... 1000000
    rm 1000001 1000002 ... 2000000
    ...
    我沒有算 buffer size 和檔名順序, 上面只是示意用的例子。


    Update 

    Victor 說 find 加上參數  -delete 就可以了, 即:
    find . -name "*.tmp" -delete
    那........ 以上的說明, 就當作 find + xargs 的靈活應用之一吧。

    2010年1月17日 星期日

    用 code.InteractiveConsole() 協助除錯

    這篇提供一段程式說明如何讓執行中的程式收到 signal 後叫出 interactive console, 很實用的技巧。對我來說, 用在 unit test fail 時正好。

    若比對的資料稍微複雜, 看到 test failed 後還是不明白錯在那裡。這時可以進入互動模式, 方便察看相關變數, 就像用 debugger 觀察局部變數一樣。只要在程式裡這麼寫:
    import code
    code.InteractiveConsole(locals=locals()).interact()
    就能叫出 interactive console, 接著就可隨意觀察啦。

    若有裝 ipython 的話, 用 ipython 更方便, 還支援 code completion:
    import IPython;
    IPython.Shell.IPShellEmbed()()

    2010年1月12日 星期二

    twiki 無法存檔

    昨天似乎因為對同一篇文章同時用兩次 section edition (透過 ChapterEditionPlugin), 結果 twiki 就爛了, 存檔時若要新增 revision, twiki 就會噴出類似這樣的訊息:
    Error saving topic During save of X an error was found by the version control system. Please notify your TWiki administrator.

    /usr/bin/rcs ........... failed.
    google 一下發現這篇和我的狀況相似, 試著照上面說的修改 config 檔, 把
    $TWiki::cfg{StoreImpl} = 'RcsWrap
    換成

    $TWiki::cfg{StoreImpl} = 'RcsLite';
    結果就好了, 希望之後不會有其它問題。

    難道這是暗示我要換到 foswiki 的徵兆嗎?

    2010年1月11日 星期一

    新 blog 開張

    搜尋引擎不會索引 BBS 的文章,之後把一些隨筆記在 BBS 的技術文章或些雜記,改記到這裡好了。主站 http://fcamel.twbbs.org/ 則照舊拿來發表較正式的中長篇文章。

    在 Fedora 下裝 id-utils

    Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...