Skip to content

Commit 6ee44b1

Browse files
Re-pushing PR after github mess.
* fixing tests after refactoring * Fixing up after dependent PR changes * feedback and remove unused code * new tests for ImageLocation * Restoring lost changes and updating some comments. * add system property guard to preview mode * Remove TODOs now jimage version is bumped * jimage writer changes to support preview mode.
1 parent b211c23 commit 6ee44b1

File tree

15 files changed

+1897
-1160
lines changed

15 files changed

+1897
-1160
lines changed

src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package jdk.internal.jimage;
2727

2828
import java.nio.ByteBuffer;
29+
import java.util.List;
2930
import java.util.Objects;
3031
import java.util.function.Predicate;
3132

@@ -159,6 +160,29 @@ public static int getFlags(String name, Predicate<String> hasEntry) {
159160
}
160161
}
161162

163+
/**
164+
* Helper function to calculate package flags for {@code "/packages/xxx"}
165+
* directory entries.
166+
*
167+
* <p>Based on the module references, the flags are:
168+
* <ul>
169+
* <li>{@code FLAGS_HAS_PREVIEW_VERSION} if <em>any</em> referenced
170+
* package has a preview version.
171+
* <li>{@code FLAGS_IS_PREVIEW_ONLY} if <em>all</em> referenced packages
172+
* are preview only.
173+
* </ul>
174+
*
175+
* @return package flags for {@code "/packages/xxx"} directory entries.
176+
*/
177+
public static int getPackageFlags(List<ModuleReference> moduleReferences) {
178+
boolean hasPreviewVersion =
179+
moduleReferences.stream().anyMatch(ModuleReference::hasPreviewVersion);
180+
boolean isPreviewOnly =
181+
moduleReferences.stream().allMatch(ModuleReference::isPreviewOnly);
182+
return (hasPreviewVersion ? ImageLocation.FLAGS_HAS_PREVIEW_VERSION : 0)
183+
| (isPreviewOnly ? ImageLocation.FLAGS_IS_PREVIEW_ONLY : 0);
184+
}
185+
162186
/**
163187
* Tests a non-preview image location's flags to see if it has preview
164188
* content associated with it.

src/java.base/share/classes/jdk/internal/jimage/ModuleReference.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public final class ModuleReference implements Comparable<ModuleReference> {
5353
/** If set, this package exists in non-preview mode. */
5454
private static final int FLAGS_PKG_HAS_NORMAL_VERSION = 0x2;
5555
/** If set, the associated module has resources (in normal or preview mode). */
56-
// TODO: Make this private again when image writer code is updated.
57-
public static final int FLAGS_PKG_HAS_RESOURCES = 0x4;
56+
private static final int FLAGS_PKG_HAS_RESOURCES = 0x4;
5857

5958
/**
6059
* References are ordered with preview versions first which permits early
@@ -118,7 +117,7 @@ public String name() {
118117
* under many modules, it only has resources in one.
119118
*/
120119
public boolean hasResources() {
121-
return ((flags & FLAGS_PKG_HAS_RESOURCES) != 0);
120+
return (flags & FLAGS_PKG_HAS_RESOURCES) != 0;
122121
}
123122

