-
Notifications
You must be signed in to change notification settings - Fork 5.9k
8276766: Enable jar and jmod to produce deterministic timestamped content #6481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8276766: Enable jar and jmod to produce deterministic timestamped content #6481
Conversation
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
👋 Welcome back aleonard! A progress list of the required criteria for merging this PR into |
@andrew-m-leonard The following labels will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command. |
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
Webrevs
|
/csr |
@andrew-m-leonard has indicated that a compatibility and specification (CSR) request is needed for this pull request. |
Thank you for this timely pull request, Andrew! I need this pull request and also #6395 to enable reproducible builds in JavaFX. 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:
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);
}
} |
Create the build timestamp as a zoned date and time in UTC instead of a local date and time. If SOURCE_DATE_EPOCH is defined, set the last modification time of ZIP and JAR entries to the local date and time in UTC of the instant defined by SOURCE_DATE_EPOCH. Add a comment as a reminder to make JMOD files deterministic when the following enhancements are complete: * Enable deterministic file content ordering for Jar and Jmod https://bugs.openjdk.java.net/browse/JDK-8276764 openjdk/jdk#6395 * Enable jar and jmod to produce deterministic timestamped content https://bugs.openjdk.java.net/browse/JDK-8276766 openjdk/jdk#6481
@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. |
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, but you need more reviewers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your efforts here.
I just happened to notice that you created a CSR, which is great, thank you.
Please add an explanation as to why the compatibility risk is minimal as that field is currently empty to the CSR.
The current version of the PR looks reasonable. Please see a few additional comments below
A user who’s not familiar with the lingo of reproducible builds will be mystified by an option named Please consider providing a more general option, say |
I just tested this pull request by building my JavaFX pull request on six Linux architectures, and it works beautifully! First I built this pull request branch of OpenJDK for Linux on the following hardware platforms: amd64 (x86_64), arm64 (aarch64), armhf (armv7l), i386 (i636), ppc64el (ppc64le), and s390x (s390x). Then I added three lines of Groovy code to the JavaFX if (sourceDateEpoch != null) {
args("--source-date", sourceDateEpoch)
} Then I built JavaFX twice for each of the architectures, with each build on a clean, isolated container created from scratch. The result is 6 architectures × 4,360 files = 26,160 identical files between the two sets of builds. The JMOD archives were the last missing piece for JavaFX, so thank you, Andrew, for completing the puzzle. By the way, my builds of OpenJDK did not include your |
@jgneff thank you for testing, that's great news
|
Thanks @mbreinhold , good point, i'll update to use --date=<iso-8601-date> |
The The only way I found to store a timestamp using the methods of You can store a zoned date and time indirectly (in seconds) by adding an extra extended timestamp field to each entry with The beauty of the |
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
@andrew-m-leonard this pull request can not be integrated into git checkout jarjmodtimestamps
git fetch https://git.openjdk.java.net/jdk master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
@vicente-romero-oracle |
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
@LanceAndersen thank you for the review comments, i've just done a new commit with them all done.. assuming all the tests run ok, i'll integrate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Andrew,
Thank you for the changes. This looks much much better. Please see additional simplification comment below.
I kicked off a Mach5 run in the meantime
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
@LanceAndersen let me know if mach5 looks good please, then I think we're good to go.. |
@andrew-m-leonard if this enhancement is now intended to go into JDK 19, then you can simply integrate it into jdk mainline when it is ready. In that case, the fix version of the CSR should be adjusted to 19 to match. If, however, you would still like to get it into JDK 18, you will need to make a late enhancement request per JEP 3, and then recreate this PR against the jdk18 stabilization repo. |
@kevinrushforth thanks Kevin, I had totally missed that RDP1 was yesterday! i'll have some thought on what's best, cheers |
@jgneff John, I know you have an interest in this, what is your urgency for this support? jdk-18 or 19 ? |
It's not urgent. I'm just being impatient. 😄 If this pull request is integrated only into JDK 19, JavaFX won't be able to support reproducible builds until OpenJFX 20 in March 2023. Java projects in general are late to the reproducible builds party. Debian, for example, builds 31,571 packages and less than three percent fail to build in a reproducible manner. Those failing packages include OpenJDK and OpenJFX. Debian plans eventually to make reproducibility a requirement, and other distributions may follow. The only true urgency, of course, is to provide Java project owners better tools to detect the next supply chain attack on the packages they distribute. |
As soon as the Mach5 finishes, I will let you know |
@jgneff thanks John, i'm going to raise the JEP 3 request and see where I get, as I concur with your statement:
The risk is minimal, also given the extensive testing we have done. |
…tent Signed-off-by: Andrew Leonard <anleonar@redhat.com>
@AlanBateman will need to review your request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Andrew,
The latest Mach5 runs remain clean and the updates look good so you are good to integrate when you are ready!
Thank you @LanceAndersen |
/integrate |
Going to push as commit db68a0c.
Your commit was automatically rebased without conflicts. |
@andrew-m-leonard Pushed as commit db68a0c. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
@LanceAndersen fyi.i've raised a docs enhancement for the closed repo "man" pages to be updated for this: https://bugs.openjdk.java.net/browse/JDK-8278764 |
Build with the OpenJDK Snap package that includes the pull request: 8276766: Enable jar and jmod to produce deterministic timestamped content openjdk/jdk#6481
Add a new --source-date (epoch seconds) 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@redhat.com
Progress
Issues
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/6481/head:pull/6481
$ git checkout pull/6481
Update a local copy of the PR:
$ git checkout pull/6481
$ git pull https://git.openjdk.java.net/jdk pull/6481/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 6481
View PR using the GUI difftool:
$ git pr show -t 6481
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/6481.diff