JVM-CI auf Remote-Macs: zentrale Engpässe sind Maven-/Gradle-Repository-Latenz, geteilte ~/.gradle- und ~/.m2-Schreibzugriffe sowie zu kurze HTTP-Timeouts. Hier: Repo-Matrix, Spiegel-Endpunkte, Cache-Pfade, Parallel-Schwellen und Retry 2/4/8s. Mehr Kontext: Startseite, Technik-Blog, Go-GOPROXY-Matrix.

① Engpässe: Warum Gradle- und Maven-Downloads auf Remote-Macs instabil wirken

Drei typische Ursachen auf gemeinsam genutzten Build-Macs:

  • Metadaten-Drift: geteiltes GRADLE_USER_HOME oder ~/.m2 bei wechselnden Mirrors.
  • Überparallelisierung: hohe -T-Werte + --parallel → IO- und Proxy-Sättigung.
  • Kurze HTTP-Timeouts: WAN-Jitter ohne Retry-Backoff.

② Entscheidungsmatrix: Firmen-Repository vs. Maven Central vs. regionaler Öffentlich-Spiegel

Nexus/Artifactory vs. Maven Central vs. regionale Spiegel (mit Security abstimmen):

Kriterium Firmen-私服 / Proxy Maven Central direkt Regionaler Öffentlich-Spiegel
Audit Policies, Quarantäne Externe Scanner nötig SLA des Betreibers
WAN Niedrige RTT im VPC Viele Hits auf Central Regional gebündelt
Gradle-Plugins Proxy → plugins.gradle.org pluginManagement getrennt Metadaten prüfen
Android google() im Proxy Offizielle URLs Kein mirrorOf=*
Ops 2026 Infra + Zertifikate Wenig Aufwand Spiegel-Sync
Ausfall SPoF ohne HA Zentral, meist stabil Spiegel-Abhängigkeit

Regel: Private GAVs nur über freigegebene Proxies; öffentliche Repos explizit in settings.gradle.kts / settings.xml ordnen.

③ Spiegel-Endpunkte: typische URLs und Einsatzlogik (Platzhalter durch Ihre Ziele ersetzen)

Kategorien und Beispiel-URLs (Hosts durch Ihre freigegebenen Endpunkte ersetzen):

Kategorie Beispiel-Endpunkt / ID Gradle (settings.gradle.kts) Maven (settings.xml)
Maven Central https://repo1.maven.org/maven2/ mavenCentral() explizit central-Repo-Block
Gradle Plugin Portal https://plugins.gradle.org/m2 gradlePluginPortal() separat Eigenes pluginRepository
Google Android https://dl.google.com/dl/android/maven2/ google() vor generischen Mirrors Profil mit höherer Priorität
Firmen-Nexus https://nexus.corp.example/repository/maven-public/ Erstes maven { url = … } mirrorOf=* nur mit Ausnahmen
Regionaler Spiegel https://mirror.region.example/maven2/ Zwischen Hub und Central mirror + blocked

Android: kein blindes mirrorOf=* ohne Ausnahme für google().

④ Lokale Cache-Pfade: GRADLE_USER_HOME, Daemon-Daten und Maven-M2-Layout

Caches auf NVMe; Isolation pro Job empfohlen:

Pfad / Variable Inhalt Empfehlung Shared-Mac
GRADLE_USER_HOME caches/, daemon/, wrapper/ Pro CI_JOB_ID oder Team-Prefix exportieren
$GRADLE_USER_HOME/caches/modules-2 Aufgelöste Modul-Artefakte Nach Mirror-Wechsel selektiv leeren
~/.m2/repository (Default) Maven-GAV-Baum Override via -Dmaven.repo.local
MAVEN_OPTS JVM-Flags für CLI -Dmaven.repo.local=/var/tmp/m2-$JOB
GRADLE_RO_DEP_CACHE (falls genutzt) Read-only Dependency Cache Nur lesend mounten; Schreibjobs separieren
Temp / Shrinker Zwischenprodukte TMPDIR auf lokale SSD setzen
Platten-Quota df / iostat Alarm bei 85 % belegt; Cleanup-Job

Export-Beispiel (Bash, Platzhalter anpassen):

export GRADLE_USER_HOME="${HOME}/.gradle-ci/${CI_JOB_ID:-local}" export MAVEN_OPTS="-Dmaven.repo.local=${HOME}/.m2-ci/${CI_JOB_ID:-local}/repository" mkdir -p "$GRADLE_USER_HOME" "${HOME}/.m2-ci/${CI_JOB_ID:-local}/repository" ./gradlew --stop || true mvn -v

Secrets nur via settings.xml-Server oder Gradle-Credentials – nicht in Logs.