124123
/**
@@ -176,9 +175,9 @@ public static Iterator<Integer> readNameOffsets(
176175
if (bufferSize == 0 || (bufferSize & 0x1) != 0) {
177176
throw new IllegalArgumentException("Invalid buffer size");
178177
}
179-
int testFlags = (includeNormal ? FLAGS_PKG_HAS_NORMAL_VERSION : 0)
178+
int includeMask = (includeNormal ? FLAGS_PKG_HAS_NORMAL_VERSION : 0)
180179
+ (includePreview ? FLAGS_PKG_HAS_PREVIEW_VERSION : 0);
181-
if (testFlags == 0) {
180+
if (includeMask == 0) {
182181
throw new IllegalArgumentException("Invalid flags");
183182
}
184183

@@ -188,14 +187,7 @@ public static Iterator<Integer> readNameOffsets(
188187
int nextIdx(int idx) {
189188
for (; idx < bufferSize; idx += 2) {
190189
// If any of the test flags are set, include this entry.
191-
192-
// Temporarily allow for *neither* flag to be set. This is what would
193-
// be written by a 1.0 version of the jimage flag, and indicates a
194-
// normal resource without a preview version.
195-
// TODO: Remove the zero-check below once image writer code is updated.
196-
int previewFlags =
197-
buffer.get(idx) & (FLAGS_PKG_HAS_NORMAL_VERSION | FLAGS_PKG_HAS_PREVIEW_VERSION);
198-
if (previewFlags == 0 || (previewFlags & testFlags) != 0) {
190+
if ((buffer.get(idx) & includeMask) != 0) {
199191
return idx;
200192
} else if (!includeNormal) {
201193
// Preview entries are first in the offset buffer, so we

src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ public enum PreviewMode {
5656
* Resolves whether preview mode should be enabled for an {@link ImageReader}.
5757
*/
5858
public boolean isPreviewModeEnabled() {
59+
if (!ENABLE_PREVIEW_MODE) {
60+
return false;
61+
}
5962
// A switch, instead of an abstract method, saves 3 subclasses.
6063
switch (this) {
6164
case DISABLED:
@@ -83,4 +86,14 @@ public boolean isPreviewModeEnabled() {
8386
throw new IllegalStateException("Invalid mode: " + this);
8487
}
8588
}
89+
;
90+
91+
// Temporary system property to disable preview patching and enable the new preview mode
92+
// feature for testing/development. Once the preview mode feature is finished, the value
93+
// will be always 'true' and this code, and all related dead-code can be removed.
94+
private static final boolean DISABLE_PREVIEW_PATCHING_DEFAULT = false;
95+
private static final boolean ENABLE_PREVIEW_MODE = Boolean.parseBoolean(
96+
System.getProperty(
97+
"DISABLE_PREVIEW_PATCHING",
98+
Boolean.toString(DISABLE_PREVIEW_PATCHING_DEFAULT)));
8699
}

src/java.base/share/native/libjimage/imageFile.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,7 @@ bool ImageFileReader::open() {
319319
!read_at((u1*)&_header, header_size, 0) ||
320320
_header.magic(_endian) != IMAGE_MAGIC ||
321321
_header.major_version(_endian) != MAJOR_VERSION ||
322-
// Temporarily, we allow either version (1.1 or 1.0) of the file to
323-
// be read so this code can be committed before image writing changes
324-
// for preview mode. Preview mode changes do not modify any structure,
325-
// so a 1.0 file will look like a jimage without any preview resources.
326-
// TODO: Restore equality check for MINOR_VERSION.
327-
_header.minor_version(_endian) > MINOR_VERSION) {
322+
_header.minor_version(_endian) != MINOR_VERSION) {
328323
close();
329324
return false;
330325
}

