SDKMAN ile Çoklu Java Sürümü Yönetimi
Birden fazla Java projesi üzerinde çalışan her geliştirici ya da sistem yöneticisi şu problemle karşılaşmıştır: bir proje Java 8 istiyor, diğeri Java 17, bir diğeri ise Java 21. Sistem genelinde tek bir Java sürümü kurulu olduğunda bu durum ciddi baş ağrısına dönüşür. JAVA_HOME değişkenini her seferinde elle güncellemek, sembolik linkleri yönetmek, farklı JDK paketlerini farklı dizinlere kurup her geçişte ortam değişkenlerini düzenlemek… Tüm bunlar hem zaman kaybettirir hem de hata yapmaya çok açıktır. İşte tam bu noktada SDKMAN devreye giriyor.
SDKMAN Nedir ve Neden Kullanmalısınız
SDKMAN (Software Development Kit Manager), JVM tabanlı diller ve araçlar için geliştirilmiş bir sürüm yönetim aracıdır. Java, Kotlin, Groovy, Scala, Maven, Gradle gibi onlarca SDK’yı kolayca kurmanızı, yönetmenizi ve farklı sürümler arasında geçiş yapmanızı sağlar. Bash üzerine inşa edilmiştir, dolayısıyla Linux ve macOS üzerinde sorunsuz çalışır. Windows için WSL (Windows Subsystem for Linux) kullanılabilir.
SDKMAN’in temel avantajları şöyle sıralanabilir:
- Çoklu sürüm desteği: Aynı anda onlarca farklı Java sürümünü kurulu tutabilirsiniz.
- Proje bazlı sürüm sabitleme:
.sdkmanrcdosyası sayesinde her projeye özel JDK sürümü tanımlayabilirsiniz. - Otomatik ortam yönetimi:
JAVA_HOMEvePATHdeğişkenleri otomatik olarak güncellenir. - Geniş dağıtım desteği: Oracle JDK, OpenJDK, GraalVM, Temurin, Zulu, Corretto gibi pek çok JDK dağıtımını destekler.
- Minimal bağımlılık: Sadece
bash,curl,zipveunzipyeterlidir.
SDKMAN Kurulumu
Kurulum son derece basittir. Terminal açıp şu komutu çalıştırmanız yeterli:
curl -s "https://get.sdkman.io" | bash
Kurulum tamamlandıktan sonra SDKMAN’i mevcut oturuma yüklemek için:
source "$HOME/.sdkman/bin/sdkman-init.sh"
Bu satır aynı zamanda ~/.bashrc ve ~/.zshrc dosyalarına otomatik olarak eklenir, dolayısıyla yeni terminal oturumlarında SDKMAN otomatik olarak aktif olur. Kurulumun başarılı olduğunu doğrulamak için:
sdk version
Çıktı olarak SDKMAN x.y.z gibi bir versiyon numarası görmelisiniz. Eğer sdk komutu bulunamıyorsa shell’i yeniden başlatın ya da source komutunu tekrar çalıştırın.
Kurulum sırasında SDKMAN, ~/.sdkman/ dizinini oluşturur. Bu dizin altında tüm SDK’larınız, konfigürasyonlarınız ve betikler yer alır:
- ~/.sdkman/bin/: SDKMAN’in ana başlatma betiği
- ~/.sdkman/candidates/: Kurulu tüm SDK’ların bulunduğu yer
- ~/.sdkman/etc/config: SDKMAN konfigürasyon dosyası
Mevcut Java Sürümlerini Listeleme
SDKMAN üzerinden kurulabilecek Java sürümlerini görmek için:
sdk list java
Bu komut size oldukça uzun bir liste getirir. Listede her satırda dağıtım adı (Vendor), sürüm numarası, dağıtım türü ve tanımlayıcı (Identifier) yer alır. Kurulu olanlar >>> işaretiyle, aktif olan ise ayrıca işaretlenmiş şekilde gösterilir.
Listeden birkaç örnek tanımlayıcı:
- 21.0.3-tem: Eclipse Temurin JDK 21
- 17.0.11-tem: Eclipse Temurin JDK 17
- 8.0.412-tem: Eclipse Temurin JDK 8
- 21.0.3-graalce: GraalVM Community Edition 21
- 17.0.11-amzn: Amazon Corretto 17
- 21.0.3-oracle: Oracle JDK 21
Sadece belirli bir dağıtıma ait sürümleri filtrelemek için grep kullanabilirsiniz:
sdk list java | grep "tem"
Java Kurulumu
Belirli bir sürümü kurmak için sdk install komutunu kullanırsınız. Tanımlayıcıyı sdk list java çıktısından kopyalayıp yapıştırmanız yeterlidir:
sdk install java 21.0.3-tem
Kurulum sırasında SDKMAN, ilgili JDK’yı indirir, ~/.sdkman/candidates/java/ altına açar ve sizden bu sürümü varsayılan yapmak isteyip istemediğinizi sorar. İlk kurulumda “yes” diyebilirsiniz.
Birden fazla sürüm kuralım:
sdk install java 17.0.11-tem
sdk install java 11.0.23-tem
sdk install java 8.0.412-tem
Her kurulumun ardından sürüm değiştirebilir ya da kurulumu tamamlayıp daha sonra geçiş yapabilirsiniz. Kurulu sürümleri görmek için:
sdk list java | grep "installed|local|>>>"
Ya da daha temiz bir çıktı için:
sdk current java
Bu komut şu anda aktif olan Java sürümünü gösterir.
Sürümler Arası Geçiş
Geçici Geçiş (Sadece Mevcut Terminal Oturumu için)
Bir sürümü sadece açık olan terminal penceresinde kullanmak istiyorsanız:
sdk use java 17.0.11-tem
Bu komut yalnızca mevcut shell oturumunu etkiler. Yeni bir terminal açtığınızda varsayılan sürüme dönülür. Bir CI/CD pipeline’ında ya da test scriptinde belirli bir Java sürümüyle çalışmak istediğinizde bu yöntemi kullanabilirsiniz.
Kalıcı Varsayılan Değiştirme
Sistem genelindeki varsayılan Java sürümünü değiştirmek için:
sdk default java 21.0.3-tem
Bu komuttan sonra yeni açacağınız tüm terminal oturumlarında Java 21 aktif olacaktır. JAVA_HOME ve PATH değişkenleri de buna göre güncellenir.
Güncel durumu doğrulamak için:
java -version
echo $JAVA_HOME
Proje Bazlı Sürüm Yönetimi: .sdkmanrc
SDKMAN’in en güçlü özelliklerinden biri, proje dizinine .sdkmanrc dosyası ekleyerek o projeye özel SDK sürümleri tanımlayabilmektir. Bu özelliği aktif etmek için önce konfigürasyonu düzenlemeniz gerekir:
nano ~/.sdkman/etc/config
Şu satırı bulun ve true yapın:
sdkman_auto_env=true
Artık bir proje dizinine girdiğinizde SDKMAN otomatik olarak o dizindeki .sdkmanrc dosyasını okur ve belirtilen sürüme geçer.
Bir proje dizininde .sdkmanrc dosyası oluşturmak için:
cd /home/kullanici/projeler/eski-proje
sdk env init
Bu komut, şu anda aktif olan Java sürümüyle bir .sdkmanrc dosyası oluşturur. İçeriğini düzenleyebilirsiniz:
cat .sdkmanrc
java=8.0.412-tem
maven=3.9.6
Farklı bir proje için Java 21 gerekiyorsa:
cd /home/kullanici/projeler/yeni-proje
sdk env init
# Sonra .sdkmanrc dosyasını düzenleyin
echo "java=21.0.3-tem" > .sdkmanrc
Artık eski-proje dizinine girdiğinizde Java 8, yeni-proje dizinine girdiğinizde Java 21 otomatik olarak aktif olur. Dizinden çıktığınızda varsayılan sürüme geri dönülür.
.sdkmanrc Olmadan Manuel Geçiş
sdkman_auto_env aktif değilse ya da o anki dizinde .sdkmanrc yoksa, sürümü elle yüklemek için:
sdk env
Bu komut, bulunduğunuz dizindeki .sdkmanrc dosyasını okur ve gerekli sürümlere geçiş yapar.
Gerçek Dünya Senaryosu: Mikroservis Ortamı
Düşünün ki bir mikroservis mimarisinde çalışıyorsunuz. Elimizde şu projeler var:
payment-service: Eski bir proje, Java 8 ve Maven 3.6 ile yazılmışuser-service: Java 11 ve Gradle 7.x ile geliştirilmişnotification-service: En yeni proje, Java 21 ve Gradle 8.x kullanıyor
Her proje dizinine gidip doğru SDK sürümünün otomatik yüklenmesi için şunları yaparsınız:
# Önce gerekli tüm sürümleri kur
sdk install java 8.0.412-tem
sdk install java 11.0.23-tem
sdk install java 21.0.3-tem
sdk install maven 3.6.3
sdk install gradle 7.6.4
sdk install gradle 8.8
# payment-service için
cd /opt/projeler/payment-service
cat > .sdkmanrc << 'EOF'
java=8.0.412-tem
maven=3.6.3
EOF
# user-service için
cd /opt/projeler/user-service
cat > .sdkmanrc << 'EOF'
java=11.0.23-tem
gradle=7.6.4
EOF
# notification-service için
cd /opt/projeler/notification-service
cat > .sdkmanrc << 'EOF'
java=21.0.3-tem
gradle=8.8
EOF
Artık her proje dizinine geçişte ortam otomatik olarak ayarlanır. Takım üyeleri de aynı .sdkmanrc dosyasını kendi makinelerine alarak aynı ortamı yeniden oluşturabilir.
GraalVM ile Native Image Derleme
SDKMAN, GraalVM kurulumunu da kolaylaştırır. Özellikle native image derleme yapıyorsanız GraalVM’e ihtiyacınız vardır:
sdk install java 21.0.3-graalce
sdk use java 21.0.3-graalce
GraalVM kurulduktan sonra native-image aracını da yükleyin:
gu install native-image
Artık Spring Boot native derleme ya da Quarkus native build gibi işlemler için hazırsınız. GraalVM ile normal JVM arasında geçiş yapmak artık tek satırlık bir iş:
# Native derleme için GraalVM'e geç
sdk use java 21.0.3-graalce
./mvnw -Pnative package
# Sonra normal geliştirme için Temurin'e dön
sdk use java 21.0.3-tem
SDKMAN’i CI/CD Pipeline’larında Kullanma
Jenkins, GitLab CI veya GitHub Actions gibi ortamlarda da SDKMAN kullanılabilir. Özellikle kendi runner’larınız varsa bu çok işe yarar.
Bir shell script ile CI ortamında SDKMAN kullanımı:
#!/bin/bash
# SDKMAN'i yükle (eğer yoksa)
if [ ! -d "$HOME/.sdkman" ]; then
curl -s "https://get.sdkman.io" | bash
fi
# SDKMAN'i aktif et
export SDKMAN_DIR="$HOME/.sdkman"
source "$HOME/.sdkman/bin/sdkman-init.sh"
# Gerekli Java sürümünü kur ve aktif et
sdk install java 17.0.11-tem || true
sdk use java 17.0.11-tem
# Proje derle
java -version
./mvnw clean package -DskipTests
echo "Build tamamlandi: $(java -version 2>&1 | head -1)"
Bu yaklaşımda || true ifadesi önemlidir; sürüm zaten kuruluysa sdk install hata döndürür ama script durmadan devam etmelidir.
SDKMAN Güncelleme ve Bakım
SDKMAN Kendisini Güncelleme
sdk selfupdate
Bu komut SDKMAN’in kendisini en son sürüme getirir.
Kurulu Bir SDK’yı Güncelleme
Temurin Java 17’nin yeni bir patch sürümü çıktıysa:
sdk upgrade java
Bu komut yükseltilebilecek tüm SDK’ları listeler. Belirli bir SDK için:
sdk upgrade java 17.0.11-tem
Kullanılmayan Sürümleri Temizleme
Zamanla kullanılmayan JDK sürümleri disk alanı kaplar. Temizlemek için:
sdk flush archives
sdk flush temp
flush archives indirilmiş zip dosyalarını temizler. flush temp ise geçici dosyaları siler. Kurulu ama artık kullanılmayan bir sürümü tamamen kaldırmak için:
sdk uninstall java 8.0.412-tem
Kaldırmadan önce o sürüme bağımlı başka proje olmadığından emin olun.
SDKMAN Konfigürasyonu
~/.sdkman/etc/config dosyasındaki önemli ayarlar şunlardır:
- sdkman_auto_answer=true: Kurulum sorularına otomatik “yes” yanıtlar, CI ortamlarında kullanışlıdır.
- sdkman_auto_env=true: Dizin değişiminde .sdkmanrc otomatik okunur.
- sdkman_auto_update=false: Otomatik güncelleme denetimini kapatır, kurumsal ortamlarda tercih edilebilir.
- sdkman_colour_enable=true: Terminal renkli çıktıyı aktif eder.
- sdkman_beta_channel=false: Beta kanalını kapatır, sadece stabil sürümler görünür.
- sdkman_rosetta2_compatible=false: Apple Silicon Mac’lerde Rosetta2 uyumlu sürümler için kullanılır.
Konfigürasyon dosyasını düzenledikten sonra değişikliklerin etkili olması için yeni terminal açın ya da:
source "$HOME/.sdkman/bin/sdkman-init.sh"
Docker ile SDKMAN Kullanımı
Dockerfile içinde SDKMAN kullanmak, build ortamını kodla birlikte sürümlendirmek açısından yararlı olabilir:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y
curl
zip
unzip
bash
&& rm -rf /var/lib/apt/lists/*
ENV SDKMAN_DIR="/root/.sdkman"
ENV JAVA_VERSION="21.0.3-tem"
RUN curl -s "https://get.sdkman.io" | bash &&
bash -c "source $SDKMAN_DIR/bin/sdkman-init.sh &&
sdk install java $JAVA_VERSION &&
sdk default java $JAVA_VERSION"
ENV JAVA_HOME="$SDKMAN_DIR/candidates/java/current"
ENV PATH="$JAVA_HOME/bin:$PATH"
WORKDIR /app
COPY . .
RUN bash -c "source $SDKMAN_DIR/bin/sdkman-init.sh && ./mvnw clean package"
Bu yaklaşım özellikle geliştirme ve test Dockerfile’larında işe yarar. Production image’leri için multi-stage build ve resmi temel imajları tercih etmek daha uygundur.
Sık Karşılaşılan Sorunlar ve Çözümleri
sdk komutu bulunamıyor hatası: Shell init dosyanıza (.bashrc veya .zshrc) SDKMAN kaynak satırının eklenip eklenmediğini kontrol edin. tail -5 ~/.bashrc ile son satırları görün.
Sürüm kurulumu ağdan dolayı başarısız oluyorsa: Proxy ayarlarınızı kontrol edin. Kurumsal ağlarda şu şekilde proxy tanımlayabilirsiniz:
export http_proxy=http://proxy.sirket.com:3128
export https_proxy=http://proxy.sirket.com:3128
sdk install java 21.0.3-tem
Yerel kurulu bir JDK’yı SDKMAN’e tanıtma: Kendi derlediğiniz ya da özel bir dizine kurduğunuz JDK’yı SDKMAN altına almak için:
sdk install java local-jdk /opt/custom-jdk/jdk-17
Bu komut /opt/custom-jdk/jdk-17 dizinindeki JDK’yı local-jdk tanımlayıcısıyla SDKMAN’e ekler.
zip/unzip yok hatası: Ubuntu/Debian sistemlerde:
sudo apt-get install zip unzip
CentOS/RHEL sistemlerde:
sudo yum install zip unzip
Sonuç
SDKMAN, Java ekosisteminde çalışan her geliştirici ve sistem yöneticisi için neredeyse vazgeçilmez bir araç haline geldi. Kurulumu beş dakika almaz, öğrenme eğrisi minimumdur ve getirdiği kolaylık ciddi zaman tasarrufu sağlar. Özellikle .sdkmanrc ile proje bazlı sürüm sabitleme özelliği, takım içinde ortam tutarlılığını sağlamak açısından büyük değer taşır. “Bende çalışıyor” problemlerinin önemli bir kısmı, farklı Java sürümlerinden kaynaklanır ve bu araç tam olarak o sorunu ortadan kaldırır.
Bugün tek bir Java sürümüyle çalışıyor olsanız bile SDKMAN kurmaya değer. Yarın yeni bir projeye geçiş yaptığınızda ya da mevcut projeniz için farklı bir JDK dağıtımını test etmek istediğinizde elimizde böyle bir araç olması hem konfigürasyonu hem de geri dönüşü son derece kolaylaştırır. Maven ve Gradle gibi araçları da yönetiyor olması ise işi daha da pratik hale getiriyor.
