Skip to content

Commit d344292

Browse files
change error message for version mismatch
1 parent 41d6dc3 commit d344292

File tree

3 files changed

+68
-18
lines changed

3 files changed

+68
-18
lines changed

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

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
*/
2525
package jdk.internal.jimage;
2626

27-
import java.io.ByteArrayInputStream;
2827
import java.io.IOException;
29-
import java.io.InputStream;
3028
import java.lang.reflect.InvocationTargetException;
3129
import java.lang.reflect.Method;
3230
import java.nio.ByteBuffer;
@@ -41,6 +39,10 @@
4139
import java.util.stream.IntStream;
4240
import jdk.internal.jimage.decompressor.Decompressor;
4341

42+
import static jdk.internal.jimage.BasicImageReader.ImageError.Reason.BAD_VERSION;
43+
import static jdk.internal.jimage.BasicImageReader.ImageError.Reason.CORRUPT_JIMAGE;
44+
import static jdk.internal.jimage.BasicImageReader.ImageError.Reason.INVALID_JIMAGE;
45+
4446
/**
4547
* @implNote This class needs to maintain JDK 8 source compatibility.
4648
*
@@ -144,10 +146,10 @@ public Void run() {
144146
if (channel.read(headerBuffer, 0L) == headerSize) {
145147
headerBuffer.rewind();
146148
} else {
147-
throw new IOException("\"" + name + "\" is not an image file");
149+
throw new ImageError(INVALID_JIMAGE, "\"" + name + "\" is not an image file");
148150
}
149151
} else if (headerBuffer.capacity() < headerSize) {
150-
throw new IOException("\"" + name + "\" is not an image file");
152+
throw new ImageError(INVALID_JIMAGE, "\"" + name + "\" is not an image file");
151153
}
152154

153155
// Interpret the image file header
@@ -164,7 +166,7 @@ public Void run() {
164166

165167
// Interpret the image index
166168
if (memoryMap.capacity() < indexSize) {
167-
throw new IOException("The image file \"" + name + "\" is corrupted");
169+
throw new ImageError(CORRUPT_JIMAGE, "The image file \"" + name + "\" is corrupted");
168170
}
169171
redirect = intBuffer(memoryMap, header.getRedirectOffset(), header.getRedirectSize());
170172
offsets = intBuffer(memoryMap, header.getOffsetsOffset(), header.getOffsetsSize());
@@ -191,14 +193,14 @@ private ImageHeader readHeader(IntBuffer buffer) throws IOException {
191193
ImageHeader result = ImageHeader.readFrom(buffer);
192194

193195
if (result.getMagic() != ImageHeader.MAGIC) {
194-
throw new IOException("\"" + name + "\" is not an image file");
196+
throw new ImageError(INVALID_JIMAGE, "\"" + name + "\" is not an image file");
195197
}
196198

197199
if (result.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
198-
result.getMinorVersion() != ImageHeader.MINOR_VERSION) {
199-
throw new IOException("The image file \"" + name + "\" is not " +
200-
"the correct version. Major: " + result.getMajorVersion() +
201-
". Minor: " + result.getMinorVersion());
200+
result.getMinorVersion() != ImageHeader.MINOR_VERSION) {
201+
throw new ImageError(BAD_VERSION, "The image file \"" + name + "\" is not " +
202+
"the correct version. Major: " + result.getMajorVersion() +
203+
". Minor: " + result.getMinorVersion());
202204
}
203205

204206
return result;
@@ -457,10 +459,31 @@ public ByteBuffer getResourceBuffer(ImageLocation loc) {
457459
return null;
458460
}
459461

460-
public InputStream getResourceStream(ImageLocation loc) {
461-
Objects.requireNonNull(loc);
462-
byte[] bytes = getResource(loc);
462+
/**
463+
* Specialized {@link IOException} thrown during construction which provides
464+
* a semantic reason for failure.
465+
*/
466+
public final static class ImageError extends IOException {
467+
private static final long serialVersionUID = 6002259582237888214L;
468+
469+
public enum Reason {
470+
/** The file being opened does not appear to be a jimage file. */
471+
INVALID_JIMAGE,
472+
/** The jimage file being opened is corrupted. */
473+
CORRUPT_JIMAGE,
474+
/** The jimage file being opened has the wrong version. */
475+
BAD_VERSION,
476+
}
477+
478+
private final Reason reason;
463479

464-
return new ByteArrayInputStream(bytes);
480+
public ImageError(Reason reason, String message) {
481+
super(message);
482+
this.reason = reason;
483+
}
484+
485+
public Reason getReason() {
486+
return reason;
487+
}
465488
}
466489
}

