RFR: 8276766: Enable jar and jmod to produce deterministic timestamped content
Andrew Leonard
aleonard at openjdk.java.net
Tue Nov 23 11:16:07 UTC 2021
On Mon, 22 Nov 2021 02:36:00 GMT, John Neffenger <jgneff at openjdk.org> wrote:
>> Add a new --source-date <TIMESTAMP> (epoch milliseconds) option to jar and jmod to allow specification of time to use for created/updated jar/jmod entries. This then allows the ability to make the content deterministic.
>>
>> Signed-off-by: Andrew Leonard <anleonar at redhat.com>
>
> Thank you for this timely pull request, Andrew! I need this pull request and also #6395 to [enable reproducible builds in JavaFX](https://github.com/openjdk/jfx/pull/446). I drove myself crazy this weekend with time zones, and if I understand your proposed changes correctly, it looks as if you're hitting the same problems as I did:
>
> 1. The [`SOURCE_DATE_EPOCH` environment variable](https://reproducible-builds.org/specs/source-date-epoch/) is defined as the number of **seconds** since the epoch of 1970-01-01T00:00:00Z, but the new command option is defined as the number of milliseconds. That makes it difficult to set `--source-date=$SOURCE_DATE_EPOCH` on the command line.
>
> 2. Calling the method `ZipEntry.setTime(long)` will not allow for reproducible builds when the builds run in different time zones.
>
> For the second problem, run the included Java Time program as shown below:
>
>
> $ javac Time.java
> $ echo $SOURCE_DATE_EPOCH
> 1637085342
> $ date --date="@$SOURCE_DATE_EPOCH"
> Tue 16 Nov 2021 09:55:42 AM PST
> $ java Time
> Build timestamp = 2021-11-16T17:55:42Z
> $ for f in *.zip; do zipinfo -v $f | grep -e Archive -e modified; done
> Archive: FailsInNome.zip
> file last modified on (DOS date/time): 2021 Nov 16 08:55:42
> Archive: FailsInRome.zip
> file last modified on (DOS date/time): 2021 Nov 16 18:55:42
> Archive: WorksInNome.zip
> file last modified on (DOS date/time): 2021 Nov 16 17:55:42
> Archive: WorksInRome.zip
> file last modified on (DOS date/time): 2021 Nov 16 17:55:42
>
>
> import java.io.FileOutputStream;
> import java.io.IOException;
> import java.time.Instant;
> import java.time.LocalDateTime;
> import java.time.ZoneOffset;
> import java.time.temporal.ChronoUnit;
> import java.util.TimeZone;
> import java.util.zip.ZipEntry;
> import java.util.zip.ZipOutputStream;
>
> public class Time {
>
> static void writeZipFile(String name, ZipEntry entry) throws IOException {
> var output = new ZipOutputStream(new FileOutputStream(name));
> output.putNextEntry(entry);
> output.closeEntry();
> output.close();
> }
>
> public static void main(String[] args) throws IOException {
> var instant = Instant.now().truncatedTo(ChronoUnit.SECONDS);
> var sourceDateEpoch = System.getenv("SOURCE_DATE_EPOCH");
> if (sourceDateEpoch != null) {
> long seconds = Long.parseLong(sourceDateEpoch);
> instant = Instant.ofEpochSecond(seconds);
> }
> System.out.println("Build timestamp = " + instant);
>
> var entry = new ZipEntry("Entry");
>
> long newTime = 1000 * instant.getEpochSecond();
> TimeZone.setDefault(TimeZone.getTimeZone("America/Nome"));
> entry.setTime(newTime);
> writeZipFile("FailsInNome.zip", entry);
> TimeZone.setDefault(TimeZone.getTimeZone("Europe/Rome"));
> entry.setTime(newTime);
> writeZipFile("FailsInRome.zip", entry);
>
> var dosTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
> TimeZone.setDefault(TimeZone.getTimeZone("America/Nome"));
> entry.setTimeLocal(dosTime);
> writeZipFile("WorksInNome.zip", entry);
> TimeZone.setDefault(TimeZone.getTimeZone("Europe/Rome"));
> entry.setTimeLocal(dosTime);
> writeZipFile("WorksInRome.zip", entry);
> }
> }
@jgneff Hi John, thanks for the comment, I hadn't realized that aspect, but sort of obvious when you look at the ZIP spec for dostime, which has no timezone info.
So with this in mind the --source-date=<timestamp> option I am looking to add for jar/jmod, will need to state the timestamp is an "Epoch timestamp", ie. seconds since Jan1 1970 in UTC, and that as such the jar/jmod dostime will represent UTC "local time", akin to the EPOCH_SOURCE_DATE spec: https://reproducible-builds.org/specs/source-date-epoch/
I will update my PR to to use this.
thanks
-------------
PR: https://git.openjdk.java.net/jdk/pull/6481
More information about the compiler-dev
mailing list