Bug 569665 Enable parsing of compressed files created by OpenJDK >= 15 Improved CRC processing for old Gzip reader. Tidy up help for acquire dialogs. Change-Id: I8136f69264c421450fa05409d4a1b92cbde7573e Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=569665
diff --git a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/ChunkedGZIPRandomAccessFile.java b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/ChunkedGZIPRandomAccessFile.java index c86d506..e9a675c 100644 --- a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/ChunkedGZIPRandomAccessFile.java +++ b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/ChunkedGZIPRandomAccessFile.java
@@ -549,8 +549,8 @@ defaultHeader[5] = (byte)(lastMod >> 8); defaultHeader[6] = (byte)(lastMod >> 16); defaultHeader[7] = (byte)(lastMod >> 24); - String opsys = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); //$NON-NLS-1$ - if (opsys.contains("linux") || opsys.contains("unix")) //$NON-NLS-1$ //$NON-NLS-2$ + String opsys = System.getProperty("os.name").toLowerCase(Locale.ROOT); //$NON-NLS-1$ + if (opsys.contains("linux") || opsys.contains("unix") || opsys.contains("aix")) //$NON-NLS-1$ //$NON-NLS-2$ defaultHeader[9] = 3; else if (opsys.contains("mac")) //$NON-NLS-1$ defaultHeader[9] = 7; @@ -656,6 +656,9 @@ { try { + // for zero length files we still want to generate a gzip + if (!writtenComment) + header(); flush(); def.finish(); dos.close();
diff --git a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/CompressedRandomAccessFile.java b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/CompressedRandomAccessFile.java index f65e032..f1b8469 100644 --- a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/CompressedRandomAccessFile.java +++ b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/CompressedRandomAccessFile.java
@@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2019,2020 IBM Corporation. + * Copyright (c) 2019,2021 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * + * https://www.eclipse.org/legal/epl-2.0/ + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -223,6 +223,12 @@ best = e2; if (e3 >= 0 && Math.abs(e3 - estimate) < Math.abs(best - estimate)) best = e3; + /* + * Attempt to detect a chunked file and round up the size + * to at least 4GB so the parser doesn't throw an error with an inaccurate size + */ + if (best < 0x100000000L && len32 <= 1024 * 1024) + best = 0x100000000L; return best; } else
diff --git a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/GZIPInputStream2.java b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/GZIPInputStream2.java index 3fbab83..782dade 100644 --- a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/GZIPInputStream2.java +++ b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/GZIPInputStream2.java
@@ -18,7 +18,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.zip.CRC32; import java.util.zip.ZipException; import io.nayuki.deflate.InflaterInputStream; @@ -37,7 +36,7 @@ InputStream is; long uncompressedLen; long uncompressedLocationAtHeader; - CRC32 crc = new CRC32(); + CRC32 crc; boolean checkcrc; String comment; String filename; @@ -45,18 +44,17 @@ { super(new InflaterInputStream((InflaterInputStream)gs.in)); is = gs.is; + crc = gs.crc.clone(); uncompressedLen = gs.uncompressedLen; uncompressedLocationAtHeader = gs.uncompressedLocationAtHeader; - // FIXME Need to initialize CRC to other value, so until then disable the CRC check - checkcrc = false; } public GZIPInputStream2(InputStream is) throws IOException { super(new InflaterInputStream(is, false)); this.is = is; + crc = new CRC32(); readHeader(is); - checkcrc = true; } private InputStream readHeader(InputStream is) throws IOException @@ -85,6 +83,8 @@ if (b3 < 0) throw new ZipException(Messages.GZIPInputStream2_TruncatedHeader); crc.update(b3); + if ((b3 & 0xe0) != 0x0) + throw new ZipException(Messages.GZIPInputStream2_BadHeaderFlag); int b4 = is.read(); if (b4 < 0) throw new ZipException(Messages.GZIPInputStream2_TruncatedHeader); @@ -143,21 +143,21 @@ bos.write(b); } crc.update(0); - filename = new String(bos.toByteArray(), StandardCharsets.UTF_8); + filename = new String(bos.toByteArray(), StandardCharsets.ISO_8859_1); } // Comment if ((b3 & FLG_FCOMMENT) != 0) { int b; - StringBuilder sb = new StringBuilder(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); while ((b = is.read()) != 0) { if (b == -1) throw new ZipException(Messages.GZIPInputStream2_TruncatedComment); crc.update(b); - sb.append((char)b); + bos.write(b); } crc.update(0); - comment = sb.toString(); + comment = new String(bos.toByteArray(), StandardCharsets.ISO_8859_1); } // CRC16 if ((b3 & FLG_FHCRC) != 0) @@ -197,7 +197,7 @@ ((InflaterInputStream)in).attach(); } } while (r < 0); - if (r >= 0); + if (r >= 0) { crc.update(r); ++uncompressedLen; @@ -274,7 +274,7 @@ // Unsigned long crc32 = b0 & 0xff | (b1 & 0xff) << 8 | (b2 & 0xff) << 16 | (b3 & 0xffL) << 24; long crc32v = crc.getValue(); - if (checkcrc && crc32v != crc32) + if (crc32v != crc32) throw new ZipException(Messages.GZIPInputStream2_BadTrailerCRC); // uncompressed length int b4 = is.read(); @@ -305,4 +305,63 @@ { super.close(); } + + /** + * A CRC32 implementation - which + * allows the state to be cloned. + */ + private static class CRC32 implements Cloneable + { + int value; + private static final int table[] = new int[256]; + static + { + for (int i = 0; i < 256; ++i) + { + int v = i; + for (int j = 0; j < 8; ++j) + { + if ((v & 1) != 0) + v = 0xedb88320 ^ (v >>> 1); + else + v >>>= 1; + } + table[i] = v; + } + } + public CRC32() + { + reset(); + } + @Override + public CRC32 clone() + { + CRC32 c = new CRC32(); + c.value = value; + return c; + } + public void reset() + { + value = 0xffffffff; + } + public void update(int b) + { + value = table[(value ^ (b & 0xff)) & 0xff] ^ (value >>> 8); + } + public void update(byte b[], int offset, int len) + { + for (int i = 0; i < len; ++i) + { + update(b[offset + i]); + } + } + public void update(byte b[]) + { + update(b, 0, b.length); + } + public long getValue() + { + return (value ^ 0xffffffff) & 0xffffffffL; + } + } }
diff --git a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/Messages.java b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/Messages.java index c4e600f..e2cf76b 100644 --- a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/Messages.java +++ b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/Messages.java
@@ -1,10 +1,10 @@ /******************************************************************************* - * Copyright (c) 2010, 2020 SAP AG and others. + * Copyright (c) 2010, 2021 SAP AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * + * https://www.eclipse.org/legal/epl-2.0/ + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -41,6 +41,7 @@ public static String ExportHprof_SegmentSizeMismatch; public static String ExportHprof_SegmentTooLong; public static String GZIPInputStream2_BadHeaderCRC; + public static String GZIPInputStream2_BadHeaderFlag; public static String GZIPInputStream2_BadTrailerCRC; public static String GZIPInputStream2_BadTrailerLength; public static String GZIPInputStream2_NotAGzip;
diff --git a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/messages.properties b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/messages.properties index 2381af1..faa87d1 100644 --- a/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/messages.properties +++ b/plugins/org.eclipse.mat.hprof/src/org/eclipse/mat/hprof/messages.properties
@@ -35,6 +35,7 @@ ExportHprof_SegmentSizeMismatch=Heap dump segment {0} expected size {1} actual size {2} at 0x{3} ExportHprof_SegmentTooLong=Heap dump segment {0} at 0x{1} is too long: {2}, continuing... GZIPInputStream2_BadHeaderCRC=Bad header CRC +GZIPInputStream2_BadHeaderFlag=Bad header flag GZIPInputStream2_BadTrailerCRC=Bad CRC trailer GZIPInputStream2_BadTrailerLength=bad length GZIPInputStream2_NotAGzip=Not a Gzip
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/AcquireDialog.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/AcquireDialog.java index 5dbe524..9b3957d 100644 --- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/AcquireDialog.java +++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/AcquireDialog.java
@@ -217,8 +217,7 @@ tableComposite.layout(); tableComposite.pack(); - Control control = localVMsTable.getParent(); - PlatformUI.getWorkbench().getHelpSystem().setHelp(control, "org.eclipse.mat.ui.help.acquire_arguments"); //$NON-NLS-1$ + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.mat.ui.help.acquire_arguments"); //$NON-NLS-1$ italicFont = resourceManager.createFont(FontDescriptor.createFrom(column.getParent().getFont()).setStyle(SWT.ITALIC)); @@ -583,6 +582,21 @@ getContainer().updateButtons(); } + @Override + public void performHelp() + { + if (localVMsTable.getSelectionIndex() >= 0) + { + AnnotatedObjectArgumentsSet argumentsSet = (AnnotatedObjectArgumentsSet) localVMsTable.getSelection()[0].getData(); + String helpUrl = argumentsSet.getDescriptor().getHelpUrl(); + if (helpUrl != null) + { + PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(helpUrl); + } + } + PlatformUI.getWorkbench().getHelpSystem().displayHelp("org.eclipse.mat.ui.help.acquire_arguments"); //$NON-NLS-1$ + } + private static class GetVMListRunnable implements IRunnableWithProgress { private IStatus status;
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderArgumentsWizardPage.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderArgumentsWizardPage.java index 5b050fb..3c2cf49 100644 --- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderArgumentsWizardPage.java +++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderArgumentsWizardPage.java
@@ -70,7 +70,7 @@ tableComposite.layout(); tableComposite.pack(); - //PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.mat.ui.help.acquire_arguments"); //$NON-NLS-1$ + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.mat.ui.help.acquire_arguments"); //$NON-NLS-1$ composite.setContent(tableComposite); setControl(composite); @@ -93,7 +93,7 @@ if (isCurrentPage()) { IPreferenceStore prefs = MemoryAnalyserPlugin.getDefault().getPreferenceStore(); - if (!prefs.getBoolean(HIDE_QUERY_HELP)) + if (!prefs.getBoolean(HIDE_QUERY_HELP) || helpPopup != null && helpPopup.getShell() != null) { relocateHelp(true); }
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderConfigurationWizardPage.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderConfigurationWizardPage.java index 9a60d90..c9c46a1 100644 --- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderConfigurationWizardPage.java +++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/acquire/ProviderConfigurationWizardPage.java
@@ -113,7 +113,7 @@ table.providerSelected(argumentsSet); onFocus(null); IPreferenceStore prefs = MemoryAnalyserPlugin.getDefault().getPreferenceStore(); - if (!prefs.getBoolean(HIDE_QUERY_HELP)) + if (!prefs.getBoolean(HIDE_QUERY_HELP) || helpPopup != null && helpPopup.getShell() != null) { relocateHelp(true); } @@ -124,7 +124,7 @@ // If a process is selected, make the configuration provider match the process acquireDialog.addProcessSelectionListener(this); - //PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.mat.ui.help.query_arguments"); //$NON-NLS-1$ + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.mat.ui.help.acquire_arguments"); //$NON-NLS-1$ Listener listener = new Listener() {