src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.io.PrintWriter;
3131
import java.nio.file.FileSystem;
3232
import java.nio.file.Files;
33+
import java.nio.file.Path;
3334
import java.nio.file.PathMatcher;
3435
import java.util.ArrayList;
3536
import java.util.Arrays;
@@ -44,6 +45,7 @@
4445
import java.lang.classfile.MethodModel;
4546

4647
import jdk.internal.jimage.BasicImageReader;
48+
import jdk.internal.jimage.BasicImageReader.ImageError.Reason;
4749
import jdk.internal.jimage.ImageHeader;
4850
import jdk.internal.jimage.ImageLocation;
4951
import jdk.tools.jlink.internal.ImageResourcesTree;
@@ -435,6 +437,22 @@ private void iterate(JImageAction jimageAction,
435437
}
436438
}
437439
} catch (IOException ioe) {
440+
// Handle specific errors for which better advice can be given.
441+
if (ioe instanceof BasicImageReader.ImageError err) {
442+
if (err.getReason() == Reason.BAD_VERSION) {
443+
Path p = file.toPath();
444+
if (p.endsWith(Path.of("lib", "modules"))) {
445+
// Looks like jimage tool is in the standard JDK directory.
446+
p = p.subpath(0, p.getNameCount() - 2).resolve("bin", "jimage");
447+
if (Files.isRegularFile(p)) {
448+
// Suggest what we hope is the correct tool path.
449+
throw TASK_HELPER.newBadArgs("err.bad.version.suggest", file, p);
450+
}
451+
}
452+
throw TASK_HELPER.newBadArgs("err.bad.version", file);
453+
}
454+
}
455+
// Non-specific error during processing.
438456
throw TASK_HELPER.newBadArgs("err.invalid.jimage", file, ioe.getMessage());
439457
}
440458
}

src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,20 @@ main.usage=\
3131
Usage: {0} <extract | info | list | verify> <options> jimage...\n\
3232
\n\
3333
\ extract - Extract all jimage entries and place in a directory specified\n\
34-
\ by the --dir=<directory> (default='.') option.\n\
34+
\ by the --dir=<directory> (default=''.'') option.\n\
3535
\n\
3636
\ info - Prints detailed information contained in the jimage header.\n\
3737
\n\
3838
\ list - Prints the names of all the entries in the jimage. When used with\n\
3939
\ --verbose, list will also print entry size and offset attributes.\n\
4040
\n\
41-
\ verify - Reports on any .class entries that don't verify as classes.\n\
41+
\ verify - Reports on any .class entries that don''t verify as classes.\n\
4242
\n\
4343
Possible options include:
4444

4545
main.usage.extract=\
4646
\ extract - Extract all jimage entries and place in a directory specified\n\
47-
\ by the --dir=<directory> (default='.') option.
47+
\ by the --dir=<directory> (default=''.'') option.
4848

4949
main.usage.info=\
5050
\ info - Prints detailed information contained in the jimage header.
@@ -54,7 +54,7 @@ main.usage.list=\
5454
\ --verbose, list will also print entry size and offset attributes.
5555

5656
main.usage.verify=\
57-
\ verify - Reports errors on any .class entries that don't verify as classes.
57+
\ verify - Reports errors on any .class entries that don''t verify as classes.
5858

5959
error.prefix=Error:
6060
warn.prefix=Warning:
@@ -101,3 +101,12 @@ err.no.jimage=no jimage provided
101101
err.option.unsupported={0} not supported: {1}
102102
err.unknown.option=unknown option: {0}
103103
err.cannot.create.dir=cannot create directory {0}
104+
105+
err.bad.version=Unable to open {0}: mismatched file version\n\
106+
\ Use ''<JAVA_HOME>/bin/jimage'' for the JDK associated with this jimage file.
107+
108+
# Apart from the trailing line (and newline before it), this message should
109+
# be identical to 'err.bad.version'.
110+
err.bad.version.suggest=Unable to open {0}: mismatched file version\n\
111+
\ Use ''<JAVA_HOME>/bin/jimage'' for the JDK associated with this jimage file.\n\
112+
\ Found candidate tool: {1}

0 commit comments

Comments
 (0)