Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 31 additions & 48 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,9 @@ or on Windows:
Your output should look something like the following:

```
ℹ️ Checking required JVMs:
✅ JAVA_HOME is set to /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home.
✅ JAVA_8_HOME is set to /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home.
✅ JAVA_11_HOME is set to /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home.
✅ JAVA_17_HOME is set to /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home.
✅ JAVA_21_HOME is set to /Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home.
✅ JAVA_25_HOME is set to /Library/Java/JavaVirtualMachines/zulu-25.jdk/Contents/Home.
✅ JAVA_GRAALVM17_HOME is set to /Library/Java/JavaVirtualMachines/graalvm-ce-java17-22.3.1/Contents/Home.
ℹ️ Checking required JVM:
✅ JAVA_HOME is set to /Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home.
ℹ️ Other JDK versions will be automatically downloaded by Gradle toolchain resolver.
ℹ️ Checking git configuration:
✅ The git command line is installed.
✅ pre-commit hook is installed in repository.
Expand All @@ -53,44 +48,39 @@ If there is any issue with your output, check the requirements above and use the

Requirements to build the full project:

* The JDK versions 8, 11, 17, 21, and 25 must be installed.
* The `JAVA_8_HOME`, `JAVA_11_HOME`, `JAVA_17_HOME`, `JAVA_21_HOME`, `JAVA_25_HOME`, and `JAVA_GRAALVM17_HOME` must point to their respective JDK location.
* The JDK 8 `bin` directory must be the only JDK on the PATH (e.g. `$JAVA_8_HOME/bin`).
* The `JAVA_HOME` environment variable may be unset. If set, it must point to the JDK 8 location (same as `JAVA_8_HOME`).
* The `git` command line must be installed.
* A container runtime environment must be available to run all tests (e.g. Docker Desktop).

### Install the required JDKs
### Install the required JDK

Download and install JDK versions 8, 11, 17, 21 and 25, and GraalVM 17 for your OS.
Gradle auto-provision needed JDKs locally. However, it still is possible to manage the JDK via other tools.

#### macOS

The following steps demonstrate how to use `brew`, but other version managers
such as [mise](https://mise.jdx.dev/) or [sdkman](https://sdkman.io/) work as well.

* Install the required JDKs using `brew`:
```shell
brew install --cask zulu@8 zulu@11 zulu@17 zulu@21 zulu graalvm/tap/graalvm-ce-java17
brew install --cask zulu@8 zulu@11 zulu@17 zulu@21 zulu@25
```

and if GraalVM is needed (17, 21, 25)
```shell
brew install graalvm/tap/graalvm-community-java17 graalvm/tap/graalvm-community-jdk21 graalvm/tap/graalvm-community-jdk25
```
* Identify your local version of GraalVM:
```
ls /Library/Java/JavaVirtualMachines | grep graalvm
```
Example: `graalvm-ce-java17-22.3.1`
* Use this version in the following command to fix the GraalVM installation by [removing the quarantine flag](https://www.graalvm.org/latest/docs/getting-started/macos/):
```
sudo xattr -r -d com.apple.quarantine /Library/Java/JavaVirtualMachines/graalvm-<current version of graalvm>
```
Example: `/Library/Java/JavaVirtualMachines/graalvm-ce-java17-22.3.1`
* Add the required environment variables to your shell using the `export` command. You can permanently install the environment variables by appending the `export` commands into your shell configuration file `~/.zshrc` or `.bashrc` or other.
Example: `graalvm-community-openjdk-17`

Use this version in the following command to fix the GraalVM installation by [removing the quarantine flag](https://www.graalvm.org/latest/docs/getting-started/macos/), e.g. :

```shell
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home
export JAVA_11_HOME=/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home
export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
export JAVA_21_HOME=/Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home
export JAVA_25_HOME=/Library/Java/JavaVirtualMachines/zulu-25.jdk/Contents/Home
export JAVA_GRAALVM17_HOME=/Library/Java/JavaVirtualMachines/graalvm-<current version of graalvm>/Contents/Home
export JAVA_HOME=$JAVA_8_HOME
xattr -r -d com.apple.quarantine "/Library/Java/JavaVirtualMachines/graalvm-community-openjdk-17"
```
* Restart your shell after applying the changes if you appended the commands to your shell configuration file.
* Restart your shell after applying the changes if you appended the command to your shell configuration file.

> [!NOTE]
> ARM users: there is no Oracle JDK v8 for ARM.
Expand All @@ -102,23 +92,21 @@ Download and install JDK versions 8, 11, 17, 21 and 25, and GraalVM 17 for your

#### Linux

Use your JDK manager ([mise](https://mise.jdx.dev/), [sdkman](https://sdkman.io/), etc.) or manually install the required JDKs.

* Download and extract JDK 8, 11, 17, 21, and 25 from [Eclipse Temurin releases](https://adoptium.net/temurin/releases/) and GraalVM 17 from [Oracle downloads](https://www.graalvm.org/downloads/).
* Install the GraalVM native image requirements for native builds by following [the GraalVM official documentation](https://www.graalvm.org/latest/reference-manual/native-image/#prerequisites).
* Add the required environment variables to your shell using the `export` command. You can permanently install the environment variables by appending the `export` commands into your shell configuration file `~/.zshrc` or `~/.bashrc` or other.
* Add the `JAVA_HOME` environment variable to your shell using the `export` command. You can permanently set it by appending the `export` command to your shell configuration file `~/.zshrc` or `~/.bashrc` or other.
```shell
export JAVA_8_HOME=/<path to extracted archive>/jdk8u<current version of JDK 8>
export JAVA_11_HOME=/<path to extracted archive>/jdk-11.<current version of JDK 11>
export JAVA_17_HOME=/<path to extracted archive>/jdk-17.<current version of JDK 17>
export JAVA_21_HOME=/<path to extracted archive>/jdk-21.<current version of JDK 21>
export JAVA_25_HOME=/<path to extracted archive>/jdk-25.<current version of JDK 25>
export JAVA_GRAALVM17_HOME=/<path to extracted archive>/graalvm-jdk-17.<current version of graalvm>/Contents/Home
export JAVA_HOME=$JAVA_8_HOME
export JAVA_HOME=/<path to extracted archive>/jdk-21.<current version of JDK 21>
```

Gradle should automatically detect the JDK in usual places. As a fallback it can automatically provision them.
* Restart your shell after applying the changes if you appended the commands to your shell configuration file.

#### Windows

* Download and install JDK 8, 11, 17, 21, and 25 [Eclipse Temurin releases](https://adoptium.net/temurin/releases/).
* Download and install JDK 8, 11, 17, 21, and 25 from [Eclipse Temurin releases](https://adoptium.net/temurin/releases/).

<details>
<summary>Alternatively, install JDKs using winget or scoop. (click here to expand)</summary>
Expand All @@ -142,18 +130,13 @@ Download and install JDK versions 8, 11, 17, 21 and 25, and GraalVM 17 for your

</details>

* To add the required environment variables, run the following PowerShell commands for each SDK version, replacing the paths with the correct version installed:
* Set the `JAVA_HOME` environment variable, replacing the path with your JDK 21 installation:
```pwsh
[Environment]::SetEnvironmentVariable("JAVA_8_HOME", "C:\Program Files\Eclipse Adoptium\jdk-8.0.432.6-hotspot", [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("JAVA_11_HOME", "C:\Program Files\Eclipse Adoptium\jdk-11.0.25.9-hotspot", [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("JAVA_17_HOME", "C:\Program Files\Eclipse Adoptium\jdk-17.0.12.7-hotspot", [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("JAVA_21_HOME", "C:\Program Files\Eclipse Adoptium\jdk-21.0.5.11-hotspot", [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("JAVA_25_HOME", "C:\Program Files\Eclipse Adoptium\jdk-25.0.1.9-hotspot", [EnvironmentVariableTarget]::User)

# JAVA_HOME = JAVA_8_HOME
[Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Eclipse Adoptium\jdk-8.0.432.6-hotspot", [EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Eclipse Adoptium\jdk-21.0.5.11-hotspot", [EnvironmentVariableTarget]::User)
```

Gradle should automatically detect the JDK in usual places. As a fallback it can automatically provision them.

### Install git

#### macOS
Expand Down
10 changes: 1 addition & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ To run the formatting verify task only:

For IntelliJ IDEA, we suggest the following settings and plugin.

The default JVM to build and run tests from the command line should be Java 8.

* Use Java 8 to build and run tests:
* `Project Structure` -> `Project` -> `SDK` -> `Download JDK...` -> `Version: 1.8` -> `Download`
* Configure Java and Groovy import formatting:
* `Settings...` ->`Editor` > `Code Style` > `Java` > `Imports`
* `Use single class import`: checked
Expand All @@ -64,6 +60,7 @@ The default JVM to build and run tests from the command line should be Java 8.
* top right Settings icon -> `Settings...` ->`Editor` > `Code Style` > `Groovy` > `Imports`
* `Class count to use import with '*'`: `9999` (some number sufficiently large that is unlikely to matter)
* `Names count to use static import with '*'`: `9999`
* To run test in a specific JDK use the `testJvm` property, e.g. `-PtestJvm=11`
* Install the [Google Java Format](https://plugins.jetbrains.com/plugin/8527-google-java-format) plugin

### Troubleshooting
Expand All @@ -82,11 +79,6 @@ The default JVM to build and run tests from the command line should be Java 8.
* IntelliJ 2021.3
complains `Failed to find KotlinGradleProjectData for GradleSourceSetData` https://youtrack.jetbrains.com/issue/KTIJ-20173.
* Switch to `IntelliJ IDEA CE 2021.2.3`.

* IntelliJ Gradle fails to import the project with `JAVA_11_HOME must be set to build Java 11 code`.
* A workaround is to run IntelliJ from your terminal with `JAVA_11_HOME`.
* In order to verify what's visible from IntelliJ, use the `Add Configuration` bar and go
to `Add New` -> `Gradle` -> `Environmental Variables`.
</details>

## Pull request guidelines
Expand Down
11 changes: 9 additions & 2 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ plugins {
id("com.diffplug.spotless") version "8.1.0"
}

// The buildSrc still needs to target Java 8 as build time instrumentation and muzzle plugin
// allow to schedule workers on different JDK version.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(8)
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package datadog.gradle.plugin.testJvmConstraints

import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.internal.provider.PropertyFactory
import org.gradle.api.provider.Provider
import org.gradle.internal.jvm.inspection.JavaInstallationRegistry
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.jvm.toolchain.JavaToolchainService
Expand Down Expand Up @@ -51,25 +53,22 @@ class TestJvmSpec(val project: Project) {
throw GradleException("testJvm property is blank")
}

// "stable" is calculated as the largest X found in JAVA_X_HOME
// "stable" is calculated as the largest Java version found via toolchains or JAVA_X_HOME
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

misc: I still do not like stable name... can we rename it to latest or something similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not change it in this PR.

when (testJvm) {
"stable" -> {
val javaVersions = project.providers.environmentVariablesPrefixedBy("JAVA_").map { javaHomes ->
javaHomes
.filter { it.key.matches(Regex("^JAVA_[0-9]+_HOME$")) && it.key != "JAVA_26_HOME" } // JDK 26 is EA
.map { Regex("^JAVA_(\\d+)_HOME$").find(it.key)!!.groupValues[1].toInt() }
}.get()
val javaVersions = discoverJavaVersionsViaToolchains()
?: discoverJavaVersionsViaEnvVars()

if (javaVersions.isEmpty()) {
throw GradleException("No valid JAVA_X_HOME environment variables found.")
throw GradleException("No Java installations found via toolchains or JAVA_X_HOME environment variables.")
}

javaVersions.max().toString()
}

else -> testJvm
}
}.map { project.logger.info("normalized testJvm: $it"); it }
}.map { project.logger.info("normalized testJvm: {}", it); it }

/**
* The home path of the test JVM.
Expand All @@ -83,9 +82,13 @@ class TestJvmSpec(val project: Project) {
private val testJvmSpec = normalizedTestJvm.map {
val (distribution, version) = Regex("([a-zA-Z]*)([0-9]+)").matchEntire(it)?.groupValues?.drop(1) ?: listOf("", "")

// Allow looking up JAVA_<TESTJVM>_HOME environment variable (e.g., JAVA_IBM8_HOME, JAVA_SEMERU8_HOME),
// because gradle doesn't offer a way to distinguish ibm8 or semeru8
val envVarValue = project.providers.environmentVariable("JAVA_${it.uppercase()}_HOME").orNull

when {
Files.exists(Paths.get(it)) -> it.normalizeToJDKJavaHome().toToolchainSpec()

envVarValue != null && Files.exists(Paths.get(envVarValue)) -> envVarValue.normalizeToJDKJavaHome().toToolchainSpec()
version.isNotBlank() -> {
// Best effort to make a spec for the passed testJvm
// `8`, `11`, `ZULU8`, `GRAALVM25`, etc.
Expand All @@ -104,7 +107,10 @@ class TestJvmSpec(val project: Project) {
vendor.set(JvmVendorSpec.AZUL)
}

"semeru" -> {
// Note: Both IBM and Semeru report java.vendor = "IBM Corporation",
// so JvmVendorSpec cannot distinguish them. Use JAVA_IBM8_HOME or
// JAVA_SEMERU8_HOME env vars for reliable selection.
"ibm", "semeru" -> {
vendor.set(JvmVendorSpec.IBM)
implementation.set(JvmImplementation.J9)
}
Expand All @@ -113,6 +119,10 @@ class TestJvmSpec(val project: Project) {
vendor.set(JvmVendorSpec.GRAAL_VM)
nativeImageCapable.set(true)
}

else -> {
throw GradleException("Unknown JVM distribution '$distribution'. Supported: oracle, zulu, ibm, semeru, graalvm.")
}
}
}
}
Expand All @@ -127,7 +137,7 @@ class TestJvmSpec(val project: Project) {
""".trimIndent()
)
}
}.map { project.logger.info("testJvm home path: $it"); it }
}.map { project.logger.info("testJvm home path: {}", it); it }

/**
* The Java launcher for the test JVM.
Expand All @@ -145,7 +155,7 @@ class TestJvmSpec(val project: Project) {
throw GradleException("Unable to find launcher for Java '$testJvm'. Does $TEST_JVM point to a JDK?")
})
}
}.flatMap { it }.map { project.logger.info("testJvm launcher: ${it.executablePath}"); it }
}.flatMap { it }.map { project.logger.info("testJvm launcher: {}", it.executablePath); it }

private fun String.normalizeToJDKJavaHome(): Path {
val javaHome = project.file(this).toPath().toRealPath()
Expand All @@ -159,4 +169,38 @@ class TestJvmSpec(val project: Project) {
private val Project.javaToolchains: JavaToolchainService
get() =
extensions.getByName("javaToolchains") as JavaToolchainService

/**
* Discovers available Java versions via Gradle's internal JavaInstallationRegistry.
*/
private fun discoverJavaVersionsViaToolchains(): List<Int>? {
val registry = (project as ProjectInternal).services.get(JavaInstallationRegistry::class.java)
val versions = registry.toolchains().mapNotNull { installation ->
installation.metadata.languageVersion.majorVersion.toInt()
}

return if (versions.isNotEmpty()) {
project.logger.info("Discovered Java versions via toolchains: {}", versions)
versions
} else {
null
}
}

/**
* Discovers available Java versions via JAVA_X_HOME environment variables.
* Fallback method when toolchain discovery is not available.
*/
private fun discoverJavaVersionsViaEnvVars(): List<Int> {
val versions = project.providers.environmentVariablesPrefixedBy("JAVA_").map { javaHomes ->
javaHomes
.filter { it.key.matches(Regex("^JAVA_[0-9]+_HOME$")) }
.mapNotNull { Regex("^JAVA_(\\d+)_HOME$").find(it.key)?.groupValues?.get(1)?.toIntOrNull() }
}.get()

if (versions.isNotEmpty()) {
project.logger.info("Discovered Java versions via JAVA_X_HOME env vars: {}", versions)
}
return versions
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.junit.jupiter.api.Test;

class EnvironmentVariablesTest {
private static final String EXISTING_ENV_VAR = "JAVA_8_HOME";
private static final String EXISTING_ENV_VAR = "PATH";
private static final String MISSING_ENV_VAR = "UNDEFINED_ENV_VAR";
private static final String DEFAULT_VALUE = "DEFAULT";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import datadog.trace.api.config.TracerConfig
import java.nio.file.Paths
import spock.lang.Specification
import spock.lang.TempDir
import spock.util.environment.Jvm

import java.nio.file.Path

Expand All @@ -29,10 +28,20 @@ abstract class CiVisibilitySmokeTest extends Specification {
protected Path prefsDir

protected static String buildJavaHome() {
if (Jvm.current.isJava8()) {
return System.getenv("JAVA_8_HOME")
def javaHome = System.getProperty("java.home")
def javacPath = Paths.get(javaHome, "bin", "javac").toFile()
if (javacPath.exists()) {
return javaHome
}
return System.getenv("JAVA_" + Jvm.current.getJavaSpecificationVersion() + "_HOME")
// In CI for JDK 8, java.home may point to the JRE directory (e.g., /usr/lib/jvm/8/jre)
// The JDK with javac is in the parent directory
def parentDir = new File(javaHome).getParentFile()
def parentJavacPath = new File(parentDir, Paths.get("bin", "javac").toString())
if (parentJavacPath.exists()) {
return parentDir.getAbsolutePath()
}
// Fallback to java.home and let callers handle the error if javac is not found
return javaHome
}

protected static String javaPath() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import datadog.trace.bootstrap.instrumentation.usm.UsmMessageFactory
import java.lang.reflect.Field
import javax.net.ssl.HttpsURLConnection
import spock.lang.AutoCleanup
import spock.lang.Requires
import spock.lang.Shared

// IBM JVM has different protocol support for TLS
@Requires({
!System.getProperty("java.vm.name").contains("IBM J9 VM")
})
class SslSocketTest extends InstrumentationSpecification {
@AutoCleanup
@Shared
Expand Down
2 changes: 1 addition & 1 deletion dd-java-agent/instrumentation/mule-4.5/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ tasks.register('extractLatestMuleServices', Sync) {
// build the mule application via maven
tasks.register('mvnPackage', Exec) {
workingDir("$appDir")
environment.JAVA_HOME = System.getenv("JAVA_8_HOME")
environment["JAVA_HOME"] = getLazyJavaHomeFor(8)

List<String> mvnArgs = [
"$rootDir/mvnw",
Expand Down
6 changes: 4 additions & 2 deletions dd-smoke-tests/armeria-grpc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ def gradlewCommand = isWindows ? 'gradlew.bat' : 'gradlew'
// define the task that builds the armeria project
tasks.register('armeriaBuild', Exec) {
workingDir "$appDir"
def toolchain17 = getJavaLauncherFor(17).get()
environment += ["GRADLE_OPTS": "-Dorg.gradle.jvmargs='-Xmx512M'", "JAVA_HOME": "$toolchain17.metadata.installationPath"]
environment += [
"GRADLE_OPTS": "-Dorg.gradle.jvmargs='-Xmx512M'",
"JAVA_HOME": getLazyJavaHomeFor(17)
]
commandLine "${rootDir}/${gradlewCommand}", "build", "--no-daemon", "--max-workers=4", "-PappBuildDir=$appBuildDir", "-PapiJar=${project(':dd-trace-api').tasks.jar.archiveFile.get()}"

outputs.cacheIf { true }
Expand Down
Loading