src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,21 +36,17 @@
3636
public final class BasicImageWriter {
3737
public static final String MODULES_IMAGE_NAME = "modules";
3838

39-
private ByteOrder byteOrder;
40-
private ImageStringsWriter strings;
39+
private final ByteOrder byteOrder;
40+
private final ImageStringsWriter strings;
4141
private int length;
4242
private int[] redirect;
4343
private ImageLocationWriter[] locations;
44-
private List<ImageLocationWriter> input;
45-
private ImageStream headerStream;
46-
private ImageStream redirectStream;
47-
private ImageStream locationOffsetStream;
48-
private ImageStream locationStream;
49-
private ImageStream allIndexStream;
50-
51-
public BasicImageWriter() {
52-
this(ByteOrder.nativeOrder());
53-
}
44+
private final List<ImageLocationWriter> input;
45+
private final ImageStream headerStream;
46+
private final ImageStream redirectStream;
47+
private final ImageStream locationOffsetStream;
48+
private final ImageStream locationStream;
49+
private final ImageStream allIndexStream;
5450

5551
public BasicImageWriter(ByteOrder byteOrder) {
5652
this.byteOrder = Objects.requireNonNull(byteOrder);
@@ -75,11 +71,15 @@ public String getString(int offset) {
7571
return strings.get(offset);
7672
}
7773

78-
public void addLocation(String fullname, long contentOffset,
79-
long compressedSize, long uncompressedSize) {
74+
public void addLocation(
75+
String fullname,
76+
long contentOffset,
77+
long compressedSize,
78+
long uncompressedSize,
79+
int previewFlags) {
8080
ImageLocationWriter location =
8181
ImageLocationWriter.newLocation(fullname, strings,
82-
contentOffset, compressedSize, uncompressedSize);
82+
contentOffset, compressedSize, uncompressedSize, previewFlags);
8383
input.add(location);
8484
length++;
8585
}
@@ -88,10 +88,6 @@ ImageLocationWriter[] getLocations() {
8888
return locations;
8989
}
9090

91-
int getLocationsCount() {
92-
return input.size();
93-
}
94-
9591
private void generatePerfectHash() {
9692
PerfectHashBuilder<ImageLocationWriter> builder =
9793
new PerfectHashBuilder<>(
@@ -174,16 +170,4 @@ public byte[] getBytes() {
174170

175171
return allIndexStream.toArray();
176172
}
177-
178-
ImageLocationWriter find(String key) {
179-
int index = redirect[ImageStringsReader.hashCode(key) % length];
180-
181-
if (index < 0) {
182-
index = -index - 1;
183-
} else {
184-
index = ImageStringsReader.hashCode(key, index) % length;
185-
}
186-
187-
return locations[index];
188-
}
189173
}

src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
4949
import java.util.stream.Collectors;
5050
import java.util.stream.Stream;
5151

52+
import jdk.internal.jimage.ImageLocation;
5253
import jdk.tools.jlink.internal.Archive.Entry;
5354
import jdk.tools.jlink.internal.Archive.Entry.EntryType;
5455
import jdk.tools.jlink.internal.JRTArchive.ResourceFileEntry;
@@ -227,31 +228,8 @@ private static ResourcePool generateJImage(ResourcePoolManager allContent,
227228
DataOutputStream out,
228229
boolean generateRuntimeImage
229230
) throws IOException {
230-
ResourcePool resultResources;
231-
try {
232-
resultResources = pluginSupport.visitResources(allContent);
233-
if (generateRuntimeImage) {
234-
// Keep track of non-modules resources for linking from a run-time image
235-
resultResources = addNonClassResourcesTrackFiles(resultResources,
236-
writer);
237-
// Generate the diff between the input resources from packaged
238-
// modules in 'allContent' to the plugin- or otherwise
239-
// generated-content in 'resultResources'
240-
resultResources = addResourceDiffFiles(allContent.resourcePool(),
241-
resultResources,
242-
writer);
243-
}
244-
} catch (PluginException pe) {
245-
if (JlinkTask.DEBUG) {
246-
pe.printStackTrace();
247-
}
248-
throw pe;
249-
} catch (Exception ex) {
250-
if (JlinkTask.DEBUG) {
251-
ex.printStackTrace();
252-
}
253-
throw new IOException(ex);
254-
}
231+
ResourcePool resultResources =
232+
getResourcePool(allContent, writer, pluginSupport, generateRuntimeImage);
255233
Set<String> duplicates = new HashSet<>();
256234
long[] offset = new long[1];
257235

@@ -282,8 +260,10 @@ private static ResourcePool generateJImage(ResourcePoolManager allContent,
282260
offset[0] += onFileSize;
283261
return;
284262
}
263+
int locFlags = ImageLocation.getFlags(
264+
res.path(), p -> resultResources.findEntry(p).isPresent());
285265
duplicates.add(path);
286-
writer.addLocation(path, offset[0], compressedSize, uncompressedSize);
266+
writer.addLocation(path, offset[0], compressedSize, uncompressedSize, locFlags);
287267
paths.add(path);
288268
offset[0] += onFileSize;
289269
}
@@ -307,6 +287,40 @@ private static ResourcePool generateJImage(ResourcePoolManager allContent,
307287
return resultResources;
308288
}
309289

290+
private static ResourcePool getResourcePool(
291+
ResourcePoolManager allContent,
292+
BasicImageWriter writer,
293+
ImagePluginStack pluginSupport,
294+
boolean generateRuntimeImage)
295+
throws IOException {
296+
ResourcePool resultResources;
297+
try {
298+
resultResources = pluginSupport.visitResources(allContent);
299+
if (generateRuntimeImage) {
300+
// Keep track of non-modules resources for linking from a run-time image
301+
resultResources = addNonClassResourcesTrackFiles(resultResources,
302+
writer);
303+
// Generate the diff between the input resources from packaged
304+
// modules in 'allContent' to the plugin- or otherwise
305+
// generated-content in 'resultResources'
306+
resultResources = addResourceDiffFiles(allContent.resourcePool(),
307+
resultResources,
308+
writer);
309+
}
310+
} catch (PluginException pe) {
311+
if (JlinkTask.DEBUG) {
312+
pe.printStackTrace();
313+
}
314+
throw pe;
315+
} catch (Exception ex) {
316+
if (JlinkTask.DEBUG) {
317+
ex.printStackTrace();
318+
}
319+
throw new IOException(ex);
320+
}
321+
return resultResources;
322+
}
323+
310324
/**
311325
* Support for creating a runtime suitable for linking from the run-time
312326
* image.

src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -53,9 +53,13 @@ private ImageLocationWriter addAttribute(int kind, String value) {
5353
return addAttribute(kind, strings.add(value));
5454
}
5555

56-
static ImageLocationWriter newLocation(String fullName,
56+
static ImageLocationWriter newLocation(
57+
String fullName,
5758
ImageStringsWriter strings,
58-
long contentOffset, long compressedSize, long uncompressedSize) {
59+
long contentOffset,
60+
long compressedSize,
61+
long uncompressedSize,
62+
int previewFlags) {
5963
String moduleName = "";
6064
String parentName = "";
6165
String baseName;
@@ -90,13 +94,14 @@ static ImageLocationWriter newLocation(String fullName,
9094
}
9195

9296
return new ImageLocationWriter(strings)
93-
.addAttribute(ATTRIBUTE_MODULE, moduleName)
94-
.addAttribute(ATTRIBUTE_PARENT, parentName)
95-
.addAttribute(ATTRIBUTE_BASE, baseName)
96-
.addAttribute(ATTRIBUTE_EXTENSION, extensionName)
97-
.addAttribute(ATTRIBUTE_OFFSET, contentOffset)
98-
.addAttribute(ATTRIBUTE_COMPRESSED, compressedSize)
99-
.addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize);
97+
.addAttribute(ATTRIBUTE_MODULE, moduleName)
98+
.addAttribute(ATTRIBUTE_PARENT, parentName)
99+
.addAttribute(ATTRIBUTE_BASE, baseName)
100+
.addAttribute(ATTRIBUTE_EXTENSION, extensionName)
101+
.addAttribute(ATTRIBUTE_OFFSET, contentOffset)
102+
.addAttribute(ATTRIBUTE_COMPRESSED, compressedSize)
103+
.addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize)
104+
.addAttribute(ATTRIBUTE_PREVIEW_FLAGS, previewFlags);
100105
}
101106

102107
@Override

0 commit comments

Comments
 (0)