調べるのに結構かかったので、備忘録として。
なお、今回参照した公式ドキュメントの選択肢は下記の通りです。
- React Native CLI Quickstart
- macOS
- Android
記事の要約
- React Native の公式ドキュメント通りに環境構築したけどエラーが起きたよ
-
sdkmanager
を起動するとNoClassDefFoundError
って言われたよ - なぜか
sdkmanager
が2つあって、もう片方のsdkmanager
はちゃんと動いたよ
ことの始まり
React Native でアプリ開発してイケイケになりたいという気持ちで環境構築を始めました。
参考にしたのは下記の公式ドキュメントです。
選択肢はそれぞれ下記の通りです。
- React Native CLI Quickstart
- macOS
- Android
ドキュメントに従い進めていきます。Android Studio は事前にインストールしてあったのでそちらを使います。
2. Install the Android SDK
の最後に「ANDROID_HOME
の設定が終われば sdkmanager
のコマンドが叩けるよ(意訳)」と書いてあったので、sdkmanager
を叩く前に 3. Configure the ANDROID_HOME environment variable
を進めました。
というわけで、設定を ~/.zshrc
に入れました。
# 不要な部分は省略
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
環境変数を適用するためにターミナルを再起動してから sdkmanager
を叩きました。
$ sdkmanager
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 5 more
うん?
調べたこと
さて、なんとかしなければReact Nativeを使うことができません。
Google先生で調べてみましたが、出てくるのはだいたい下記のような情報です。
自前のJava11じゃなくてAndroid Studio同梱のJava1.8を使えばOK
ところが、私のAndroid StudioにはJava11が同梱されています。
$ /Applications/Android\ Studio.app/Contents/jre/Contents/Home/bin/java --version
openjdk 11.0.11 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
OpenJDK 64-Bit Server VM (build 11.0.11+0-b60-7590822, mixed mode)
また、公式ドキュメントでもJava11を導入するように指示があります。
Java Development Kit
We recommend installing JDK using Homebrew. Run the following commands in a Terminal after installing Homebrew:brew install --cask adoptopenjdk/openjdk/adoptopenjdk11
Java1.8を利用するのは想定されていないと考えるのが妥当でしょう。
とはいえ、そこから答えに辿り着くのが結構大変でした。
解決策
解決策が見つかったのは下記のページです。
which sdkmanager -> this should point to /Users/brunnock/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager
sdkmanager --version -> this should show 6.0
sdkmanager
のパスとバージョンが指示されていますね。
バージョンについてはlatest
(6.0)しかインストールしていないので大丈夫だと思います。
一方で、パスについては下記の通りに指定したはずです。
# 不要な部分は省略
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin # ←ココ
export PATH=$PATH:$ANDROID_HOME/platform-tools
つまり、指定するsdkmanager
のパスが誤っているように思えます。
そこで上記を修正して再度sdkmanager
を叩いてみましょう。
# 不要な部分は省略
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
# export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin # 追加
$ sdkmanager
[=======================================] 100% Computing updates...
やったぜ!
って誤っていた方のパス、公式ドキュメントの指定だったはずですが……うーん?
エラーの原因
せっかくなのでもう少し確認してみましょう。
エラーの起きた方のsdkmanager
と正常に動作した方のsdkmanager
を比較してみます。
#!/usr/bin/env sh
##############################################################################
##
## sdkmanager start up script for UN*X
##
##############################################################################
# 以下省略
#!/usr/bin/env sh
##############################################################################
##
## sdkmanager start up script for Mac
##
##############################################################################
# 以下省略
ここでは省略して一部分しか載せていませんが、何箇所か違いがありました。
差分を見る限り、正常に動作したのはMac用の sdkmanager
のようです。
つまり、Mac用ではない sdkmanager
を使っていたから想定通りにシェルスクリプトが動作せずにエラーが起きていたんですね。
なぜ指定のディレクトリにMac用ではない sdkmanager
がいたのかは結局わからずじまいですが……
Android Studioは事前にインストールしてあったのでドキュメント通りの操作ではなく、もしかしたらそれが原因かなぁとも思いますが、確認はしていないです。
終わりに
というわけで、Macで sdkmanager
に NoClassDefFoundError
と言われたらパスの指定が誤っていることを疑ってみてもいいかも、という話でした。