Java8対応のCheckstyle5.9が出ています

checkstyle – Checkstyle 6.0

Java8に対応したCheckstyle5.9が出ています。(リリースノート: checkstyle – Release Notes

→ (2014/10/27 追記) 6.0 が出てました。はやすぎっ

これでFindbugsCheckstyleと2大伝統的JavaインスペクションツールがJava8対応したわけで、だいたいの人はJava8に来れますね。

ちなみにEclipseプラグインの方は、まだ5.8っぽいです。 Eclipse Checkstyle Plug-in / Feature Requests / #145 Upgrade to checkstyle 5.9

→ (2014/10/29 追記)5.9対応のEclipseプラグインがリリースされています。

Dropboxの1TBのやつ使い始めた

Dropboxの1TBプランを契約して使い始めました。

もともとDropbox自体は使ってなかったのですが、1TBプランが月1200円ではじまったのを聞いて契約してみました。

私がよく愛用しているGoogle Driveも安価に1TBプランもあって、実はそっちも一度契約したんですが、Google DriveWindowsアプリが一度に1アカウントしか接続できないこともあり、仕事用アカウントと両立できないのですぐに契約ストップさせました。(1か月の払い損ですね)

あとGoogleはメールも併用していることもあり、たとえばファイル側の容量がオーバーフローしたらメールどうしようとか考えてしまい、クオータがあればいいなあ、とも思ったり。

暗号化ドライブをDropboxに入れる ~ BitLocker+VHD(VHDX)

で、バックアップされておいてほしいファイルをバンバカ入れていくんですが、AES 256bitで暗号化されているらしいとはいえ、ちょっと生でおきたくないファイルがいくつかあって、それを置くのにどうしようかなあと考え、すぐにTrueCryptを思い出したんですが、開発してるんだか怪しいので、使いたくなくないなーと思って調べたら、TrueCrypt公式にBitLocker使えばいいよーとのことが書いてあったので、

  1. Dropboxの共有フォルダ内にVHDXドライブイメージを作って(VHDに比べてWindows8.1以降で使えるVHDXはスパース可(可変長)です。)
  2. ドライブイメージを接続して
  3. 繋がった仮想ディスクにパーティション作ってNTFSで初期化して
  4. ドライブとしてマウントして
  5. マウントしたドライブをBitLockerでパスワードかければ

無事、暗号化された仮想ドライブのファイルが出来上がります。

200GBぐらいのファイルを作ったんですが、数日ほっておいたらDropboxが無事同期完了させてくれていました。

で、ドライブの中身を変更したら、また200GBを全部同期しなおしか、と思うところですが、そこはDropboxの底力、ちゃんと差分のみを送信してくれます。

こんな感じで快適バックアップライフを送っています。

だいたいの人は大事なファイルが1TB内におさまるはずなのでお試しあれ。

JMockit+JaCoCo トラブルあれこれ

JMockitはテストのために一部のクラスの定義を書き換えるライブラリ、JaCoCoはカバレッジ取得用のライブラリ、どちらも昨今のJava開発のユニットテストで(多分)よく使うものです。

Antで両方を使ったサンプルプロジェクトも用意してみました。 (ライブラリダウンロードのためにはじめてIvyも使ってみた)

https://github.com/knjname/jmockit-jacoco-javaagent-arg-order

JMockitもJaCoCo、どちらもinstrumentationという仕組みを用いてその機能を実現しています。

http://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html

instrumentationというのは、超簡単にいえば、Javaでロードするクラスの中身をロード前に書き換える仕組みです。

instrumentationを使用するには、下記のようにJVM起動時にinstrumentation用のクラスとマニフェストを内包したJARを指定してあげればOK。

java -javaagent:instrumentationに使うJARのパス ほかの引数...

上記のような指定で、-javaagent:~~ に指定されたJARのマニフェストにあるPre-Mainという項に書かれたクラスのpremainメソッドが起動し、そのメソッドの中でクラスの定義を書き換えるクラスがJVMに登録されます。

ま、ここらへんの詳しい仕組みはJMockitなど使う上ではどうでもいいです。

-javaagent複数指定できるので、たとえばJMockit、JaCoCo双方を使う場合は、jmockitのJAR、JaCoCoのJAR、どちらも指定してあげれば、どちらも有効になります。

java -javaagent jmockit.jar -javaagent jacocoagent.jar ほかの引数...

JMockit+JaCoCoがEclipse(EclEmma Java Code Coverage)で動かないよう!

上記解説でJVM起動時にjmockit.jarとjacocoagent.jarを両方指定しましたが、これには正しい指定順序(JMockit→JaCoCo)があり、これが逆(JaCoCo→JMockit)だと下記のようなエラーが出てしまいます。

java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader): attempted  duplicate class definition for name: "knjname/AddRandomTest$1"
     at java.lang.ClassLoader.defineClass1(Native Method)
     at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
     at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
     at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
     at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
     at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
     at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
     at java.security.AccessController.doPrivileged(Native Method)
     at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
     at knjname.AddRandomTest.testAddRandom(AddRandomTest.java:16)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:483)
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

