問題出現
一次項目更新後,發現項目無法正常 build 了,出現如下報錯:
error: cannot access DoNotMock
class file for com.google.errorprone.annotations.DoNotMock not found
定位問題
-
Review 代碼更新,尋找可疑點
這一步 review 沒有發現什麼特殊的改動,隻是更改了幾個 proto 檔案的定義。但是回退代碼後卻又能正常 build,是以說明建構失敗的确是此次更新引入的問題。
- 根據報錯資訊尋找問題根源
-
尋找錯誤包
看錯誤是類找不到的問題,那麼首先确定這個類是哪個包的;Google 了下,該類出現在 error-prone , 并且發現
從 2.3.0 開始就被移除掉了,相關讨論見 GITHUBDoNotMock
<dependency> <groupId>com.google.errorprone</groupId> <artifactId>error_prone_annotations</artifactId> <version>2.2.0</version> </dependency>
-
分析包依賴
從上面其實就可以看出這應該是一個依賴包不對帶來的問題。那麼此時就需要分析項目的依賴。重點檢視 error_prone_annotations 的相關依賴。分析如下(本來在 console 中 error_prone_annotations 有高亮的,貼上來就沒有了):
從上面可以看出,最終用的是 2.3.2 的$ ./gradlew dependencies -q --configuration compile | grep error_prone_annotations --color -C 10 compile - Dependencies for source set 'main' (deprecated, use 'implementation' instead). +--- net.xxxx.mshell:mshell-java-dropwizard-core:10.0.0 | +--- io.dropwizard:dropwizard-core:1.3.13 | | +--- io.dropwizard:dropwizard-util:1.3.13 | | | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0 -> 2.9.9 | | | +--- com.google.guava:guava:24.1.1-jre -> 27.1-jre | | | | +--- com.google.guava:failureaccess:1.0.1 | | | | +--- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava | | | | +--- com.google.code.findbugs:jsr305:3.0.2 | | | | +--- org.checkerframework:checker-qual:2.5.2 | | | | +--- com.google.errorprone:error_prone_annotations:2.2.0 -> 2.3.2 # here use error_prone_annotations 2.3.2 | | | | +--- com.google.j2objc:j2objc-annotations:1.1 | | | | \--- org.codehaus.mojo:animal-sniffer-annotations:1.17 | | | +--- com.google.code.findbugs:jsr305:3.0.2 | | | \--- joda-time:joda-time:2.10.1 | | +--- io.dropwizard:dropwizard-jackson:1.3.13 | | | +--- com.google.guava:guava:24.1.1-jre -> 27.1-jre (*) | | | +--- io.dropwizard:dropwizard-util:1.3.13 (*) | | | +--- com.fasterxml.jackson.core:jackson-core:2.9.9 | | | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0 -> 2.9.9 | | | +--- com.fasterxml.jackson.core:jackson-databind:2.9.9.1 -- -- | | | | +--- io.dropwizard:dropwizard-configuration:1.3.5 -> 1.3.13 (*) | | | | \--- org.apache.commons:commons-lang3:3.4 -> 3.8.1 | | | +--- com.google.protobuf:protobuf-java:3.6.0 -> 3.8.0 | | | \--- net.jodah:failsafe:2.0.1 | | +--- net.xxxx.experimentation:java-mr-hyde-client:0.5.1 (*) | | +--- io.dropwizard:dropwizard-logging:1.3.13 (*) | | +--- io.dropwizard:dropwizard-configuration:1.3.13 (*) | | +--- io.dropwizard:dropwizard-metrics:1.3.13 (*) | | +--- io.dropwizard.metrics:metrics-healthchecks:4.0.2 -> 4.0.5 (*) | | +--- org.slf4j:jcl-over-slf4j:1.7.25 -> 1.7.26 (*) | | \--- com.google.errorprone:error_prone_annotations:2.0.12 -> 2.3.2 # here use error_prone_annotations 2.3.2 | +--- net.xxxx.mshell:mshell-java-secrets:10.0.0 (*) | +--- net.xxxx.mshell:mshell-java-metrics:10.0.0 (*) | +--- net.xxxx.mshell:mshell-java-async-client:10.0.0 | | +--- org.asynchttpclient:async-http-client:2.4.9 | | | +--- org.asynchttpclient:async-http-client-netty-utils:2.4.9 | | | | +--- io.netty:netty-buffer:4.1.25.Final | | | | | \--- io.netty:netty-common:4.1.25.Final | | | | +--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26 | | | | \--- com.sun.activation:javax.activation:1.2.0 | | | +--- io.netty:netty-codec-http:4.1.25.Final -- -- | | | +--- com.lightstep.tracer:java-common:0.15.8 | | | | +--- io.opentracing:opentracing-api:0.31.0 | | | | +--- io.opentracing:opentracing-util:0.31.0 (*) | | | | +--- com.google.protobuf:protobuf-java:3.5.1 -> 3.8.0 | | | | \--- com.google.api.grpc:grpc-google-common-protos:1.12.0 | | | | +--- io.grpc:grpc-stub:1.10.1 -> 1.13.2 | | | | | \--- io.grpc:grpc-core:1.13.2 | | | | | +--- io.grpc:grpc-context:1.13.2 | | | | | +--- com.google.code.gson:gson:2.7 | | | | | +--- com.google.guava:guava:20.0 -> 27.1-jre (*) | | | | | +--- com.google.errorprone:error_prone_annotations:2.1.2 -> 2.3.2 # here use error_prone_annotations 2.3 | | | | | +--- com.google.code.findbugs:jsr305:3.0.0 -> 3.0.2 | | | | | +--- io.opencensus:opencensus-api:0.12.3 | | | | | \--- io.opencensus:opencensus-contrib-grpc-metrics:0.12.3 | | | | | \--- io.opencensus:opencensus-api:0.12.3 | | | | +--- io.grpc:grpc-protobuf:1.10.1 -> 1.13.2 | | | | | +--- io.grpc:grpc-core:1.13.2 (*) | | | | | +--- com.google.protobuf:protobuf-java:3.5.1 -> 3.8.0 | | | | | +--- com.google.guava:guava:20.0 -> 27.1-jre (*) | | | | | +--- com.google.api.grpc:proto-google-common-protos:1.0.0 -> 1.12.0 | | | | | | \--- com.google.protobuf:protobuf-java:3.5.1 -> 3.8.0 -- -- | | +--- io.prometheus:simpleclient:0.6.0 | | \--- io.dropwizard.metrics:metrics-core:3.1.2 -> 4.0.5 (*) | \--- javax.xml.bind:jaxb-api:2.3.1 | \--- javax.activation:javax.activation-api:1.2.0 \--- io.dropwizard.modules:dropwizard-protobuf:1.3.12-1 +--- io.dropwizard:dropwizard-core:1.3.12 -> 1.3.13 (*) +--- com.google.protobuf:protobuf-java:3.8.0 \--- com.google.protobuf:protobuf-java-util:3.8.0 +--- com.google.protobuf:protobuf-java:3.8.0 +--- com.google.guava:guava:26.0-android -> 27.1-jre (*) +--- com.google.errorprone:error_prone_annotations:2.3.2 # here use error_prone_annotations 2.3 \--- com.google.code.gson:gson:2.7
,該版本中是沒有error_prone_annotations
注解的。而 2.3.2 版本的DoNotMock
是由error_prone_annotations
引入。至此找到問題所在。就是包依賴的問題protobuf-java-util:3.8.0
-
解決問題
在上一步中已已經确定問題點,就是包依賴導緻的問題。那麼我們便可以着手解決問題,該問題可以有三個解決方案:
- 編譯時強制使用含
的DoNotMock
error_prone_annotations
implementation('com.google.errorprone:error_prone_annotations:2.2.0') { force = true }
- 在依賴中移除
error_prone_annotations:2.3.2
compile ("io.dropwizard.modules:dropwizard-protobuf:${dropwizardProtobufVersion}") { exclude group: 'com.google.errorprone', module: 'error_prone_annotations' }
- 更新所有依賴
的包,更新到新版不使用error_prone_annotations
;該方案影響較大。需要先全局查找使用了DoNotMock
的包。然後分析其使用依賴,再判斷是否能更新。DoNotMock
回顧問題
問題是解決了,但是有個疑問。此次更新中,我們并沒有更新相關的包依賴,為何以前 build 的時候沒有出錯,而這次卻出錯了呢?
這邊再次 Review 了下更新的代碼,再結合此前對包依賴的分析,發現了問題所在。此次更新中,我們在 proto 檔案中定義了 grpc 接口服務,而此服務的編譯依賴包
io.grpc
;即編譯 grpc 接口服務的包需要使用到相關的類,而這些類中有些使用了
DoNotMock
。而不幸的是,我們引用的其他包中使用了更新的
error_prone_annotations
,然該包中又不含
DoNotMock
,進而導緻了編譯錯誤。
error: cannot access DoNotMock
class file for com.google.errorprone.annotations.DoNotMock not found