GroovyでJenkinsプラグインを作っていて、ちょっとしたリファクタリングだけのアップデートなのにプラグイン内でエラーをはいてJenkinsプラグインのロードに失敗したことがありました
今回はその対処方法です
tl;dr
コードレベルで差分がなければコンパイラを疑え
エラー内容
./gradlew server
(略)
Jenkins home directory: /Users/sueyoshi_go/workspace/github.com/jenkinsci/yaml-axis-plugin/work found at: System.getProperty("JENKINS_HOME")
Failed to instantiate Key[type=org.jenkinsci.plugins.yamlaxis.YamlAxis$DescriptorImpl, annotation=[none]]; skipping this component
com.google.inject.ProvisionException: Guice provision errors:
1) Error injecting constructor, java.lang.VerifyError: (class: org/jenkinsci/plugins/yamlaxis/YamlAxis, method: super$1$forEach signature: (Ljava/util/function/Consumer;)V) Illegal use of nonvirtual function call
at org.jenkinsci.plugins.yamlaxis.YamlAxis$DescriptorImpl.<init>(YamlAxis.groovy:80)
1 error
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:52)
at com.google.inject.Scopes$1$1.get(Scopes.java:65)
at hudson.ExtensionFinder$GuiceFinder$FaultTolerantScope$1.get(ExtensionFinder.java:427)
at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
at com.google.inject.internal.InjectorImpl$3$1.call(InjectorImpl.java:1005)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1051)
at com.google.inject.internal.InjectorImpl$3.get(InjectorImpl.java:1001)
at hudson.ExtensionFinder$GuiceFinder._find(ExtensionFinder.java:389)
at hudson.ExtensionFinder$GuiceFinder.find(ExtensionFinder.java:380)
at hudson.ClassicPluginStrategy.findComponents(ClassicPluginStrategy.java:386)
at hudson.ExtensionList.load(ExtensionList.java:300)
at hudson.ExtensionList.ensureLoaded(ExtensionList.java:253)
at hudson.ExtensionList.getComponents(ExtensionList.java:154)
at hudson.DescriptorExtensionList.load(DescriptorExtensionList.java:182)
at hudson.ExtensionList.ensureLoaded(ExtensionList.java:253)
at hudson.ExtensionList.iterator(ExtensionList.java:143)
at hudson.model.ComputerSet.<clinit>(ComputerSet.java:441)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at hudson.init.TaskMethodFinder.invoke(TaskMethodFinder.java:106)
at hudson.init.TaskMethodFinder$TaskImpl.run(TaskMethodFinder.java:176)
at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:282)
at jenkins.model.Jenkins$7.runTask(Jenkins.java:904)
at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:210)
at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.VerifyError: (class: org/jenkinsci/plugins/yamlaxis/YamlAxis, method: super$1$forEach signature: (Ljava/util/function/Consumer;)V) Illegal use of nonvirtual function call
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at hudson.model.Descriptor.<init>(Descriptor.java:284)
at hudson.matrix.AxisDescriptor.<init>(AxisDescriptor.java:43)
at org.jenkinsci.plugins.yamlaxis.YamlAxis$DescriptorImpl.<init>(YamlAxis.groovy)
at org.jenkinsci.plugins.yamlaxis.YamlAxis$DescriptorImpl$$FastClassByGuice$$9a80bc2f.newInstance(<generated>)
at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:61)
at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:108)
at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:88)
at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:269)
at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1058)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
... 29 more
エラー箇所
調査
バージョン間の差分を見てもどこが悪いのか分からず。。。(0.1.0が正常に動いていたバージョンで0.1.1がエラーになったバージョン)
ためしに正常に動いていたバージョンのtagをcheckoutしても同様のエラーが発生。
「コードレベルで差分がないならコンパイラが悪いのでは?」ということで調べたらビンゴでした 1
使ったJDKのバージョン
v0.1.0(正常に動いていたバージョン)をビルドしたJDK
$ java -v
openjdk version "1.7.0-u10-b09"
OpenJDK Runtime Environment (build 1.7.0-u10-b09-20121015)
OpenJDK 64-Bit Server VM (build 23.6-b03, mixed mode)
v0.1.1(エラーになったバージョン)をビルドしたJDK
$ java -v
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
ちなみにどうしてv0.1.0とv0.1.1でJDKのバージョンが違うのかというと、プラグイン開発のためローカルでJenkinsを動かすのが重いので途中からスペックの高いPC(JDK 8)を使うようにしたためです
最終的にはv0.1.0をビルドしたのと同じPC(JDK 7)でビルドしなおして動作確認とったらエラーが出なくなっているのを確認できたのでリリースしました。
教訓
ユニットテストがグリーンだからといって動作確認もせずにリリースしてはいけない
追記
GroovyでJDK 8サポートされたのは2.3からだった
The Groovy programming language - Groovy 2.3 release notes
Jenkinsとの兼ね合いでGroovyのバージョンは1.8.9に固定しているので 2、JDK 8だと正しくビルドできないってのはありそう。
-
さらっと書いていますがコンパイラにたどり着くまでに一晩かかってます ↩