JaCoCoが先行してクラスロード部分に邪念を送ったことにより、JMockitのモック化のためのゴニョゴニョを邪魔してるんですね。

まあ、普通にAntで起動する場合は下記のようにjacocoのAntタスク使い、その場合はこの現象にあうことはないのですが

<jacoco:coverage destfile= "target/coverage.exec">
  <junit fork= "true">
    <jvmarg line= " -javaagent:lib/jmockit-1.11.jar " />
<!-- 以下略 -->

EclipseでEclEmmaとかいうJaCoCoでカバレッジを取得するプラグイン(http://www.eclemma.org/)を使って普通にJMockitを使用したテストを起動するとプラグインの動作で内部的にJaCoCoのJARが先行してしまい、上記のエラーが出てしまいます。

このエラーはEclipse上のカバレッジ取得アクション(Coverage As)起動時にプラグイン内部でたぶん -javaagent:jacocoのJAR を先頭に追記したせいで発生しているようで、JUnit起動構成のVM引数設定を編集して、-javaagentを追加したりなどしても無駄みたいです。

これを解決するには、JaCoCoの指定よりJMockitの指定が先行しさえすればいいので、

  • Eclipseの設定 -> Java -> Installed JREs から
  • JUnit用のJREを新規構成して
  • その構成のDefault VM argumentsに-javaagent:jmockitのJARのパス を追記し、(-javaagent:${workspace_loc}/プロジェクト名/lib/jmockit.jar のようにワークスペースまでの変数とかいれると便利)
  • その構成のJREJUnitコードのプロジェクトのJREライブラリに指定してあげれば

無事に動くと思います。

ちなみに私はこれに半日ハマっていました。酷い。

よその環境で何故かJMockitが動かないよう!

上記のEclipseとは別に、なんでかローカルで動いていたはずのJMockitさんが別Java環境で動かないことがあります。

java.lang.IllegalStateException : Native library for Attach API not available in this JRE
      at mockit.internal.startup.AgentLoader.getVirtualMachineImplementationFromEmbeddedOnes(AgentLoader.java:96)
      at mockit.internal.startup.AgentLoader.loadAgent(AgentLoader.java:50)
      at mockit.internal.startup.AgentInitialization.loadAgentFromLocalJarFile(AgentInitialization.java:29)
      at mockit.internal.startup.Startup.initializeIfPossible(Startup.java:212)
      at org.junit.runner.Runner.<clinit>( Runner.java:22)
      at org.junit.internal.builders.JUnit4Builder.runnerForClass(JUnit4Builder.java:10)
      at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
      at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
      at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
      at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.UnsatisfiedLinkError: no attach in java.library.path
      at java.lang.ClassLoader.loadLibrary(Unknown Source)
      at java.lang.Runtime.loadLibrary0(Unknown Source)
      at java.lang.System.loadLibrary(Unknown Source)
      at sun.tools.attach.WindowsVirtualMachine.<clinit>(WindowsVirtualMachine.java:185)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0( Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
      at java.lang.reflect.Constructor.newInstance(Unknown Source)
      at mockit.internal.util.ConstructorReflection.invoke(ConstructorReflection.java:68)
      at mockit.internal.util.ConstructorReflection.newInstance(ConstructorReflection.java:37)
      at mockit.internal.startup.AgentLoader.getVirtualMachineImplementationFromEmbeddedOnes(AgentLoader.java:92)
      ... 17 more

これは、前の例で示していたような -javaagent:jmockitのJAR を指定しないと発生することがあります。

-javaagent:の指定がないし、今ここでそれ相当のを動的追加しよっか、ってことでAttach APIというのを探して使おうとして、なかったのでエラーということみたいです。

でもこれ確か最近のJavaじゃ指定しなくていいってマニュアルに書いてたはずじゃ?

Depending on your development environment, you may have to do one other thing:

  • If you are developing on JDK 1.5, then make sure that -javaagent:jmockit.jar (with the proper absolute or relative path tojmockit.jar) is passed as an initialization parameter to the JVM when running tests. This standard JVM initialization parameter causes it to load on start-up the "Java agent" that JMockit uses internally for bytecode instrumentation; this is required to work in all standard JVMs since version 1.5, in all OSs. You may have to use this parameter even on a newer JDK 1.6+, if its Attach API implementation is not supported by JMockit: such is the case with the IBM J9 JDK 1.6, the Mac OS X JDKs, and with JDKs for the Solaris OS.

  • If you use TestNG in a JDK 1.6+ environment, JMockit can be initialized in one of three possible ways (apart from use of "-javaagent" indicated above, which can also be used). See this page for details.

When using a HotSpot JDK 1.6+ or a JRockit JDK 1.6+ on Windows or Linux, neither of the extra steps above is necessary.

http://jmockit.googlecode.com/svn-history/r1166/trunk/www/installation.html

はい。最後。

When using a HotSpot JDK 1.6+ or a JRockit JDK 1.6+ on Windows or Linux, neither of the extra steps above is necessary.

(超訳:JDK1.6以上は上記の追加手順はどちらも不要。)

と、こういうことなのですが、これが適用可能なのは厳密にいうと、Attach API(http://docs.oracle.com/javase/8/docs/technotes/guides/attach/index.html)というものが使える環境限定の話らしく、JREJavaでは使えませんし、JDKを指定したつもりでもなんか使えない場合もありました。(Jenkins上とか。なんでなんだろう?)

Attach APIが利用可能であるには、具体的にはjavaが attach.dll (Windows) / attach.so (Linux) をライブラリとして参照可能である必要があるみたいです。

Attach APIに頼らずに無難にどこの環境でもJMockitを使えるようにするには -javaagent:JMockitのJAR は付けておいて損はないと思います。ビルドスクリプトとか。

これも私はハマってました。

っていうか、Attach APIって何?

-javaagent: 相当のAgentClassというやつをVM起動後に動的に追加できることもできるAPIと覚えればOK。出自はJava6から。

http://docs.oracle.com/javase/8/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html

VirtualMachineクラスのloadAgentメソッドにAgent-Classの指定があるJARのパスを渡せば、動的に -javaagent: 相当のクラス定義変換をVMに組み込むことができます。

JMockitみたいなのを作るには、こういうAPIを使って、あらゆるクラスについて好きなタイミングで、挙動を変えられるアスペクト的なバイトコードを全クラスに仕込むようにしておけば作れそうですね。

ほかJMockitの罠

  • クラスパス上、JMockitのJARがJUnitのJARより先行しなければならない。
  • EclipseJUnitプラグインJUnitだと動かないかも(JUnitは明示的に持ってくる派なので遭遇したことはないが
  • junitはfork="true"じゃないとJavaAgent指定する系は動かない。

まあ、一度動けばJMockitもJaCoCoも便利ですよ。

2014-09-01 追記

最近のマニュアル(←まずそっち読めよ)だと

JMockit - Tutorial - Running tests

To run tests that use any of the JMockit APIs, use your Java IDE, Ant/Maven script, etc. the way you normally would. In principle, any JDK of version 1.6 or newer, on Windows, Mac OS X, or Linux, can be used. JMockit supports (and requires) the use of JUnit or TestNG; details specific to each of these test frameworks are as follows:

For JUnit 4.5+ test suites, make sure that jmockit.jar appears before the JUnit jar in the classpath. Alternatively, annotate test classes with @RunWith(JMockit.class).

(Note for Eclipse users: when specifying the order of jars in the classpath, make sure to use the "Order and Export" tab of the "Java Build Path" window. Also, make sure the Eclipse project uses the JRE from a JDK installation instead of a "plain" JRE, since the latter lacks the "attach" native library.)

For TestNG 6.2+ test suites, simply add jmockit.jar to the classpath (at any position).

と書いてあるみたいで、Java6以降使ってね、ってのとjarの指定がアレならRunWithでも動くし、JREを使った場合はAttach APIがないから動かないよと書いてますね。

僕としては何かトラブルがあったら、-javaagent を指定することを薦めたい。

Lispのカッコは怖くないよ

最近Lispの連れション仲間を増やしたいので、いろんな初見の人に「Lispって知ってる?」と質問して回っています。

そこそこアンテナのある技術者ならLispというのがプログラミング言語の一派を意味しており、それが主に大量のカッコで構成されていることは知っているようなのですが、なんか拒否反応が多いんですよね。

拒否反応というのが、まあ、だいたい

  • 「カッコが多すぎて気がおかしくなる」
  • 「私の人生は大量のカッコに対応するには短すぎる」
  • 「大学でやったけどカッコ死ね。」

みたいなHTML初心者がタグのネストに敗北したみたいな感想ですね…。

まあ、パッと見てそういいたくなる気持ちは分かるんですが、それ自体がよくあるLispに対する誤解と言わざるを得ないです。

事実、Lispプログラミングは大量のカッコを相手にするのですが、誰もカッコの個数なんて見ていません。

Lispのプログラムの構造を読むときは、インデントしか見てません。

カッコを読む側の話

Lispプログラムの例として、下記のregexp-opt-depthという関数(Emacsregexp-opt.el)を見てください。

(defun regexp-opt-depth (regexp)
  (save-match-data
    (string-match regexp "")
    (let ((count 0) start last)
      (while (string-match "\\\\(\\(\\?[0-9]*:\\)?" regexp start)
        (setq start (match-end 0))
        (when (and (not (match-beginning 1))
                   (subregexp-context-p regexp (match-beginning 0) last))
          (setq last start)
          (setq count (1+ count))))
      count)))

Javaなどであれば { やら } などなどもうちょっと可愛げのある記号が出てくるのに、特徴も糞もない大量のカッコとアルファベット+記号の羅列でめまいがしてきますね。

海千山千と言われるLisperはこのカッコの対応を一瞬で読み解ける超人ばかりなのでしょうか?

もちろんNoです。

上記のようなLispプログラムを読む場合は、普通は下記のように思考しながら読んでいきます。(各行の;; 以降が思考内容です。)

;; defunがあるから、関数定義だなあ。
;; その次には関数名がくるはず。regexp-opt-depthという関数の定義をするんだなあ。
;; regexpという引数一つをとるんだなあ。
(defun regexp-opt-depth (regexp)

  ;; ネストされたところからカッコが始まっている。
  ;; 関数の処理の本体がここから始まるんだなあ。
  ;; save-match-dataを使っているんだな。
  (save-match-data

    ;; さらにネストされた位置にstring-matchの呼び出しがあるなあ。
    (string-match regexp "")

    ;; string-matchが終わったらletを呼び出すんだなあ。
    ;; letは変数の定義だからcountが0、startとlastは定義だけしてるんだなあ。
    (let ((count 0) start last)

      ;; 変数の定義(let)の中にwhileの呼び出しがあるなあ。whileはループ文だなあ
      ;; (string-match… 部分がループ条件か。
      (while (string-match "\\\\(\\(\\?[0-9]*:\\)?" regexp start)

        ;; こっからwhileのループ処理本体だなあ。
        ;; setqは変数代入だなあ。start変数の書き換えかあ。
        (setq start (match-end 0))

        ;; ループ処理の最後にwhenで条件を満たした場合のみの処理を書いているなあ。
        ;; インデント的に(and (not …) (subregexp-context-p ...))が条件か。
        (when (and (not (match-beginning 1))
                           (subregexp-context-p regexp (match-beginning 0) last))

          ;; 条件満たしたらsetqを2つやるんだなあ。
          (setq last start)
          (setq count (1+ count))))

      ;; インデントから見て、letの直下の処理で、最後にcountを返却しているんだなあ。
      count)))

上記の読み方のどこにも遠く離れたカッコの個数や対応を数える兆候が見られないことに注目してください。

カッコの対応を知るのにカッコの数ではなく、(が出現するインデント位置しか見ていません。

(局所的に近場のカッコの1つ2つは数えています。ただそれぐらいは通常の人間ができる芸当の範疇だと思います。)

このようにLispプログラムはインデントでしか読まないのが当たり前なので、逆にLispプログラムを書く場合はインデントで構造が読めるように配置しなければ相当読みづらいといえるでしょう。(普通はエディタが勝手にインデントとってくれます)

開きカッコのインデント位置は気にしますが、閉じカッコといえば、上記のインデントを守っていればただの開きカッコのつじつま合わせにしか過ぎないので、一箇所に集められるだけ集められているのがわかるでしょうか? count)))) などとなっている部分がそうですね。

このようにLispプログラムの構造は、構文上の絶対の規制はないものの、インデントで視覚的に示します。考え方はPythonHaskellCoffeeScriptと同じですね。JavaやCでもまともなプログラムなら構文に沿ってインデントをつけるはずです。

カッコを作る側の話

で、インデントで構造を示すのはいいんですが、インデントなぞただの努力目標、本質的にプログラムの構造はカッコの対応で示されます。(意地悪でカッコに反するインデントをすることも可能です。)

海千山千のLISPerはこれら大量のカッコをいちいちバランスとれるように開きの数と閉じの数を数えながら、Lispプログラムを編集しているのかというと、もちろんNoです。エディタの機能でどうにかします。

普通はpareditというカッコのバランスとったままカッコ単位の各種編集ができる便利なEmacsマクロを使います。これによりほとんどカッコの対応を崩さずに編集可能になります。逆に言うとこれがないとLispなんてやってられません。

Lispではすべてがカッコなので、pareditで好きな単位の式を綺麗に抜き取ることも可能です。

カッコ単位の編集に特化している感じですね。

カッコになっていれば、全部同じ方法で編集できるので、Lisperにとってすべてがカッコの世界はとてもハッピーかもしれません。

まとめ

カッコは怖くないよ!!

2014-08-05 追記

すごいブックマークついてる!!

Lispのカッコよりみなさんの忌憚なきコメントのほうがLisp初心者の僕にとっては怖いですね。

nazoking ((はてなブログで((((gyazo)に置かれた(gifアニメ)のURL)をツイッターでシェア)したツイート)を貼り付け)していて、結果gifアニメが動いていないという悲劇

すんません次からはちゃんとやります

Lispの魅力伝えられてないよ

まず、カッコごときでLispのことを食わず嫌いにならないで欲しいと思いました。

マクロとかは後でいいかと。できればハッカーと画家でも読んでもらえれば。

countの後ろのかっこの数

これは普通にカッコの釣り合いをとってくれるエディタで書いていけば、開き-閉じかっこの数なんかはずっと調整が取れている状態になり、気にしなくてもちゃんとなるようになってます。

Pythonとかでいいじゃん

今回書いたのは単にLispのカッコを恐れる必要がない理由だけですので、PythonLispと同じ土俵に立っているわけではありません。

マクロ機能はもちろん、各Lisp系言語ごとの目玉機能も違いがありますからね。

Lispの利点は他の言語で構文木取り扱う場合にASTパーサ持ち出したり、プリプロセッサだの普段使わない道具を持ってこざるをえなかったりしなきゃいけないといったことがないことです。以前のC++のように>>がテンプレート構文としてダメだどうかとかもありません。これはひたすらカッコしかないお陰です。

ひたすらカッコしかないお陰で、カッコ編集機能だけでいろんなLisp系言語(Common LispSchemeClojure、EmacsLisp)をカバーできたりします。これは他の言語には真似できないところでもあるし、永遠にカッコから脱却できない理由でもあるんじゃないでしょうか。

まあ、本質的には木構造的な何かが表せられればいいので、別にカッコじゃなくてもいいと思います。(編集は面倒そうだが)

emacs

今回はEmacsのpareditを紹介しましたが、vimや他IDEでもたぶんまともに編集できる環境はあるはずです。

LOL(let over lambda - http://letoverlambda.com/ )の人はvimで編集しているらしいです。

Clojure

にゃんぱすー!

tanimina: cf. 「S式の読みやすさ」http://blog.practical-scheme.net/shiro/20120823a-s-expression

このエントリの意味ないやん…

Shiroさんのサイトには全ての答えがありますね…

読み方がわかった、怖くなくなった、なるほど など

あなたたちを待っていました!

ほかみなさん

コメントありがとうございました。

ちなみに、私はもっぱら何か考える時はCoffeeScriptで考えます。

ま、普通に 1+2 とか i++ とか書きたいし、関数は (x) -> (y) -> x + y とかすっきり書けるし、分配もあるし、リスト内包記法みたいなのもあるし?

しかしCoffeeScriptでインデントがとち狂い始めた時、Lispのほうが私の木構造への意図がコードに残り続るし、カッコの編集楽でいいなあと思ったりします。

っていうかいろんな言語がわざわざASTとか作んないでさあ、S式に一度なってくれればいいんだよねー。

転職しました

(※古巣への不満とか、そういうのは無しです)

f:id:knjname:20140729003759p:plain

転職しました。

みなさま、その節は大変お世話になりました。

これからも変わらずプログラマとして、皆様に笑顔になっていたけるよう精進してまいります。

(一部の方へ)飲み会など良い機会ありましたら、またご一緒させてください。

FindBugs 3.0.0 (Java8対応) リリースされてた

http://findbugs.sourceforge.net/

FindBugs 3.0.0が昨日リリースされていたようです!(Eclipseプラグインもリリースされています)

Java8対応になりました!

はっきりいって https://mailman.cs.umd.edu/pipermail/findbugs-discuss/2014-May/003995.html このMLのスレッド読んだ時はもう年内は絶望的だと思っていましたが、よかったー。

これまでJava7ターゲットでクラスファイルを出そうがJava8でFindBugsを動かす限り落ちていたので、とても助かります。

で、さっそく私も使い始めましたが、ちゃんと動いているようです。(注意される警告がやや増えた気がする)

多くのJava8移行者にとって、EclipseFindBugsCheckstyleがJava8未対応というのがかなりの痛手でしたが、先月末からEclipse Lunaがリリースされ、そしてFindBugsがリリースされ、状況がかなり改善されてきてますね。

あとはCheckstyleを待つのみです。

(しかし、本当に人の善意に頼ってOSSは成り立っているものだと感じました。)

追記:CheckstyleのJava8対応について

https://github.com/checkstyle/checkstyle/issues/10

sabaka commented on 14 May Hi! It is my GSOC issue. It has to be done till 18th of August, but I'm going to finish in July.

Also, after discuss with team, we decide, that implementation of ignoring option for Java 8 features is painful, and may break grammar. Unfortunately community has to wait for full implementation of Java 8 features.

プロジェクトメンバの立ち位置がよくわかんないですが、これを見る限りでは、とりあえず対応ではなく、ちゃんとしたJava8対応を8月半ばまでに投入予定みたいですね。