パッケージに含まれるクラス名を全て取得する方法

ずーっと前にもこれで苦しんだ気がするけど、きれいさっぱり忘れていたので調べ直し。java.lang.Classやjava.lang.Package, java.lang.ClassLoader辺りからゲットできるかなーと思っていたけど、ものの見事にダメ。

っていう訳で、じゃあ実行時に毎度調べるのはしんどいので、クラス名の一覧をどこかに用意しておこうと思って、それを作るために再度上記のクラスを調べたけどやっぱりなくて、じゃあもうjarを解凍して、そのファイル名からゲットしてやれ!とか思っちゃったんだけど、考えてみればjarはzipなわけでjava.util.jar.JarFileでgetEntriesすればいいじゃん、じゃあどのファイルから取得すればいいの?確かMacとその他では違ったはずーとか思いながらJDKの中を見ていたら、jre/libのしたに classlist なるファイルを発見。まさか!と思ったらどうやらクラス名の一覧が書いてあるらしい!素晴らしいぜー!これをパッケージ名でgrepすれば欲しかったクラス名の一覧が取得できるっすー。

以下、JRubyのコードです。

patterns = Regexp.union(*ARGV.map{|arg| Regexp.new(arg.gsub(/\./, "/"))})
classlist = File.join(ENV_JAVA["java.home"], "lib", "classlist")
classes = []
open(classlist) do |f|
  f.each do |line|
    classes << line.gsub(/\//, '.') if patterns =~ line
  end
end
classes.sort.each do |klass|
  puts klass
end

list_java_classes.rb

$ jruby list_java_classes.rb java.awt javax.swing

という風に実行するとjava.awtとjavax.swingに含まれるクラス名を標準出力に出してくれます。