1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SDKMANのJDKをSystem JDKとしてmacOSに誤認させる

Last updated at Posted at 2024-11-02

なぜ誤認させたい?

  • SDKMANをセットアップするとJAVA_HOMEをSDKMANがよしなにしてくれるようなる
  • /usr/bin/java, /usr/libexec/java_homeなどが変わらずSystem JDKの場所である/Library/Java/JavaVirtualMachines配下のJDKを参照する
  • XcodeのScriptPhaseなどJAVA_HOMEを見ず、強制的にSystem JDKを参照するライブラリやプラグイン類がいる
  • どうにかしてPCにinstallするJDKをSDKMANだけに寄せたいのでSDKMANでinstallしたJDKをSystem JDKに誤認させたい

SDKMAN以外のJDKはどうなっているか

  • システムのJDKは/Library/Java/JavaVirtualMachinesにinstallもしくはsymbolic linkを貼ったものであるパターンが多い
    • jdk.java.netからinstallする場合、tarファイルを/Library/Java/JavaVirtualMachinesに展開する
    • Homebrewでopenjdkをinstallする場合、システムが認識できるようにシンボリックリンクを貼るように表示される
    • For the system Java wrappers to find this JDK, symlink it with
      sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
      
      openjdk is keg-only, which means it was not symlinked into /opt/homebrew,
      because macOS provides similar software and installing this software in
      parallel can cause all kinds of trouble.
      
      If you need to have openjdk first in your PATH, run:
      echo 'export PATH="/opt/homebrew/opt/openjdk/bin:$PATH"' >> $HOME.zshrc
      
      For compilers to find openjdk you may need to set:
      export CPPFLAGS="-I/opt/homebrew/opt/openjdk/include"
      
  • /Library/Java/JavaVirtualMachinesにApplication Bundle形式でJDKが展開される
    • Distributionによって若干の差異はあるが以下のようなファイル構造になる
      •   /Library/Java/JavaVirtualMachines
          └── Contents
              ├── CodeResources
              ├── Home
              │   ├── bin
              │   ├── conf
              │   ├── include
              │   ├── jmods
              │   ├── legal
              │   ├── lib
              │   └── release
              ├── Info.plist
              ├── MacOS
              │   └── libjli.dylib
              └── _CodeSignature
                  └── CodeResources
        

SDKMANでinstallしたJDKはどうなっているか

  • 特別なinstall設定を行わない場合$HOME/.sdkman/candidates/java配下にinstallされる
  • Distributionによって若干の差異はあるが、以下のようなファイル構造になる
  • 概ねApplication Bundle形式のHomeディレクトリの内容だと考えていい
$HOME/.sdkman/candidates/java
└──17.0.13-tem
    ├── NOTICE
    ├── bin
    ├── conf
    ├── include
    ├── jmods
    ├── legal
    ├── lib
    ├── man
    └── release

System JDKとして認識されるためにはどうすればよいか

  • OpenJDKを参考にすると/Library/Java/JavaVirtualMachines/Contents配下にsymbolic linkとファイルを配置する必要がある
    • bin, conf各種があるHome
    • libjli.dylibがあるMacOS
    • Info.plistの作成

Home,MacOSディレクトリへのsymbolic link作成

  • SDKMANでinstallしたJDKのsymbolic linkを作成してあげればよい
# directoryの作成(sdkman.jdkは任意の名前)
sudo mkdir -p /Library/Java/JavaVirtualMachines/sdkman.jdk/Contents/Home
sudo mkdir -p /Library/Java/JavaVirtualMachines/sdkman.jdk/Contents/MacOS

# bin, conf, include, jmods, legal, lib系のsymbolic link作成
sudo ln -sfn ~/.sdkman/candidates/java/17.0.13-tem/* /Library/Java/JavaVirtualMachines/sdkman.jdk/Contents/Home

# libjli.dylibの位置ははDistributionによって異なるので注意する必要がある(↓はtemurinの場合)
sudo ln -sfn ~/.sdkman/candidates/java/17.0.13-tem/lib/libjli.dylib /Library/Java/JavaVirtualMachines/sdkman.jdk/Contents/MacOS/libjli.dylib

Info.plistの作成

  • Homebrewでopenjdkをinstallした際は/opt/homebrew/Cellar/openjdk/23/libexec/openjdk.jdk/Contentsに以下のInfo.plistが配置されている
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleExecutable</key>
    <string>libjli.dylib</string>
    <key>CFBundleGetInfoString</key>
    <string>OpenJDK 23</string>
    <key>CFBundleIdentifier</key>
    <string>net.java.openjdk.jdk</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>7.0</string>
    <key>CFBundleName</key>
    <string>OpenJDK 23</string>
    <key>CFBundlePackageType</key>
    <string>BNDL</string>
    <key>CFBundleShortVersionString</key>
    <string>23</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>0</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>The application is requesting access to the microphone.</string>
    <key>JavaVM</key>
    <dict>
        <key>JVMCapabilities</key>
        <array>
                <string>CommandLine</string>
        </array>
        <key>JVMMinimumFrameworkVersion</key>
        <string>13.2.9</string>
        <key>JVMMinimumSystemVersion</key>
        <string>11.00.00</string>
        <key>JVMPlatformVersion</key>
        <string>23</string>
        <key>JVMVendor</key>
        <string>Homebrew</string>
        <key>JVMVersion</key>
        <string>23</string>
    </dict>
</dict>
</plist>

  • Systemが最低限認識できるようにすると以下のようなInfo.plistになる
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleIdentifier</key>
    <string>sdkman.current.jdk</string>
    <key>CFBundleName</key>
    <string>SDKMAN current JDK</string>
    <key>CFBundleExecutable</key>
    <string>libjli.dylib</string>
    <key>JavaVM</key>
    <dict>
        <key>JVMCapabilities</key>
        <array>
            <string>CommandLine</string>
        </array>
        <key>JVMPlatformVersion</key>
        <string>${sdk current java}</string>
        <key>JVMVendor</key>
        <string>SDKMAN</string>
        <key>JVMVersion</key>
        <string>${sdk current java}</string>
    </dict>
</dict>
</plist>

要素さえ揃っていれば、CFBundleIdentifier, CFBundleName, JavaVMは任意の値で問題ない

結果

  • ここまで実施すると/usr/bin/java, /usr/libexec/java_homeがSDKMANでinstallしたJDKをSystem JDKとして認譋するようになる
$ where java
/usr/bin/java
$HOME/.sdkman/candidates/java/current/bin/java 

$ /usr/bin/java -version
openjdk version "17.0.13" 2024-10-15
OpenJDK Runtime Environment Temurin-17.0.13+11 (build 17.0.13+11)
OpenJDK 64-Bit Server VM Temurin-17.0.13+11 (build 17.0.13+11, mixed mode, sharing)

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (1):
    ${sdk current java} (arm64) "SDKMAN" - "SDKMAN current JDK" /Library/Java/JavaVirtualMachines/sdkman.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/sdkman.jdk/Contents/Home

Ref

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?