--- title: JVM layout: docs permalink: /docs/jvm/ --- The JVM ecosystem provides many languages (Java, Scala, Groovy, Kotlin, ...) and build tools (Maven, Gradle, sbt, ...). The `javac` compiler generates reproducible bytecode `.class` output as do most language-specific compilers, but JVM packaging (in `.jar` files) is not reproducible-friendly -- particularly timestamp of files in the archive --, each build tool requires some work mostly at packaging step to provide Reproducible Builds. ## Reproducible Central Whatever the build tool is, binary JVM artifacts are generally published in artifact repositories that use the Maven2 repository format (using groupId/artifactId/version coordinates) like [Maven Central](https://search.maven.org/) or [Google's Android Repository](https://dl.google.com/dl/android/maven2/index.html). [Reproducible Central](https://github.com/jvm-repo-rebuild/reproducible-central#readme) is an effort to rebuild public releases published to [Maven Central](https://search.maven.org/) and check that Reproducible Build can be achieved. Contributions are welcome to write additional [`.buildspec` file](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/doc/BUILDSPEC.md) that will be used to rebuild the release and compare against binaries available in Maven Central. ## Configuring Build Tools for Reproducible Builds ### Maven Getting reproducible builds with Maven requires some plugins configuration: see [Maven - Guide to Configuring for Reproducible Builds](https://maven.apache.org/guides/mini/guide-reproducible-builds.html) for more details. ### Gradle Gradle supports [reproducible archives](https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives) as of v3.4. Tasks which generate archives, such as ZIPs or JARs, can enforce preserved file timestamps and reproducible file order which fix two of the main sources of non-determinism in JVM artifacts. ### `sbt` When using [sbt](https://www.scala-sbt.org/), a build tool popular with Scala projects, you can use the [sbt-reproducible-builds](https://github.com/raboof/sbt-reproducible-builds) plugin to strip your artifacts and share buildinfo information. ## `.buildinfo` file JVM `.buildinfo` file format is a format drafted in 2018 when working initially on Reproducible Builds for the JVM, to try to record full build info data, from source and environment used to rebuild to output result: its intent was to easily compare 2 builds run by independant people. After 3 years of work on Reproducible Builds, it has been found more useful as an internal file format: Reproducible Central and its `.buildspec` format is more what we need to check that Reproducible Builds results has been achieved. `.buildinfo` just records a build, be it reproducible or not. Buildinfo file format version 1.0-SNAPSHOT is kept here for reference on past work. It uses [Java properties format](https://en.wikipedia.org/wiki/.properties): ``` #### Work In Progress #### buildinfo.version=1.0-SNAPSHOT name= group-id= artifact-id= version= # source information for rebuilders, as source tarball artifact in repository and/or url and/or scm coordinates source.artifact=:::: source.url= source.scm.uri= source.scm.tag= # build instructions build-tool= build.setup= # effective recorded build environment information java.version= java.vendor= os.name= source.used= # Each build tool or plugin is free to add additional entries to the buildinfo, # both for build instructions and effective recorded build environment. # For example, the sbt plugin may add the following for Scala: sbt.version=1.2.3 scala.version=2.12.6 # and Maven could add data on rebuild instructions and effective recorded environment: mvn.rebuild-args=-Dmaven.test.skip package mvn.build-root=:: mvn.version=Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) mvn.minimum.version= # A buildinfo file can contain checksums for multiple output files, for # example for the main jar and the accompanying pom.xml (when generated): outputs.0.filename= outputs.0.length= outputs.0.checksums.sha512= outputs.1.filename= outputs.1.length= outputs.1.checksums.sha512= ... ``` Notice that `${artifactId}-${version}-sources.jar` files published in Maven repositories are not buildable sources, but [sources for IDEs](https://central.sonatype.org/pages/requirements.html#supply-javadoc-and-sources). Source tarballs, intended for building, are not always published in repositories but only sometimes, with 2 classical naming conventions: - `${artifactId}-${version}-source-release.zip` (see [artifacts in Central providing such source tarballs](https://search.maven.org/search?q=l:source-release)) - `${artifactId}-${version}-src.zip` (see [artifacts in Central providing such source tarballs](https://search.maven.org/search?q=l:src))