⑤ Parallelität: --parallel, org.gradle.workers.max und Maven -T-Schwellen

Limitierend sind oft IO und WAN, nicht nur CPU:

Parameter Typischer Startwert (Shared-Mac) Obere Grenze / Heuristik
org.gradle.parallel true bei multi-project Nur mit isoliertem GRADLE_USER_HOME
org.gradle.workers.max 24 floor(0,75 × physische Kerne), min. verfügbarer RAM beachten
CLI --parallel gleichbedeutend zu Properties Nicht zusätzlich extreme --max-workers
Maven -T 1C 1 Thread pro CPU-Kern Auf HDD oder NAS-Homes vermeiden
Maven -T 2 Zwei Module parallel Bei kleinen Reaktoren oft stabiler als 1C

CI: optional org.gradle.vfs.watch=false bei Netz-Workspaces.

⑥ HTTP-Timeouts, Resolver-Retries und exponentielles Backoff (2s / 4s / 8s)

Längere Timeouts + max. drei Retries mit Pause 2/4/8s.

gradle.properties (oder -D):

systemProp.org.gradle.internal.http.connectionTimeout=120000 systemProp.org.gradle.internal.http.socketTimeout=300000

Maven: aether.connector.* bzw. wagon in settings.xml (Version prüfen).

Bash-Backoff-Skizze für den äußeren CI-Wrapper:

for d in 2 4 8; do mvn -B -q verify && exit 0 sleep "$d" done exit 1
Symptom Wahrscheinliche Ursache Maßnahme
Could not resolve … sporadisch WAN-Jitter, zu kurzes Timeout Timeouts erhöhen + Retry-Cap
Checksum failed Gemischte Proxies / Cache Repo-Reihenfixierung, Cache-Unterverzeichnis löschen
Build hängt bei Download Dead TCP / Proxy Healthcheck des Nexus, alternativer Mirror
401 auf privatem Repo Abgelaufenes Token Secret-Rotation, kein Retry ohne Auth-Fix

⑦ Rollout: sechs Pflichtschritte für reproduzierbare JVM-Builds auf Remote-Macs

JDK-, Gradle-Wrapper- und Maven-Version wie in Prod fixieren.

Artefakt Zweck CI-Prüfpunkt
gradle-wrapper.properties Feste Gradle-Distribution SHA256 gegen offizielle Quelle
pom.xml / BOM Abhängigkeitsmanagement Keine SNAPSHOT-Drifts ohne Freigabe
settings.xml (maskiert) Mirrors & Server-Creds Nur Secrets-Injection, kein Klartext im Image

Operative Sequenz

  1. Inventar: Alle Repository-URLs und private GAV-Scopes in einem Sheet sammeln.
  2. Cache-Layout: GRADLE_USER_HOME und maven.repo.local pro Job definieren und in der Pipeline erzwingen.
  3. Mirrors aktivieren: Firmen-Proxy zuerst, dann freigegebene öffentliche Pfadsegmente; Android/Google separat.
  4. Parallelität: Start mit konservativen workers.max- und -T-Werten, nach drei grünen Builds messen und anheben.
  5. Timeouts & Retry: Properties setzen und äußeren Wrapper mit 2/4/8s-Backoff testen.
  6. Abnahme: Kaltlauf ohne Cache und Warm-Lauf mit Cache protokollieren; Speicherverbrauch auf dem Remote-Mac notieren.
./gradlew -version ./gradlew dependencies --configuration runtimeClasspath | head mvn -B -q -DskipTests dependency:go-offline || true

⑧ Kurz-FAQ: Gradle-Caches, Maven-Threads und Spiegelwechsel

./gradlew --stop nötig?
Nach Wechsel von GRADLE_USER_HOME/JDK sinnvoll auf Shared Hosts; in Containern oft unnötig.
mvn deploy scheitert in CI?
distributionManagement, Credentials, ggf. blockierter PUT-Egress prüfen.

Fazit

Fazit (2026): Stabile Gradle- und Maven-Pulls auf Remote-Macs erfordern die Kombination aus klar priorisierten Spiegeln, isolierter Cache-Verzeichnisstruktur, gedeckelter Parallelität sowie langen HTTP-Timeouts und begrenztem Retry-Backoff. Für den Einstieg ohne Anmeldung: Startseite, Remote-Mac-Pakete kaufen und Hilfe zu SSH & Verbindung.

JVM-CI & Remote-Mac 2026

Nächste Schritte – ohne Login

Startseite, Paketkauf und Hilfe mit SSH- sowie Verbindungsanleitungen – alles ohne Konto.

Apple-Silicon-Remote-Macs
JVM-Downloads planbar
Support bei Netzfragen