最初に書いておきます、未解決です。
Unsolved!
(6/19 追記)
コンパイル、通せるようになりました!
http://d.hatena.ne.jp/Kazuhira/20130619/1371647811
この前、InfinispanのTree APIを使おうとして、sbt+Scalaでビルドに失敗するということを書きましたが、Twitterでもちょこっとつぶやいていました。
sbtで、Infinispan Tree APIを使おうとすると、”Fqn.class is broken”、”bad constant pool”言われるんですが…
2013-06-13 22:12:39 via web
が、これを目に留めた方がいたようで(Infinispanの中の方??)、こんなツッコミをもらいました…。
@kazuhira_r Hmmm, can you create a JIRA in URL and explain us the problem?
2013-06-18 01:13:29 via TweetDeck to @kazuhira_r
それが昨日の深夜の話でして、JIRAで説明してと言われましても、JIRAがちょっとよくわからないし、説明できる自信ないし、そもそも時間も遅すぎたので(すげー言い訳)、お断りしたところ
@kazuhira_r If you ever give it a go again, it'd be good to debug it
2013-06-18 02:00:05 via TweetDeck to @kazuhira_r
デバッグしてみなよ的なことを言われたわけで…。
ちょっとだけ、頑張ってみることにしました。
ちなみに、前回はsbt+Scalaのビルドで失敗し、Gradle+Javaの組み合わせで成功しています。
準備
まずは、使う環境から。
Java
$ java -version java version "1.7.0_21" Java(TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)
sbt
> sbt-version [info] 0.12.3
Gradle
$ gradle -version ------------------------------------------------------------ Gradle 1.6 ------------------------------------------------------------ Gradle build time: 2013年5月7日 9時12分14秒 UTC Groovy: 1.8.6 Ant: Apache Ant(TM) version 1.8.4 compiled on May 22 2012 Ivy: 2.2.0 JVM: 1.7.0_21 (Oracle Corporation 23.21-b01) OS: Linux 3.8.0-25-generic amd64
実行のバリエーションをいくつか用意します。
sbt+Scala
build.sbt
scalaVersion := "2.10.2" resolvers += "JBoss Public Maven Repository Group" at "http://repository.jboss.org/nexus/content/groups/public-jboss/" libraryDependencies += "org.infinispan" % "infinispan-tree" % "5.3.0.CR2"
ムダに、Infinispan 5.3.0.CR2。まあ、他のバージョンを選んでも特に動きは変わりませんが…。
src/main/scala/InfinispanTreeExample.scala
import org.infinispan.manager.DefaultCacheManager import org.infinispan.tree.{TreeCacheFactory, TreeCache} object InfinispanTreeExample { def main(args: Array[String]): Unit = { val manager = new DefaultCacheManager val cache = manager.getCache[String, String]() val treeCache: TreeCache[String, String] = new TreeCacheFactory().createTreeCache(cache) } }
$ sbt [info] Set current project to default-ea72c1 (in build file:/xxxxx/) > compile [info] Updating {file:/xxxxx/}default-ea72c1... [info] Resolving org.jboss#staxmapper;1.1.0.Final ... [info] Done updating. [info] Compiling 1 Scala source to /xxxxx/target/scala-2.10/classes... [warn] Class net.jcip.annotations.Immutable not found - continuing with a stub. [warn] Caught: java.lang.NullPointerException while parsing annotations in /home/xxxxx/.ivy2/cache/org.infinispan/infinispan-tree/bundles/infinispan-tree-5.3.0.CR2.jar(org/infinispan/tree/Fqn.class) [error] error while loading Fqn, class file '/home/xxxxx/.ivy2/cache/org.infinispan/infinispan-tree/bundles/infinispan-tree-5.3.0.CR2.jar(org/infinispan/tree/Fqn.class)' is broken [error] (class java.lang.RuntimeException/bad constant pool index: 0 at pos: 8277) [warn] two warnings found [error] one error found [error] (compile:compile) Compilation failed [error] Total time: 9 s, completed 2013/06/18 23:06:13
やっぱり、コンパイルに失敗します。
原因は、
org.infinispan.tree.Fqn
というクラスがおかしい
[error] error while loading Fqn, class file '/home/xxxxx/.ivy2/cache/org.infinispan/infinispan-tree/bundles/infinispan-tree-5.3.0.CR2.jar(org/infinispan/tree/Fqn.class)' is broken [error] (class java.lang.RuntimeException/bad constant pool index: 0 at pos: 8277)
って言ってますね。
sbt+Java
build.sbt
version := "0.0.1-SNAPSHOT" resolvers += "JBoss Public Maven Repository Group" at "http://repository.jboss.org/nexus/content/groups/public-jboss/" libraryDependencies += "org.infinispan" % "infinispan-tree" % "5.3.0.CR2"
src/main/java/InfinispanTreeExample.java
import org.infinispan.Cache; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.tree.TreeCache; import org.infinispan.tree.TreeCacheFactory; public class InfinispanTreeExample { public static void main(String[] args) throws Exception { DefaultCacheManager manager = new DefaultCacheManager(); Cache<String, String> cache = manager.getCache(); TreeCache<String, String> treeCache = new TreeCacheFactory().createTreeCache(cache); } }
$ sbt [info] Set current project to default-803641 (in build file:/xxxxx/) > compile [info] Updating {file:/xxxxx/}default-803641... [info] Resolving org.jboss#staxmapper;1.1.0.Final ... [info] Done updating. [info] Compiling 1 Java source to xxxxx/target/scala-2.9.2/classes... [success] Total time: 4 s, completed 2013/06/18 23:09:21
こちらは、コンパイルに成功しました。
Gradle+Scala
build.gradle
apply plugin: 'scala' repositories { mavenCentral() maven { url 'https://repository.jboss.org/nexus/content/groups/public' } } dependencies { compile 'org.scala-lang:scala-library:2.10.2' compile 'org.infinispan:infinispan-tree:5.3.0.CR2' }
src/main/scala/InfinispanTreeExample.scala
import org.infinispan.manager.DefaultCacheManager import org.infinispan.tree.{TreeCacheFactory, TreeCache} object InfinispanTreeExample { def main(args: Array[String]): Unit = { val manager = new DefaultCacheManager("infinispan.xml") val cache = manager.getCache[String, String]() val treeCache: TreeCache[String, String] = new TreeCacheFactory().createTreeCache(cache) } }
$ gradle compileScala :compileJava UP-TO-DATE :compileScala [ant:scalac] warning: Class net.jcip.annotations.Immutable not found - continuing with a stub. [ant:scalac] warning: Caught: java.lang.NullPointerException while parsing annotations in /home/xxxxx/.gradle/caches/artifacts-24/filestore/org.infinispan/infinispan-tree/5.3.0.CR2/bundle/aeb1b651609799b60df6a12e7805211fb2681606/infinispan-tree-5.3.0.CR2.jar(org/infinispan/tree/Fqn.class) [ant:scalac] error: error while loading Fqn, class file '/home/xxxxx/.gradle/caches/artifacts-24/filestore/org.infinispan/infinispan-tree/5.3.0.CR2/bundle/aeb1b651609799b60df6a12e7805211fb2681606/infinispan-tree-5.3.0.CR2.jar(org/infinispan/tree/Fqn.class)' is broken [ant:scalac] (class java.lang.RuntimeException/bad constant pool index: 0 at pos: 8277) [ant:scalac] two warnings found [ant:scalac] one error found :compileScala FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':compileScala'. > Compile failed with 1 error; see the compiler error output for details. * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED Total time: 17.244 secs
お?こっちも失敗した??
Gradle+Java
build.gradle
apply plugin: 'java' repositories { mavenCentral() maven { url 'https://repository.jboss.org/nexus/content/groups/public' } } dependencies { compile 'org.infinispan:infinispan-tree:5.3.0.CR2' }
src/main/java/InfinispanTreeExample.java
import org.infinispan.Cache; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.tree.TreeCache; import org.infinispan.tree.TreeCacheFactory; public class InfinispanTreeExample { public static void main(String[] args) throws Exception { DefaultCacheManager manager = new DefaultCacheManager(); Cache<String, String> cache = manager.getCache(); TreeCache<String, String> treeCache = new TreeCacheFactory().createTreeCache(cache); } }
$ gradle compileJava
:compileJava
BUILD SUCCESSFUL
Total time: 6.915 secs
まあ、こちらは普通に成功します。
ということは?
というわけで、sbtもGradleも何も使わずに、素のscalacで試してみることに。
Infinispanのダウンロードページより、5.3.0.CR2をダウンロードして、必要なJARファイルだけ取り出してきました。
http://www.jboss.org/infinispan/downloads
$ ll 合計 5620 drwxrwxr-x 3 xxxxx xxxxx 12288 Jun 18 23:16 ./ drwxrwxr-x 7 xxxxx xxxxx 4096 Jun 18 21:19 ../ -rw-rw-r-- 1 xxxxx xxxxx 374 Jun 18 21:19 InfinispanTreeExample.scala -rw-r--r-- 1 xxxxx xxxxx 2661154 Jun 17 18:16 infinispan-core-5.3.0.CR2.jar -rw-r--r-- 1 xxxxx xxxxx 67332 Jun 17 18:19 infinispan-tree.jar -rw-rw-r-- 1 xxxxx xxxxx 60796 Mar 25 12:23 jboss-logging-3.1.1.GA.jar -rw-rw-r-- 1 xxxxx xxxxx 229949 Mar 25 12:23 jboss-marshalling-1.3.15.GA.jar -rw-rw-r-- 1 xxxxx xxxxx 82089 Mar 25 12:23 jboss-marshalling-river-1.3.15.GA.jar -rw-rw-r-- 1 xxxxx xxxxx 11209 Mar 25 12:23 jboss-transaction-api_1.1_spec-1.0.0.Final.jar -rw-rw-r-- 1 xxxxx xxxxx 2254 Mar 25 12:22 jcip-annotations-1.0.jar -rw-r--r-- 1 xxxxx xxxxx 2079265 Jun 7 10:06 jgroups-3.3.1.Final.jar -rw-rw-r-- 1 xxxxx xxxxx 481535 Mar 25 12:22 log4j-1.2.16.jar -rw-rw-r-- 1 xxxxx xxxxx 36001 Mar 25 12:23 staxmapper-1.1.0.Final.jar
使うScalaコードは同じです。
では、コンパイル。
$ scalac -classpath "*.jar" InfinispanTreeExample.scala $
予想に反して、コンパイルが通りましたが…。
もう意味分からんのですが…。ということは、sbtとかGradleを介しているのがNGということ??
Gradleでデバッグしてみる
いくつか試していて、GradleではscalacのAntタスクを使っていることがわかったので、scalacのコードを眺めつつ、先ほどの、Gradle+Scalaで使ったbuild.gradleに
compileScala {
compileScala.scalaCompileOptions.additionalParameters= ['-Ydebug']
}
を加えて実行。
ものすごーくスタックトレースが流れますが、コケている直接の原因はここっぽいです。
[ant:scalac] java.lang.RuntimeException: bad constant pool index: 0 at pos: 8277 [ant:scalac] at scala.tools.nsc.symtab.classfile.ClassfileParser$ConstantPool.scala$tools$nsc$symtab$classfile$ClassfileParser$ConstantPool$$errorBadIndex(ClassfileParser.scala:406) [ant:scalac] at scala.tools.nsc.symtab.classfile.ClassfileParser$ConstantPool.getName(ClassfileParser.scala:154) [ant:scalac] at scala.tools.nsc.symtab.classfile.ClassfileParser.scala$tools$nsc$symtab$classfile$ClassfileParser$$parseAttribute$1(ClassfileParser.scala:849) [ant:scalac] at scala.tools.nsc.symtab.classfile.ClassfileParser.parseAttributes(ClassfileParser.scala:1066) [ant:scalac] at scala.tools.nsc.symtab.classfile.ClassfileParser.parseClass(ClassfileParser.scala:551) [ant:scalac] at scala.tools.nsc.symtab.classfile.ClassfileParser.parse(ClassfileParser.scala:88) [ant:scalac] at scala.tools.nsc.symtab.SymbolLoaders$ClassfileLoader.doComplete(SymbolLoaders.scala:261) [ant:scalac] at scala.tools.nsc.symtab.SymbolLoaders$SymbolLoader.complete(SymbolLoaders.scala:194) [ant:scalac] at scala.tools.nsc.symtab.SymbolLoaders$SymbolLoader.load(SymbolLoaders.scala:210) [ant:scalac] at scala.reflect.internal.Symbols$Symbol.typeParams(Symbols.scala:1480) [ant:scalac] at scala.reflect.internal.Types$NoArgsTypeRef.typeParams(Types.scala:2136) [ant:scalac] at scala.reflect.internal.Types$NoArgsTypeRef.isHigherKinded(Types.scala:2135) [ant:scalac] at scala.reflect.internal.transform.UnCurry$class.scala$reflect$internal$transform$UnCurry$$expandAlias(UnCurry.scala:13) [ant:scalac] at scala.reflect.internal.transform.UnCurry$$anon$2.apply(UnCurry.scala:17) [ant:scalac] at scala.reflect.internal.Types$TypeMap$$anonfun$noChangeToSymbols$1.apply(Types.scala:4272) [ant:scalac] at scala.reflect.internal.Types$TypeMap$$anonfun$noChangeToSymbols$1.apply(Types.scala:4272)
Scala CompilerのClassfileParserで、コケていらっしゃる??
以下、 scala/tools/nsc/symtab/classfile/ClassfileParser.scala より。
ここのクラスを解析しているところで
def parse(file: AbstractFile, root: Symbol): Unit = { debuglog("[class] >> " + root.fullName) pushBusy(root) { this.in = new AbstractFileReader(file) this.clazz = if (root.isModule) root.companionClass else root // WARNING! do no use clazz.companionModule to find staticModule. // In a situation where root can be defined, but its companionClass not, // this would give incorrect results (see SI-5031 in separate compilation scenario) this.staticModule = if (root.isModule) root else root.companionModule this.isScala = false parseHeader this.pool = new ConstantPool parseClass() } }
追っていって、ここの最後のConstantPool#getName(index: Int)を呼び出し
def parseAttributes(sym: Symbol, symtype: Type) { def convertTo(c: Constant, pt: Type): Constant = { if (pt.typeSymbol == definitions.BooleanClass && c.tag == IntTag) Constant(c.value != 0) else c convertTo pt } def parseAttribute() { val attrName = pool.getName(in.nextChar).toTypeName
その先で、indexの値が0ということでエラーケースに落ちているようです。
/** Return the name found at given index. */ def getName(index: Int): Name = { if (index <= 0 || len <= index) errorBadIndex(index)
最終的に、例外をスローしているのはここですね。
/** Throws an exception signaling a bad constant index. */ private def errorBadIndex(index: Int) = throw new RuntimeException("bad constant pool index: " + index + " at pos: " + in.bp)
クラスファイルの属性(Signature、InnerClasses、RuntimeVisibleAnnotationsとか)を解析している時に、その位置情報が不正だということですが…。
とまあ、コケている場所はわかったのですが、Fqnのクラスファイルのいったい何が気に入らないかまでは、結局わからないまま今日はタイムアップ。
いったん、ここまでかなぁ…。