From 0da41b464e1a5abccd1f327c79f28ac42e887d89 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 6 Dec 2019 12:13:25 -0800 Subject: [PATCH 01/32] 8235499: Change HotSpot jtreg records test to better handle JDK updates Reviewed-by: hseigel, iignatyev --- test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java | 4 ++-- test/hotspot/jtreg/runtime/records/recordReflectionTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java b/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java index 53df049c5cd..7716b9cf17c 100644 --- a/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java +++ b/test/hotspot/jtreg/runtime/records/ignoreRecordAttribute.java @@ -35,7 +35,7 @@ public class ignoreRecordAttribute { public static void main(String[] args) throws Exception { - + String MAJOR_VERSION = Integer.toString(44 + Runtime.version().feature()); ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--enable-preview", "-Xlog:class+record", "-Xshare:off", "superNotJLRecord"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception { "-Xlog:class+record", "-Xshare:off", "recordIgnoredVersion"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Ignoring Record attribute"); - output.shouldContain("because class file version is not 58.65535"); + output.shouldContain("because class file version is not " + MAJOR_VERSION + ".65535"); } } diff --git a/test/hotspot/jtreg/runtime/records/recordReflectionTest.java b/test/hotspot/jtreg/runtime/records/recordReflectionTest.java index 5dc9fee5325..cf32a7d7e1d 100644 --- a/test/hotspot/jtreg/runtime/records/recordReflectionTest.java +++ b/test/hotspot/jtreg/runtime/records/recordReflectionTest.java @@ -23,7 +23,7 @@ /* * @test - * @compile --enable-preview --source 14 recordReflectionTest.java + * @compile --enable-preview --source ${jdk.version} recordReflectionTest.java * @run main/othervm --enable-preview recordReflectionTest */ From fa21d57760d57ab3224e3cc6aa9e483ac4410b24 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 6 Dec 2019 13:03:39 -0800 Subject: [PATCH 02/32] 8218268: Javac treats Manifest Class-Path entries as Paths instead of URLs Reviewed-by: mchung, bchristi --- .../com/sun/tools/javac/file/FSInfo.java | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java index 8cb18f42a44..ab0d3d8e3fd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,9 @@ import java.io.IOError; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -92,7 +95,6 @@ public boolean isFile(Path file) { } public List getJarClassPath(Path file) throws IOException { - Path parent = file.getParent(); try (JarFile jarFile = new JarFile(file.toFile())) { Manifest man = jarFile.getManifest(); if (man == null) @@ -107,17 +109,18 @@ public List getJarClassPath(Path file) throws IOException { return Collections.emptyList(); List list = new ArrayList<>(); + URL base = file.toUri().toURL(); for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) { String elt = st.nextToken(); try { - Path f = FileSystems.getDefault().getPath(elt); - if (!f.isAbsolute() && parent != null) - f = parent.resolve(f).toAbsolutePath(); - list.add(f); - } catch (InvalidPathException | IOError e) { - throw new IOException(e); + URL url = tryResolveFile(base, elt); + if (url != null) { + list.add(Path.of(url.toURI())); + } + } catch (URISyntaxException ex) { + throw new IOException(ex); } } @@ -125,6 +128,25 @@ public List getJarClassPath(Path file) throws IOException { } } + /** + * Attempt to return a file URL by resolving input against a base file + * URL. + * + * @return the resolved URL or null if the input is an absolute URL with + * a scheme other than file (ignoring case) + * @throws MalformedURLException + */ + static URL tryResolveFile(URL base, String input) throws MalformedURLException { + URL retVal = new URL(base, input); + if (input.indexOf(':') >= 0 && !"file".equalsIgnoreCase(retVal.getProtocol())) { + // 'input' contains a ':', which might be a scheme, or might be + // a Windows drive letter. If the resolved file has a protocol + // that isn't "file:", it should be ignored. + return null; + } + return retVal; + } + private FileSystemProvider jarFSProvider; public synchronized FileSystemProvider getJarFSProvider() { From e1921502c5e9a76d7c3f344c924175b13949997b Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 6 Dec 2019 13:32:46 -0800 Subject: [PATCH 03/32] 8235514: Update record serialization tests to not use hard coded source versions Reviewed-by: lancea --- .../io/Serializable/records/BadCanonicalCtrTest.java | 7 ++++--- .../io/Serializable/records/ProhibitedMethods.java | 7 ++++--- .../records/SerialPersistentFieldsTest.java | 11 ++++++----- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java b/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java index 510eb2e63cf..5e1a0b24933 100644 --- a/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java +++ b/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java @@ -59,6 +59,7 @@ * constructor cannot be found during deserialization. */ public class BadCanonicalCtrTest { + private static final String VERSION = Integer.toString(Runtime.version().feature()); // ClassLoader for creating instances of the records to test with. ClassLoader goodRecordClassLoader; @@ -79,7 +80,7 @@ public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("R1", "public record R1 () implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); goodRecordClassLoader = new ByteCodeLoader("R1", byteCode, BadCanonicalCtrTest.class.getClassLoader()); byte[] bc1 = removeConstructor(byteCode); missingCtrClassLoader = new ByteCodeLoader("R1", bc1, BadCanonicalCtrTest.class.getClassLoader()); @@ -89,7 +90,7 @@ public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("R2", "public record R2 (int x, int y) implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); goodRecordClassLoader = new ByteCodeLoader("R2", byteCode, goodRecordClassLoader); byte[] bc1 = removeConstructor(byteCode); missingCtrClassLoader = new ByteCodeLoader("R2", bc1, missingCtrClassLoader); @@ -101,7 +102,7 @@ public void setup() { "public record R3 (long l) implements java.io.Externalizable {" + " public void writeExternal(java.io.ObjectOutput out) { }" + " public void readExternal(java.io.ObjectInput in) { } }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); goodRecordClassLoader = new ByteCodeLoader("R3", byteCode, goodRecordClassLoader); byte[] bc1 = removeConstructor(byteCode); missingCtrClassLoader = new ByteCodeLoader("R3", bc1, missingCtrClassLoader); diff --git a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java index 2b7b252ca0a..35b34acb7e6 100644 --- a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java +++ b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java @@ -69,6 +69,7 @@ * record objects. */ public class ProhibitedMethods { + private static final String VERSION = Integer.toString(Runtime.version().feature()); public interface ThrowingExternalizable extends Externalizable { default void writeExternal(ObjectOutput out) { @@ -106,7 +107,7 @@ public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("Foo", "public record Foo () implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); byteCode = addWriteObject(byteCode); byteCode = addReadObject(byteCode); byteCode = addReadObjectNoData(byteCode); @@ -115,7 +116,7 @@ public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("Bar", "public record Bar (int x, int y) implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); byteCode = addWriteObject(byteCode); byteCode = addReadObject(byteCode); byteCode = addReadObjectNoData(byteCode); @@ -125,7 +126,7 @@ public void setup() { byte[] byteCode = InMemoryJavaCompiler.compile("Baz", "import java.io.Serializable;" + "public record Baz(U u, V v) implements Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); byteCode = addWriteObject(byteCode); byteCode = addReadObject(byteCode); byteCode = addReadObjectNoData(byteCode); diff --git a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java index 1bcdcdca5bb..c4d96d88c3b 100644 --- a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java @@ -64,6 +64,7 @@ * Checks that the serialPersistentFields declaration is effectively ignored. */ public class SerialPersistentFieldsTest { + private static final String VERSION = Integer.toString(Runtime.version().feature()); ClassLoader serializableRecordLoader; @@ -85,7 +86,7 @@ public void setup() { { // R1 byte[] byteCode = InMemoryJavaCompiler.compile("R1", "public record R1 () implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("s", String.class), new ObjectStreamField("i", int.class), @@ -98,7 +99,7 @@ public void setup() { { // R2 byte[] byteCode = InMemoryJavaCompiler.compile("R2", "public record R2 (int x) implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("s", String.class) }; @@ -108,7 +109,7 @@ public void setup() { { // R3 byte[] byteCode = InMemoryJavaCompiler.compile("R3", "public record R3 (int x, int y) implements java.io.Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; byteCode = addSerialPersistentFields(byteCode, serialPersistentFields); serializableRecordLoader = new ByteCodeLoader("R3", byteCode, serializableRecordLoader); @@ -117,7 +118,7 @@ public void setup() { byte[] byteCode = InMemoryJavaCompiler.compile("R4", "import java.io.Serializable;" + "public record R4(U u, V v) implements Serializable { }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("v", String.class) }; @@ -134,7 +135,7 @@ public void setup() { " @Override public void readExternal(ObjectInput in) {\n" + " throw new AssertionError(\"should not reach here\");\n" + " } }", - "--enable-preview", "-source", "14"); + "--enable-preview", "-source", VERSION); ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("v", String.class) }; From 41b4803cdf4f6fd1e170c0b4bfc587893303f956 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 6 Dec 2019 14:47:05 -0800 Subject: [PATCH 04/32] 8235438: [JVMCI] StackTraceElement::decode should use the original Method Reviewed-by: coleenp, never --- src/hotspot/share/classfile/javaClasses.cpp | 90 ++++++++++----------- src/hotspot/share/classfile/javaClasses.hpp | 7 +- src/hotspot/share/jvmci/jvmciEnv.cpp | 5 +- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 99ce25575fc..e7897e601a7 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -2709,62 +2709,58 @@ void java_lang_StackTraceElement::fill_in(Handle element, java_lang_StackTraceElement::set_fileName(element(), NULL); java_lang_StackTraceElement::set_lineNumber(element(), -1); } else { - // Fill in source file name and line number. - Symbol* source = Backtrace::get_source_file_name(holder, version); - oop source_file = java_lang_Class::source_file(java_class()); - if (source != NULL) { - // Class was not redefined. We can trust its cache if set, - // else we have to initialize it. - if (source_file == NULL) { - source_file = StringTable::intern(source, CHECK); - java_lang_Class::set_source_file(java_class(), source_file); - } - } else { - // Class was redefined. Dump the cache if it was set. - if (source_file != NULL) { - source_file = NULL; - java_lang_Class::set_source_file(java_class(), source_file); - } - } - java_lang_StackTraceElement::set_fileName(element(), source_file); + Symbol* source; + oop source_file; + int line_number; + decode_file_and_line(java_class, holder, version, method, bci, source, source_file, line_number, CHECK); - int line_number = Backtrace::get_line_number(method(), bci); + java_lang_StackTraceElement::set_fileName(element(), source_file); java_lang_StackTraceElement::set_lineNumber(element(), line_number); } } -#if INCLUDE_JVMCI -void java_lang_StackTraceElement::decode(Handle mirror, methodHandle method, int bci, Symbol*& methodname, Symbol*& filename, int& line_number) { - int method_id = method->orig_method_idnum(); - int cpref = method->name_index(); - decode(mirror, method_id, method->constants()->version(), bci, cpref, methodname, filename, line_number); +void java_lang_StackTraceElement::decode_file_and_line(Handle java_class, + InstanceKlass* holder, + int version, + const methodHandle& method, + int bci, + Symbol*& source, + oop& source_file, + int& line_number, TRAPS) { + // Fill in source file name and line number. + source = Backtrace::get_source_file_name(holder, version); + source_file = java_lang_Class::source_file(java_class()); + if (source != NULL) { + // Class was not redefined. We can trust its cache if set, + // else we have to initialize it. + if (source_file == NULL) { + source_file = StringTable::intern(source, CHECK); + java_lang_Class::set_source_file(java_class(), source_file); + } + } else { + // Class was redefined. Dump the cache if it was set. + if (source_file != NULL) { + source_file = NULL; + java_lang_Class::set_source_file(java_class(), source_file); + } + } + line_number = Backtrace::get_line_number(method(), bci); } -void java_lang_StackTraceElement::decode(Handle mirror, int method_id, int version, int bci, int cpref, Symbol*& methodname, Symbol*& filename, int& line_number) { - // Fill in class name - InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); - Method* method = holder->method_with_orig_idnum(method_id, version); - - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); +#if INCLUDE_JVMCI +void java_lang_StackTraceElement::decode(const methodHandle& method, int bci, + Symbol*& filename, int& line_number, TRAPS) { + ResourceMark rm(THREAD); + HandleMark hm(THREAD); - // Fill in method name - methodname = sym; + filename = NULL; + line_number = -1; - if (!version_matches(method, version)) { - // If the method was redefined, accurate line number information isn't available - filename = NULL; - line_number = -1; - } else { - // Fill in source file name and line number. - // Use a specific ik version as a holder since the mirror might - // refer to a version that is now obsolete and no longer accessible - // via the previous versions list. - holder = holder->get_klass_version(version); - assert(holder != NULL, "sanity check"); - filename = holder->source_file_name(); - line_number = Backtrace::get_line_number(method, bci); - } + oop source_file; + int version = method->constants()->version(); + InstanceKlass* holder = method->method_holder(); + Handle java_class(THREAD, holder->java_mirror()); + decode_file_and_line(java_class, holder, version, method, bci, filename, source_file, line_number, CHECK); } #endif // INCLUDE_JVMCI diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 27c952e82e2..149463578f8 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -1401,6 +1401,10 @@ class java_lang_StackTraceElement: AllStatic { static void set_lineNumber(oop element, int value); static void set_declaringClassObject(oop element, oop value); + static void decode_file_and_line(Handle java_mirror, InstanceKlass* holder, int version, + const methodHandle& method, int bci, + Symbol*& source, oop& source_file, int& line_number, TRAPS); + public: // Create an instance of StackTraceElement static oop create(const methodHandle& method, int bci, TRAPS); @@ -1412,8 +1416,7 @@ class java_lang_StackTraceElement: AllStatic { static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; #if INCLUDE_JVMCI - static void decode(Handle mirror, int method, int version, int bci, int cpref, Symbol*& methodName, Symbol*& fileName, int& lineNumber); - static void decode(Handle mirror, methodHandle method, int bci, Symbol*& methodName, Symbol*& fileName, int& lineNumber); + static void decode(const methodHandle& method, int bci, Symbol*& fileName, int& lineNumber, TRAPS); #endif // Debugging diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index d1ba906ed47..ff19eb1bc08 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -898,12 +898,11 @@ JVMCIObject JVMCIEnv::get_jvmci_primitive_type(BasicType type) { JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS) { JavaThread* THREAD = JavaThread::current(); - Symbol* method_name_sym; Symbol* file_name_sym; int line_number; - Handle mirror (THREAD, method->method_holder()->java_mirror()); - java_lang_StackTraceElement::decode(mirror, method, bci, method_name_sym, file_name_sym, line_number); + java_lang_StackTraceElement::decode(method, bci, file_name_sym, line_number, CHECK_(JVMCIObject())); + Symbol* method_name_sym = method->name(); InstanceKlass* holder = method->method_holder(); const char* declaring_class_str = holder->external_name(); From e7fa637179bfa685af2b67cddc9f7403d06aaec5 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 6 Dec 2019 15:10:40 -0800 Subject: [PATCH 05/32] 8235351: Lookup::unreflect should bind with the original caller independent of Method's accessible flag Reviewed-by: alanb --- .../java/lang/invoke/MethodHandles.java | 63 +++++++++---------- .../lang/invoke/CallerSensitiveAccess.java | 23 ++++++- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 45631cfecd9..16362f54ccc 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -1789,7 +1789,7 @@ public String toString() { */ public MethodHandle findStatic(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); - return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method)); + return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerLookup(method)); } /** @@ -1881,7 +1881,7 @@ public MethodHandle findVirtual(Class refc, String name, MethodType type) thr } byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); - return getDirectMethod(refKind, refc, method, findBoundCallerClass(method)); + return getDirectMethod(refKind, refc, method, findBoundCallerLookup(method)); } private MethodHandle findVirtualForMH(String name, MethodType type) { // these names require special lookups because of the implicit MethodType argument @@ -2133,7 +2133,7 @@ public MethodHandle findSpecial(Class refc, String name, MethodType type, checkSpecialCaller(specialCaller, refc); Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); + return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerLookup(method)); } /** @@ -2434,7 +2434,7 @@ public VarHandle findStaticVarHandle(Class decl, String name, Class type) public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); - MethodHandle mh = getDirectMethodNoRestrictInvokeSpecial(refc, method, findBoundCallerClass(method)); + MethodHandle mh = getDirectMethodNoRestrictInvokeSpecial(refc, method, findBoundCallerLookup(method)); if (!mh.type().leadingReferenceParameter().isAssignableFrom(receiver.getClass())) { throw new IllegalAccessException("The restricted defining class " + mh.type().leadingReferenceParameter().getName() + @@ -2486,7 +2486,7 @@ public MethodHandle unreflect(Method m) throws IllegalAccessException { assert(method.isMethod()); @SuppressWarnings("deprecation") Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); + return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerLookup(method)); } private MethodHandle unreflectForMH(Method m) { // these names require special lookups because they throw UnsupportedOperationException @@ -2537,7 +2537,7 @@ public MethodHandle unreflectSpecial(Method m, Class specialCaller) throws Il MemberName method = new MemberName(m, true); assert(method.isMethod()); // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method)); + return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerLookup(method)); } /** @@ -2828,17 +2828,12 @@ void checkMethodName(byte refKind, String name) throws NoSuchMethodException { * If this lookup object has full privilege access, then the caller class is the lookupClass. * Otherwise, if m is caller-sensitive, throw IllegalAccessException. */ - Class findBoundCallerClass(MemberName m) throws IllegalAccessException { - Class callerClass = null; - if (MethodHandleNatives.isCallerSensitive(m)) { + Lookup findBoundCallerLookup(MemberName m) throws IllegalAccessException { + if (MethodHandleNatives.isCallerSensitive(m) && !hasFullPrivilegeAccess()) { // Only lookups with full privilege access are allowed to resolve caller-sensitive methods - if (hasFullPrivilegeAccess()) { - callerClass = lookupClass; - } else { - throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); - } + throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); } - return callerClass; + return this; } /** @@ -3042,28 +3037,28 @@ private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, } /** Check access and get the requested method. */ - private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method, Class boundCallerClass) throws IllegalAccessException { + private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method, Lookup callerLookup) throws IllegalAccessException { final boolean doRestrict = true; final boolean checkSecurity = true; - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, boundCallerClass); + return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup); } /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */ - private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class refc, MemberName method, Class boundCallerClass) throws IllegalAccessException { + private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class refc, MemberName method, Lookup callerLookup) throws IllegalAccessException { final boolean doRestrict = false; final boolean checkSecurity = true; - return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, boundCallerClass); + return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup); } /** Check access and get the requested method, eliding security manager checks. */ - private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class refc, MemberName method, Class boundCallerClass) throws IllegalAccessException { + private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class refc, MemberName method, Lookup callerLookup) throws IllegalAccessException { final boolean doRestrict = true; final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, boundCallerClass); + return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup); } /** Common code for all methods; do not call directly except from immediately above. */ private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberName method, boolean checkSecurity, - boolean doRestrict, Class boundCallerClass) throws IllegalAccessException { - + boolean doRestrict, + Lookup boundCaller) throws IllegalAccessException { checkMethod(refKind, refc, method); // Optionally check with the security manager; this isn't needed for unreflect* calls. if (checkSecurity) @@ -3101,7 +3096,6 @@ private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberNa // redo basic checks checkMethod(refKind, refc, method); } - DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method, lookupClass()); MethodHandle mh = dmh; // Optionally narrow the receiver argument to lookupClass using restrictReceiver. @@ -3109,22 +3103,25 @@ private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberNa (MethodHandleNatives.refKindHasReceiver(refKind) && restrictProtectedReceiver(method))) { mh = restrictReceiver(method, dmh, lookupClass()); } - mh = maybeBindCaller(method, mh, boundCallerClass); + mh = maybeBindCaller(method, mh, boundCaller); mh = mh.setVarargs(method); return mh; } - private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, - Class boundCallerClass) + private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, Lookup boundCaller) throws IllegalAccessException { - if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) + if (boundCaller.allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) return mh; - Class hostClass = lookupClass; - if (!hasFullPrivilegeAccess()) // caller must have full power access - hostClass = boundCallerClass; // boundCallerClass came from a security manager style stack walk - MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); + + // boundCaller must have full privilege access. + // It should have been checked by findBoundCallerLookup. Safe to check this again. + if (!boundCaller.hasFullPrivilegeAccess()) + throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); + + MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, boundCaller.lookupClass); // Note: caller will apply varargs after this step happens. return cbmh; } + /** Check access and get the requested field. */ private MethodHandle getDirectField(byte refKind, Class refc, MemberName field) throws IllegalAccessException { final boolean checkSecurity = true; @@ -3296,7 +3293,7 @@ private MethodHandle getDirectMethodForConstant(byte refKind, Class defc, Mem if (MethodHandleNatives.refKindIsField(refKind)) { return getDirectFieldNoSecurityManager(refKind, defc, member); } else if (MethodHandleNatives.refKindIsMethod(refKind)) { - return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass); + return getDirectMethodNoSecurityManager(refKind, defc, member, findBoundCallerLookup(member)); } else if (refKind == REF_newInvokeSpecial) { return getDirectConstructorNoSecurityManager(defc, member); } diff --git a/test/jdk/java/lang/invoke/CallerSensitiveAccess.java b/test/jdk/java/lang/invoke/CallerSensitiveAccess.java index 379e305874c..a8aa649059e 100644 --- a/test/jdk/java/lang/invoke/CallerSensitiveAccess.java +++ b/test/jdk/java/lang/invoke/CallerSensitiveAccess.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 8196830 + * @bug 8196830 8235351 * @modules java.base/jdk.internal.reflect * @run testng/othervm --illegal-access=deny CallerSensitiveAccess * @summary Check Lookup findVirtual, findStatic and unreflect behavior with @@ -95,6 +95,27 @@ public void testPublicLookupUnreflect(@NoInjection Method method, String desc) t MethodHandles.publicLookup().unreflect(method); } + /** + * public accessible caller sensitive methods in APIs exported by java.base. + */ + @DataProvider(name = "accessibleCallerSensitiveMethods") + static Object[][] accessibleCallerSensitiveMethods() { + return callerSensitiveMethods(Object.class.getModule()) + .filter(m -> Modifier.isPublic(m.getModifiers())) + .map(m -> { m.setAccessible(true); return m; }) + .map(m -> new Object[] { m, shortDescription(m) }) + .toArray(Object[][]::new); + } + + /** + * Using publicLookup, attempt to use unreflect to obtain a method handle to a + * caller sensitive method. + */ + @Test(dataProvider = "accessibleCallerSensitiveMethods", + expectedExceptions = IllegalAccessException.class) + public void testLookupUnreflect(@NoInjection Method method, String desc) throws Exception { + MethodHandles.publicLookup().unreflect(method); + } // -- Test method handles to setAccessible -- From 6a547f9574ae16b4d69b70e27a59966e36593443 Mon Sep 17 00:00:00 2001 From: Sandhya Viswanathan Date: Fri, 6 Dec 2019 16:03:44 -0800 Subject: [PATCH 06/32] 8235510: java.util.zip.CRC32 performance drop after 8200067 Backout 8200067 optimization Reviewed-by: kvn --- src/hotspot/cpu/x86/assembler_x86.cpp | 2 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 28 ---------------------- src/hotspot/cpu/x86/vm_version_x86.cpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 10 ++++---- 4 files changed, 7 insertions(+), 35 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 67f2ad39297..dd94fdea557 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -7232,7 +7232,7 @@ void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, in } void Assembler::evpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask, int vector_len) { - assert(VM_Version::supports_vpclmulqdq(), "Requires vector carryless multiplication support"); + assert(VM_Version::supports_avx512_vpclmulqdq(), "Requires vector carryless multiplication support"); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 4eff694a4aa..5a56c77d27c 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -8945,34 +8945,6 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, Regi shrl(len, 4); jcc(Assembler::zero, L_tail_restore); - // Fold total 512 bits of polynomial on each iteration - if (VM_Version::supports_vpclmulqdq()) { - Label Parallel_loop, L_No_Parallel; - - cmpl(len, 8); - jccb(Assembler::less, L_No_Parallel); - - movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr() + 32)); - evmovdquq(xmm1, Address(buf, 0), Assembler::AVX_512bit); - movdl(xmm5, crc); - evpxorq(xmm1, xmm1, xmm5, Assembler::AVX_512bit); - addptr(buf, 64); - subl(len, 7); - evshufi64x2(xmm0, xmm0, xmm0, 0x00, Assembler::AVX_512bit); //propagate the mask from 128 bits to 512 bits - - BIND(Parallel_loop); - fold_128bit_crc32_avx512(xmm1, xmm0, xmm5, buf, 0); - addptr(buf, 64); - subl(len, 4); - jcc(Assembler::greater, Parallel_loop); - - vextracti64x2(xmm2, xmm1, 0x01); - vextracti64x2(xmm3, xmm1, 0x02); - vextracti64x2(xmm4, xmm1, 0x03); - jmp(L_fold_512b); - - BIND(L_No_Parallel); - } // Fold crc into first bytes of vector movdqa(xmm1, Address(buf, 0)); movdl(rax, xmm1); diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 3be590bded1..f47985e0ca4 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -691,7 +691,7 @@ void VM_Version::get_processor_features() { _features &= ~CPU_AVX512BW; _features &= ~CPU_AVX512VL; _features &= ~CPU_AVX512_VPOPCNTDQ; - _features &= ~CPU_VPCLMULQDQ; + _features &= ~CPU_AVX512_VPCLMULQDQ; _features &= ~CPU_VAES; } diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 0f3d5a56c06..cab645bd7e1 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -245,7 +245,7 @@ class VM_Version : public Abstract_VM_Version { : 1, gfni : 1, vaes : 1, - vpclmulqdq : 1, + avx512_vpclmulqdq : 1, avx512_vnni : 1, avx512_bitalg : 1, : 1, @@ -338,7 +338,7 @@ class VM_Version : public Abstract_VM_Version { #define CPU_FMA ((uint64_t)UCONST64(0x800000000)) // FMA instructions #define CPU_VZEROUPPER ((uint64_t)UCONST64(0x1000000000)) // Vzeroupper instruction #define CPU_AVX512_VPOPCNTDQ ((uint64_t)UCONST64(0x2000000000)) // Vector popcount -#define CPU_VPCLMULQDQ ((uint64_t)UCONST64(0x4000000000)) //Vector carryless multiplication +#define CPU_AVX512_VPCLMULQDQ ((uint64_t)UCONST64(0x4000000000)) //Vector carryless multiplication #define CPU_VAES ((uint64_t)UCONST64(0x8000000000)) // Vector AES instructions #define CPU_VNNI ((uint64_t)UCONST64(0x10000000000)) // Vector Neural Network Instructions @@ -561,8 +561,8 @@ enum Extended_Family { result |= CPU_AVX512VL; if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0) result |= CPU_AVX512_VPOPCNTDQ; - if (_cpuid_info.sef_cpuid7_ecx.bits.vpclmulqdq != 0) - result |= CPU_VPCLMULQDQ; + if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0) + result |= CPU_AVX512_VPCLMULQDQ; if (_cpuid_info.sef_cpuid7_ecx.bits.vaes != 0) result |= CPU_VAES; if (_cpuid_info.sef_cpuid7_ecx.bits.avx512_vnni != 0) @@ -855,7 +855,7 @@ enum Extended_Family { static bool supports_fma() { return (_features & CPU_FMA) != 0 && supports_avx(); } static bool supports_vzeroupper() { return (_features & CPU_VZEROUPPER) != 0; } static bool supports_vpopcntdq() { return (_features & CPU_AVX512_VPOPCNTDQ) != 0; } - static bool supports_vpclmulqdq() { return (_features & CPU_VPCLMULQDQ) != 0; } + static bool supports_avx512_vpclmulqdq() { return (_features & CPU_AVX512_VPCLMULQDQ) != 0; } static bool supports_vaes() { return (_features & CPU_VAES) != 0; } static bool supports_vnni() { return (_features & CPU_VNNI) != 0; } From 36bd09dead31636e71ab9d74edff130cbd5124a4 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Sat, 7 Dec 2019 09:40:28 +0800 Subject: [PATCH 07/32] 8233222: Clarify system property usage in KerberosPrincipal instantiation Reviewed-by: mullan --- .../auth/kerberos/KerberosPrincipal.java | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java index d52421ca8f4..69bbcaf16d9 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java @@ -106,10 +106,19 @@ public final class KerberosPrincipal * *

If the input name does not contain a realm, the default realm * is used. The default realm can be specified either in a Kerberos - * configuration file or via the java.security.krb5.realm + * configuration file or via the {@systemproperty java.security.krb5.realm} * system property. For more information, see the * {@extLink security_guide_jgss_tutorial Kerberos Requirements}. - * Additionally, if a security manager is + * + *

Note that when this class or any other Kerberos-related class is + * initially loaded and initialized, it may read and cache the default + * realm from the Kerberos configuration file or via the + * java.security.krb5.realm system property (the value will be empty if + * no default realm is specified), such that any subsequent calls to set + * or change the default realm by setting the java.security.krb5.realm + * system property may be ignored. + * + *

Additionally, if a security manager is * installed, a {@link ServicePermission} must be granted and the service * principal of the permission must minimally be inside the * {@code KerberosPrincipal}'s realm. For example, if the result of @@ -146,10 +155,19 @@ public KerberosPrincipal(String name) { * *

If the input name does not contain a realm, the default realm * is used. The default realm can be specified either in a Kerberos - * configuration file or via the java.security.krb5.realm + * configuration file or via the {@systemproperty java.security.krb5.realm} * system property. For more information, see the * {@extLink security_guide_jgss_tutorial Kerberos Requirements}. - * Additionally, if a security manager is + * + *

Note that when this class or any other Kerberos-related class is + * initially loaded and initialized, it may read and cache the default + * realm from the Kerberos configuration file or via the + * java.security.krb5.realm system property (the value will be empty if + * no default realm is specified), such that any subsequent calls to set + * or change the default realm by setting the java.security.krb5.realm + * system property may be ignored. + * + *

Additionally, if a security manager is * installed, a {@link ServicePermission} must be granted and the service * principal of the permission must minimally be inside the * {@code KerberosPrincipal}'s realm. For example, if the result of From ee140f7f816dc6f8cb73cb52b1a499e1074499c0 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Sun, 8 Dec 2019 10:05:57 -0500 Subject: [PATCH 08/32] 8235262: Move c2i_entry_barrier for x86_32 to shared Reviewed-by: rkennke, eosterlund --- .../x86/gc/shared/barrierSetAssembler_x86.cpp | 35 ++++++++++---- .../shenandoahBarrierSetAssembler_x86.cpp | 46 ------------------- .../shenandoahBarrierSetAssembler_x86.hpp | 2 - 3 files changed, 27 insertions(+), 56 deletions(-) diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index ef4791e351a..af4ed123e6a 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -374,22 +374,41 @@ void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters. __ jcc(Assembler::equal, bad_call); +#ifdef _LP64 + Register tmp1 = rscratch1; + Register tmp2 = rscratch2; +#else + Register tmp1 = rax; + Register tmp2 = rcx; + __ push(tmp1); + __ push(tmp2); +#endif // _LP64 + // Pointer chase to the method holder to find out if the method is concurrently unloading. Label method_live; - __ load_method_holder_cld(rscratch1, rbx); + __ load_method_holder_cld(tmp1, rbx); - // Is it a strong CLD? - __ movl(rscratch2, Address(rscratch1, ClassLoaderData::keep_alive_offset())); - __ cmpptr(rscratch2, 0); + // Is it a strong CLD? + __ cmpl(Address(tmp1, ClassLoaderData::keep_alive_offset()), 0); __ jcc(Assembler::greater, method_live); - // Is it a weak but alive CLD? - __ movptr(rscratch1, Address(rscratch1, ClassLoaderData::holder_offset())); - __ resolve_weak_handle(rscratch1, rscratch2); - __ cmpptr(rscratch1, 0); + // Is it a weak but alive CLD? + __ movptr(tmp1, Address(tmp1, ClassLoaderData::holder_offset())); + __ resolve_weak_handle(tmp1, tmp2); + __ cmpptr(tmp1, 0); __ jcc(Assembler::notEqual, method_live); +#ifndef _LP64 + __ pop(tmp2); + __ pop(tmp1); +#endif + __ bind(bad_call); __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); __ bind(method_live); + +#ifndef _LP64 + __ pop(tmp2); + __ pop(tmp1); +#endif } diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index 5c082f65e6f..551433b8f66 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -395,52 +395,6 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_native(MacroAssembler __ block_comment("load_reference_barrier_native { "); } -#ifdef _LP64 -void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { - // Use default version - BarrierSetAssembler::c2i_entry_barrier(masm); -} -#else -void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { - BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod(); - if (bs == NULL) { - return; - } - - Label bad_call; - __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters. - __ jcc(Assembler::equal, bad_call); - - Register tmp1 = rax; - Register tmp2 = rcx; - - __ push(tmp1); - __ push(tmp2); - - // Pointer chase to the method holder to find out if the method is concurrently unloading. - Label method_live; - __ load_method_holder_cld(tmp1, rbx); - - // Is it a strong CLD? - __ cmpl(Address(tmp1, ClassLoaderData::keep_alive_offset()), 0); - __ jcc(Assembler::greater, method_live); - - // Is it a weak but alive CLD? - __ movptr(tmp1, Address(tmp1, ClassLoaderData::holder_offset())); - __ resolve_weak_handle(tmp1, tmp2); - __ cmpptr(tmp1, 0); - __ jcc(Assembler::notEqual, method_live); - __ pop(tmp2); - __ pop(tmp1); - - __ bind(bad_call); - __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); - __ bind(method_live); - __ pop(tmp2); - __ pop(tmp1); -} -#endif - void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) { if (ShenandoahStoreValEnqueueBarrier) { storeval_barrier_impl(masm, dst, tmp); diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp index b4d5089a568..32480066752 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp @@ -86,8 +86,6 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { Address dst, Register val, Register tmp1, Register tmp2); virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); - virtual void c2i_entry_barrier(MacroAssembler* masm); - virtual void barrier_stubs_init(); }; From 228c3144d296b3369c99bce0dd50a00719ebb18c Mon Sep 17 00:00:00 2001 From: Rahul Raghavan Date: Mon, 9 Dec 2019 14:02:03 +0530 Subject: [PATCH 09/32] 8233453: MLVM deoptimize stress test timed out Increased timeout factor for MLVM deoptimize stress test Reviewed-by: iignatyev, thartmann --- .../vm/mlvm/meth/stress/compiler/deoptimize/Test.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java index b6b0a5467af..f1ae9a219be 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java @@ -45,7 +45,7 @@ * * @requires vm.debug != true * - * @run main/othervm + * @run main/othervm/timeout=300 * -XX:ReservedCodeCacheSize=100m * vm.mlvm.meth.stress.compiler.deoptimize.Test * -threadsPerCpu 4 @@ -67,7 +67,7 @@ * * @requires vm.debug == true * - * @run main/othervm + * @run main/othervm/timeout=300 * -XX:ReservedCodeCacheSize=100m * vm.mlvm.meth.stress.compiler.deoptimize.Test * -threadsPerCpu 2 From 4c4d6cdc929dd6286adc98ee45c9787f05f38548 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 9 Dec 2019 10:16:01 +0100 Subject: [PATCH 10/32] 8235483: Warnings printed during the build Reviewed-by: erikj --- make/gendata/Gendata-jdk.compiler.gmk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make/gendata/Gendata-jdk.compiler.gmk b/make/gendata/Gendata-jdk.compiler.gmk index b5c722647ee..eb08bdc421c 100644 --- a/make/gendata/Gendata-jdk.compiler.gmk +++ b/make/gendata/Gendata-jdk.compiler.gmk @@ -45,6 +45,7 @@ CT_MODULESOURCEPATH := $(call GetModuleSrcPath) CT_DATA_DESCRIPTION += $(TOPDIR)/make/data/symbols/symbols COMPILECREATESYMBOLS_ADD_EXPORTS := \ + --add-exports java.base/jdk.internal=java.compiler.interim,jdk.compiler.interim \ --add-exports jdk.compiler.interim/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports jdk.compiler.interim/com.sun.tools.javac.code=ALL-UNNAMED \ --add-exports jdk.compiler.interim/com.sun.tools.javac.util=ALL-UNNAMED \ @@ -58,6 +59,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \ INCLUDES := build/tools/symbolgenerator com/sun/tools/classfile, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols, \ ADD_JAVAC_FLAGS := $(INTERIM_LANGTOOLS_ARGS) \ + --patch-module java.base=$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim \ $(COMPILECREATESYMBOLS_ADD_EXPORTS), \ )) From 9cabfa82ffa4dec1e96644e853e2fb4edfa26759 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Mon, 9 Dec 2019 10:26:41 +0100 Subject: [PATCH 11/32] 8165443: Free Collection Set serial phase takes very long on large heaps Reviewed-by: tschatzl, kbarrett --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 453 +++++++++--------- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 5 + src/hotspot/share/gc/g1/g1CollectionSet.cpp | 26 +- src/hotspot/share/gc/g1/g1CollectionSet.hpp | 14 + src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 22 +- src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp | 20 +- src/hotspot/share/gc/g1/g1Policy.cpp | 2 +- src/hotspot/share/gc/g1/heapRegion.cpp | 13 + src/hotspot/share/gc/g1/heapRegion.hpp | 9 +- src/hotspot/share/gc/g1/heapRegionManager.cpp | 77 +++ src/hotspot/share/gc/g1/heapRegionManager.hpp | 3 + src/hotspot/share/gc/g1/heapRegionSet.cpp | 56 ++- src/hotspot/share/gc/g1/heapRegionSet.hpp | 11 + .../share/gc/g1/heapRegionSet.inline.hpp | 20 + .../jtreg/gc/g1/TestGCLogMessages.java | 8 +- .../gc/collection/TestG1ParallelPhases.java | 4 +- 16 files changed, 496 insertions(+), 247 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 8adcc138125..c4f5aa34eba 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -98,6 +98,7 @@ #include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" #include "utilities/align.hpp" +#include "utilities/bitMap.inline.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/stack.inline.hpp" @@ -2366,6 +2367,10 @@ void G1CollectedHeap::collection_set_iterate_all(HeapRegionClosure* cl) { _collection_set.iterate(cl); } +void G1CollectedHeap::collection_set_par_iterate_all(HeapRegionClosure* cl, HeapRegionClaimer* hr_claimer, uint worker_id) { + _collection_set.par_iterate(cl, hr_claimer, worker_id, workers()->active_workers()); +} + void G1CollectedHeap::collection_set_iterate_increment_from(HeapRegionClosure *cl, HeapRegionClaimer* hr_claimer, uint worker_id) { _collection_set.iterate_incremental_part_from(cl, hr_claimer, worker_id, workers()->active_workers()); } @@ -4079,7 +4084,6 @@ void G1CollectedHeap::free_region(HeapRegion* hr, assert(!hr->is_free(), "the region should not be free"); assert(!hr->is_empty(), "the region should not be empty"); assert(_hrm->is_available(hr->hrm_index()), "region should be committed"); - assert(free_list != NULL, "pre-condition"); if (G1VerifyBitmaps) { MemRegion mr(hr->bottom(), hr->end()); @@ -4094,7 +4098,9 @@ void G1CollectedHeap::free_region(HeapRegion* hr, } hr->hr_clear(skip_remset, true /* clear_space */, locked /* locked */); _policy->remset_tracker()->update_at_free(hr); - free_list->add_ordered(hr); + if (free_list != NULL) { + free_list->add_ordered(hr); + } } void G1CollectedHeap::free_humongous_region(HeapRegion* hr, @@ -4128,281 +4134,282 @@ void G1CollectedHeap::decrement_summary_bytes(size_t bytes) { } class G1FreeCollectionSetTask : public AbstractGangTask { -private: - - // Closure applied to all regions in the collection set to do work that needs to - // be done serially in a single thread. - class G1SerialFreeCollectionSetClosure : public HeapRegionClosure { - private: - G1EvacuationInfo* _evacuation_info; - const size_t* _surviving_young_words; - - // Bytes used in successfully evacuated regions before the evacuation. - size_t _before_used_bytes; - // Bytes used in unsucessfully evacuated regions before the evacuation - size_t _after_used_bytes; - - size_t _bytes_allocated_in_old_since_last_gc; - - size_t _failure_used_words; - size_t _failure_waste_words; - - FreeRegionList _local_free_list; + // Helper class to keep statistics for the collection set freeing + class FreeCSetStats { + size_t _before_used_bytes; // Usage in regions successfully evacutate + size_t _after_used_bytes; // Usage in regions failing evacuation + size_t _bytes_allocated_in_old_since_last_gc; // Size of young regions turned into old + size_t _failure_used_words; // Live size in failed regions + size_t _failure_waste_words; // Wasted size in failed regions + size_t _rs_length; // Remembered set size + uint _regions_freed; // Number of regions freed public: - G1SerialFreeCollectionSetClosure(G1EvacuationInfo* evacuation_info, const size_t* surviving_young_words) : - HeapRegionClosure(), - _evacuation_info(evacuation_info), - _surviving_young_words(surviving_young_words), - _before_used_bytes(0), - _after_used_bytes(0), - _bytes_allocated_in_old_since_last_gc(0), - _failure_used_words(0), - _failure_waste_words(0), - _local_free_list("Local Region List for CSet Freeing") { + FreeCSetStats() : + _before_used_bytes(0), + _after_used_bytes(0), + _bytes_allocated_in_old_since_last_gc(0), + _failure_used_words(0), + _failure_waste_words(0), + _rs_length(0), + _regions_freed(0) { } + + void merge_stats(FreeCSetStats* other) { + assert(other != NULL, "invariant"); + _before_used_bytes += other->_before_used_bytes; + _after_used_bytes += other->_after_used_bytes; + _bytes_allocated_in_old_since_last_gc += other->_bytes_allocated_in_old_since_last_gc; + _failure_used_words += other->_failure_used_words; + _failure_waste_words += other->_failure_waste_words; + _rs_length += other->_rs_length; + _regions_freed += other->_regions_freed; } - virtual bool do_heap_region(HeapRegion* r) { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); + void report(G1CollectedHeap* g1h, G1EvacuationInfo* evacuation_info) { + evacuation_info->set_regions_freed(_regions_freed); + evacuation_info->increment_collectionset_used_after(_after_used_bytes); - assert(r->in_collection_set(), "Region %u should be in collection set.", r->hrm_index()); - g1h->clear_region_attr(r); + g1h->decrement_summary_bytes(_before_used_bytes); + g1h->alloc_buffer_stats(G1HeapRegionAttr::Old)->add_failure_used_and_waste(_failure_used_words, _failure_waste_words); - if (r->is_young()) { - assert(r->young_index_in_cset() != 0 && (uint)r->young_index_in_cset() <= g1h->collection_set()->young_region_length(), - "Young index %u is wrong for region %u of type %s with %u young regions", - r->young_index_in_cset(), - r->hrm_index(), - r->get_type_str(), - g1h->collection_set()->young_region_length()); - size_t words_survived = _surviving_young_words[r->young_index_in_cset()]; - r->record_surv_words_in_group(words_survived); - } + G1Policy *policy = g1h->policy(); + policy->add_bytes_allocated_in_old_since_last_gc(_bytes_allocated_in_old_since_last_gc); + policy->record_rs_length(_rs_length); + policy->cset_regions_freed(); + } - if (!r->evacuation_failed()) { - assert(!r->is_empty(), "Region %u is an empty region in the collection set.", r->hrm_index()); - _before_used_bytes += r->used(); - g1h->free_region(r, - &_local_free_list, - true, /* skip_remset */ - true, /* skip_hot_card_cache */ - true /* locked */); - } else { - r->uninstall_surv_rate_group(); - r->clear_young_index_in_cset(); - r->set_evacuation_failed(false); - // When moving a young gen region to old gen, we "allocate" that whole region - // there. This is in addition to any already evacuated objects. Notify the - // policy about that. - // Old gen regions do not cause an additional allocation: both the objects - // still in the region and the ones already moved are accounted for elsewhere. - if (r->is_young()) { - _bytes_allocated_in_old_since_last_gc += HeapRegion::GrainBytes; - } - // The region is now considered to be old. - r->set_old(); - // Do some allocation statistics accounting. Regions that failed evacuation - // are always made old, so there is no need to update anything in the young - // gen statistics, but we need to update old gen statistics. - size_t used_words = r->marked_bytes() / HeapWordSize; - - _failure_used_words += used_words; - _failure_waste_words += HeapRegion::GrainWords - used_words; - - g1h->old_set_add(r); - _after_used_bytes += r->used(); + void account_failed_region(HeapRegion* r) { + size_t used_words = r->marked_bytes() / HeapWordSize; + _failure_used_words += used_words; + _failure_waste_words += HeapRegion::GrainWords - used_words; + _after_used_bytes += r->used(); + + // When moving a young gen region to old gen, we "allocate" that whole + // region there. This is in addition to any already evacuated objects. + // Notify the policy about that. Old gen regions do not cause an + // additional allocation: both the objects still in the region and the + // ones already moved are accounted for elsewhere. + if (r->is_young()) { + _bytes_allocated_in_old_since_last_gc += HeapRegion::GrainBytes; } - return false; } - void complete_work() { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - - _evacuation_info->set_regions_freed(_local_free_list.length()); - _evacuation_info->increment_collectionset_used_after(_after_used_bytes); - - g1h->prepend_to_freelist(&_local_free_list); - g1h->decrement_summary_bytes(_before_used_bytes); - - G1Policy* policy = g1h->policy(); - policy->add_bytes_allocated_in_old_since_last_gc(_bytes_allocated_in_old_since_last_gc); + void account_evacuated_region(HeapRegion* r) { + _before_used_bytes += r->used(); + _regions_freed += 1; + } - g1h->alloc_buffer_stats(G1HeapRegionAttr::Old)->add_failure_used_and_waste(_failure_used_words, _failure_waste_words); + void account_rs_length(HeapRegion* r) { + _rs_length += r->rem_set()->occupied(); } }; - G1CollectionSet* _collection_set; - G1SerialFreeCollectionSetClosure _cl; - const size_t* _surviving_young_words; - - size_t _rs_length; - - volatile jint _serial_work_claim; + // Closure applied to all regions in the collection set. + class FreeCSetClosure : public HeapRegionClosure { + // Helper to send JFR events for regions. + class JFREventForRegion { + EventGCPhaseParallel _event; + public: + JFREventForRegion(HeapRegion* region, uint worker_id) : _event() { + _event.set_gcId(GCId::current()); + _event.set_gcWorkerId(worker_id); + if (region->is_young()) { + _event.set_name(G1GCPhaseTimes::phase_name(G1GCPhaseTimes::YoungFreeCSet)); + } else { + _event.set_name(G1GCPhaseTimes::phase_name(G1GCPhaseTimes::NonYoungFreeCSet)); + } + } - struct WorkItem { - uint region_idx; - bool is_young; - bool evacuation_failed; + ~JFREventForRegion() { + _event.commit(); + } + }; + + // Helper to do timing for region work. + class TimerForRegion { + Tickspan& _time; + Ticks _start_time; + public: + TimerForRegion(Tickspan& time) : _time(time), _start_time(Ticks::now()) { } + ~TimerForRegion() { + _time += Ticks::now() - _start_time; + } + }; - WorkItem(HeapRegion* r) { - region_idx = r->hrm_index(); - is_young = r->is_young(); - evacuation_failed = r->evacuation_failed(); + // FreeCSetClosure members + G1CollectedHeap* _g1h; + const size_t* _surviving_young_words; + uint _worker_id; + Tickspan _young_time; + Tickspan _non_young_time; + FreeCSetStats* _stats; + + void assert_in_cset(HeapRegion* r) { + assert(r->young_index_in_cset() != 0 && + (uint)r->young_index_in_cset() <= _g1h->collection_set()->young_region_length(), + "Young index %u is wrong for region %u of type %s with %u young regions", + r->young_index_in_cset(), r->hrm_index(), r->get_type_str(), _g1h->collection_set()->young_region_length()); } - }; - volatile size_t _parallel_work_claim; - size_t _num_work_items; - WorkItem* _work_items; + void handle_evacuated_region(HeapRegion* r) { + assert(!r->is_empty(), "Region %u is an empty region in the collection set.", r->hrm_index()); + stats()->account_evacuated_region(r); - void do_serial_work() { - // Need to grab the lock to be allowed to modify the old region list. - MutexLocker x(OldSets_lock, Mutex::_no_safepoint_check_flag); - _collection_set->iterate(&_cl); - } - - void do_parallel_work_for_region(uint region_idx, bool is_young, bool evacuation_failed) { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); + // Free the region and and its remembered set. + _g1h->free_region(r, NULL, false /* skip_remset */, true /* skip_hot_card_cache */, true /* locked */); + } - HeapRegion* r = g1h->region_at(region_idx); - assert(!g1h->is_on_master_free_list(r), "sanity"); + void handle_failed_region(HeapRegion* r) { + // Do some allocation statistics accounting. Regions that failed evacuation + // are always made old, so there is no need to update anything in the young + // gen statistics, but we need to update old gen statistics. + stats()->account_failed_region(r); - Atomic::add(&_rs_length, r->rem_set()->occupied()); + // Update the region state due to the failed evacuation. + r->handle_evacuation_failure(); - if (!is_young) { - g1h->hot_card_cache()->reset_card_counts(r); + // Add region to old set, need to hold lock. + MutexLocker x(OldSets_lock, Mutex::_no_safepoint_check_flag); + _g1h->old_set_add(r); } - if (!evacuation_failed) { - r->rem_set()->clear_locked(); + Tickspan& timer_for_region(HeapRegion* r) { + return r->is_young() ? _young_time : _non_young_time; } - } - class G1PrepareFreeCollectionSetClosure : public HeapRegionClosure { - private: - size_t _cur_idx; - WorkItem* _work_items; + FreeCSetStats* stats() { + return _stats; + } public: - G1PrepareFreeCollectionSetClosure(WorkItem* work_items) : HeapRegionClosure(), _cur_idx(0), _work_items(work_items) { } + FreeCSetClosure(const size_t* surviving_young_words, + uint worker_id, + FreeCSetStats* stats) : + HeapRegionClosure(), + _g1h(G1CollectedHeap::heap()), + _surviving_young_words(surviving_young_words), + _worker_id(worker_id), + _young_time(), + _non_young_time(), + _stats(stats) { } virtual bool do_heap_region(HeapRegion* r) { - _work_items[_cur_idx++] = WorkItem(r); + assert(r->in_collection_set(), "Invariant: %u missing from CSet", r->hrm_index()); + JFREventForRegion event(r, _worker_id); + TimerForRegion timer(timer_for_region(r)); + + _g1h->clear_region_attr(r); + stats()->account_rs_length(r); + + if (r->is_young()) { + assert_in_cset(r); + r->record_surv_words_in_group(_surviving_young_words[r->young_index_in_cset()]); + } else { + _g1h->hot_card_cache()->reset_card_counts(r); + } + + if (r->evacuation_failed()) { + handle_failed_region(r); + } else { + handle_evacuated_region(r); + } + assert(!_g1h->is_on_master_free_list(r), "sanity"); + return false; } + + void report_timing(Tickspan parallel_time) { + G1GCPhaseTimes* pt = _g1h->phase_times(); + pt->record_time_secs(G1GCPhaseTimes::ParFreeCSet, _worker_id, parallel_time.seconds()); + if (_young_time.value() > 0) { + pt->record_time_secs(G1GCPhaseTimes::YoungFreeCSet, _worker_id, _young_time.seconds()); + } + if (_non_young_time.value() > 0) { + pt->record_time_secs(G1GCPhaseTimes::NonYoungFreeCSet, _worker_id, _non_young_time.seconds()); + } + } }; - void prepare_work() { - G1PrepareFreeCollectionSetClosure cl(_work_items); - _collection_set->iterate(&cl); - } + // G1FreeCollectionSetTask members + G1CollectedHeap* _g1h; + G1EvacuationInfo* _evacuation_info; + FreeCSetStats* _worker_stats; + HeapRegionClaimer _claimer; + const size_t* _surviving_young_words; + uint _active_workers; - void complete_work() { - _cl.complete_work(); + FreeCSetStats* worker_stats(uint worker) { + return &_worker_stats[worker]; + } - G1Policy* policy = G1CollectedHeap::heap()->policy(); - policy->record_rs_length(_rs_length); - policy->cset_regions_freed(); + void report_statistics() { + // Merge the accounting + FreeCSetStats total_stats; + for (uint worker = 0; worker < _active_workers; worker++) { + total_stats.merge_stats(worker_stats(worker)); + } + total_stats.report(_g1h, _evacuation_info); } + public: - G1FreeCollectionSetTask(G1CollectionSet* collection_set, G1EvacuationInfo* evacuation_info, const size_t* surviving_young_words) : - AbstractGangTask("G1 Free Collection Set"), - _collection_set(collection_set), - _cl(evacuation_info, surviving_young_words), - _surviving_young_words(surviving_young_words), - _rs_length(0), - _serial_work_claim(0), - _parallel_work_claim(0), - _num_work_items(collection_set->region_length()), - _work_items(NEW_C_HEAP_ARRAY(WorkItem, _num_work_items, mtGC)) { - prepare_work(); + G1FreeCollectionSetTask(G1EvacuationInfo* evacuation_info, const size_t* surviving_young_words, uint active_workers) : + AbstractGangTask("G1 Free Collection Set"), + _g1h(G1CollectedHeap::heap()), + _evacuation_info(evacuation_info), + _worker_stats(NEW_C_HEAP_ARRAY(FreeCSetStats, active_workers, mtGC)), + _claimer(active_workers), + _surviving_young_words(surviving_young_words), + _active_workers(active_workers) { + for (uint worker = 0; worker < active_workers; worker++) { + ::new (&_worker_stats[worker]) FreeCSetStats(); + } } ~G1FreeCollectionSetTask() { - complete_work(); - FREE_C_HEAP_ARRAY(WorkItem, _work_items); + Ticks serial_time = Ticks::now(); + report_statistics(); + for (uint worker = 0; worker < _active_workers; worker++) { + _worker_stats[worker].~FreeCSetStats(); + } + FREE_C_HEAP_ARRAY(FreeCSetStats, _worker_stats); + _g1h->phase_times()->record_serial_free_cset_time_ms((Ticks::now() - serial_time).seconds() * 1000.0); } - // Chunk size for work distribution. The chosen value has been determined experimentally - // to be a good tradeoff between overhead and achievable parallelism. - static uint chunk_size() { return 32; } - virtual void work(uint worker_id) { - G1GCPhaseTimes* timer = G1CollectedHeap::heap()->phase_times(); - - // Claim serial work. - if (_serial_work_claim == 0) { - jint value = Atomic::add(&_serial_work_claim, 1) - 1; - if (value == 0) { - double serial_time = os::elapsedTime(); - do_serial_work(); - timer->record_serial_free_cset_time_ms((os::elapsedTime() - serial_time) * 1000.0); - } - } - - // Start parallel work. - double young_time = 0.0; - bool has_young_time = false; - double non_young_time = 0.0; - bool has_non_young_time = false; - - while (true) { - size_t end = Atomic::add(&_parallel_work_claim, chunk_size()); - size_t cur = end - chunk_size(); - - if (cur >= _num_work_items) { - break; - } - - EventGCPhaseParallel event; - double start_time = os::elapsedTime(); - - end = MIN2(end, _num_work_items); - - for (; cur < end; cur++) { - bool is_young = _work_items[cur].is_young; - - do_parallel_work_for_region(_work_items[cur].region_idx, is_young, _work_items[cur].evacuation_failed); - - double end_time = os::elapsedTime(); - double time_taken = end_time - start_time; - if (is_young) { - young_time += time_taken; - has_young_time = true; - event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::YoungFreeCSet)); - } else { - non_young_time += time_taken; - has_non_young_time = true; - event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::NonYoungFreeCSet)); - } - start_time = end_time; - } - } + EventGCPhaseParallel event; + Ticks start = Ticks::now(); + FreeCSetClosure cl(_surviving_young_words, worker_id, worker_stats(worker_id)); + _g1h->collection_set_par_iterate_all(&cl, &_claimer, worker_id); - if (has_young_time) { - timer->record_time_secs(G1GCPhaseTimes::YoungFreeCSet, worker_id, young_time); - } - if (has_non_young_time) { - timer->record_time_secs(G1GCPhaseTimes::NonYoungFreeCSet, worker_id, non_young_time); - } + // Report the total parallel time along with some more detailed metrics. + cl.report_timing(Ticks::now() - start); + event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::ParFreeCSet)); } }; void G1CollectedHeap::free_collection_set(G1CollectionSet* collection_set, G1EvacuationInfo& evacuation_info, const size_t* surviving_young_words) { _eden.clear(); - double free_cset_start_time = os::elapsedTime(); + // The free collections set is split up in two tasks, the first + // frees the collection set and records what regions are free, + // and the second one rebuilds the free list. This proved to be + // more efficient than adding a sorted list to another. + Ticks free_cset_start_time = Ticks::now(); { - uint const num_regions = _collection_set.region_length(); - uint const num_chunks = MAX2(num_regions / G1FreeCollectionSetTask::chunk_size(), 1U); - uint const num_workers = MIN2(workers()->active_workers(), num_chunks); - - G1FreeCollectionSetTask cl(collection_set, &evacuation_info, surviving_young_words); + uint const num_cs_regions = _collection_set.region_length(); + uint const num_workers = clamp(num_cs_regions, 1u, workers()->active_workers()); + G1FreeCollectionSetTask cl(&evacuation_info, surviving_young_words, num_workers); - log_debug(gc, ergo)("Running %s using %u workers for collection set length %u", - cl.name(), num_workers, num_regions); + log_debug(gc, ergo)("Running %s using %u workers for collection set length %u (%u)", + cl.name(), num_workers, num_cs_regions, num_regions()); workers()->run_task(&cl, num_workers); } - phase_times()->record_total_free_cset_time_ms((os::elapsedTime() - free_cset_start_time) * 1000.0); + + Ticks free_cset_end_time = Ticks::now(); + phase_times()->record_total_free_cset_time_ms((free_cset_end_time - free_cset_start_time).seconds() * 1000.0); + + // Now rebuild the free region list. + hrm()->rebuild_free_list(workers()); + phase_times()->record_total_rebuild_freelist_time_ms((Ticks::now() - free_cset_end_time).seconds() * 1000.0); collection_set->clear(); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 06334e47cc0..25b72115624 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1201,6 +1201,11 @@ class G1CollectedHeap : public CollectedHeap { void heap_region_par_iterate_from_start(HeapRegionClosure* cl, HeapRegionClaimer* hrclaimer) const; + // Iterate over all regions in the collection set in parallel. + void collection_set_par_iterate_all(HeapRegionClosure* cl, + HeapRegionClaimer* hr_claimer, + uint worker_id); + // Iterate over all regions currently in the current collection set. void collection_set_iterate_all(HeapRegionClosure* blk); diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index 4ff2b1372a9..1bd8ea8a219 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -201,6 +201,13 @@ void G1CollectionSet::iterate(HeapRegionClosure* cl) const { } } +void G1CollectionSet::par_iterate(HeapRegionClosure* cl, + HeapRegionClaimer* hr_claimer, + uint worker_id, + uint total_workers) const { + iterate_part_from(cl, hr_claimer, 0, cur_length(), worker_id, total_workers); +} + void G1CollectionSet::iterate_optional(HeapRegionClosure* cl) const { assert_at_safepoint(); @@ -215,18 +222,25 @@ void G1CollectionSet::iterate_incremental_part_from(HeapRegionClosure* cl, HeapRegionClaimer* hr_claimer, uint worker_id, uint total_workers) const { - assert_at_safepoint(); + iterate_part_from(cl, hr_claimer, _inc_part_start, increment_length(), worker_id, total_workers); +} - size_t len = increment_length(); - if (len == 0) { +void G1CollectionSet::iterate_part_from(HeapRegionClosure* cl, + HeapRegionClaimer* hr_claimer, + size_t offset, + size_t length, + uint worker_id, + uint total_workers) const { + assert_at_safepoint(); + if (length == 0) { return; } - size_t start_pos = (worker_id * len) / total_workers; + size_t start_pos = (worker_id * length) / total_workers; size_t cur_pos = start_pos; do { - uint region_idx = _collection_set_regions[cur_pos + _inc_part_start]; + uint region_idx = _collection_set_regions[cur_pos + offset]; if (hr_claimer == NULL || hr_claimer->claim_region(region_idx)) { HeapRegion* r = _g1h->region_at(region_idx); bool result = cl->do_heap_region(r); @@ -234,7 +248,7 @@ void G1CollectionSet::iterate_incremental_part_from(HeapRegionClosure* cl, } cur_pos++; - if (cur_pos == len) { + if (cur_pos == length) { cur_pos = 0; } } while (cur_pos != start_pos); diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.hpp b/src/hotspot/share/gc/g1/g1CollectionSet.hpp index c52aa16b66e..efa969d3e69 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.hpp @@ -254,6 +254,16 @@ class G1CollectionSet { // Select the old regions of the initial collection set and determine how many optional // regions we might be able to evacuate in this pause. void finalize_old_part(double time_remaining_ms); + + // Iterate the part of the collection set given by the offset and length applying the given + // HeapRegionClosure. The worker_id will determine where in the part to start the iteration + // to allow for more efficient parallel iteration. + void iterate_part_from(HeapRegionClosure* cl, + HeapRegionClaimer* hr_claimer, + size_t offset, + size_t length, + uint worker_id, + uint total_workers) const; public: G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy); ~G1CollectionSet(); @@ -306,6 +316,10 @@ class G1CollectionSet { // Iterate over the entire collection set (all increments calculated so far), applying // the given HeapRegionClosure on all of them. void iterate(HeapRegionClosure* cl) const; + void par_iterate(HeapRegionClosure* cl, + HeapRegionClaimer* hr_claimer, + uint worker_id, + uint total_workers) const; void iterate_optional(HeapRegionClosure* cl) const; diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 3b6f8c738c6..81e18e656e2 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -131,8 +131,10 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : _gc_par_phases[RedirtyCards] = new WorkerDataArray("Parallel Redirty (ms):", max_gc_threads); _gc_par_phases[RedirtyCards]->create_thread_work_items("Redirtied Cards:"); + _gc_par_phases[ParFreeCSet] = new WorkerDataArray("Parallel Free Collection Set (ms):", max_gc_threads); _gc_par_phases[YoungFreeCSet] = new WorkerDataArray("Young Free Collection Set (ms):", max_gc_threads); _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray("Non-Young Free Collection Set (ms):", max_gc_threads); + _gc_par_phases[RebuildFreeList] = new WorkerDataArray("Parallel Rebuild Free List (ms):", max_gc_threads); reset(); } @@ -167,6 +169,8 @@ void G1GCPhaseTimes::reset() { _recorded_start_new_cset_time_ms = 0.0; _recorded_total_free_cset_time_ms = 0.0; _recorded_serial_free_cset_time_ms = 0.0; + _recorded_total_rebuild_freelist_time_ms = 0.0; + _recorded_serial_rebuild_freelist_time_ms = 0.0; _cur_fast_reclaim_humongous_time_ms = 0.0; _cur_region_register_time = 0.0; _cur_fast_reclaim_humongous_total = 0; @@ -328,11 +332,11 @@ void G1GCPhaseTimes::debug_phase(WorkerDataArray* phase, uint extra_inde } } -void G1GCPhaseTimes::trace_phase(WorkerDataArray* phase, bool print_sum) const { +void G1GCPhaseTimes::trace_phase(WorkerDataArray* phase, bool print_sum, uint extra_indent) const { LogTarget(Trace, gc, phases) lt; if (lt.is_enabled()) { LogStream ls(lt); - log_phase(phase, 3, &ls, print_sum); + log_phase(phase, 3 + extra_indent, &ls, print_sum); } } @@ -456,6 +460,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { _cur_strong_code_root_purge_time_ms + _recorded_redirty_logged_cards_time_ms + _recorded_total_free_cset_time_ms + + _recorded_total_rebuild_freelist_time_ms + _cur_fast_reclaim_humongous_time_ms + _cur_expand_heap_time_ms + _cur_string_deduplication_time_ms; @@ -492,9 +497,14 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { #endif debug_time("Free Collection Set", _recorded_total_free_cset_time_ms); - trace_time("Free Collection Set Serial", _recorded_serial_free_cset_time_ms); - trace_phase(_gc_par_phases[YoungFreeCSet]); - trace_phase(_gc_par_phases[NonYoungFreeCSet]); + trace_time("Serial Free Collection Set", _recorded_serial_free_cset_time_ms); + trace_phase(_gc_par_phases[ParFreeCSet]); + trace_phase(_gc_par_phases[YoungFreeCSet], true, 1); + trace_phase(_gc_par_phases[NonYoungFreeCSet], true, 1); + + debug_time("Rebuild Free List", _recorded_total_rebuild_freelist_time_ms); + trace_time("Serial Rebuild Free List ", _recorded_serial_rebuild_freelist_time_ms); + trace_phase(_gc_par_phases[RebuildFreeList]); if (G1EagerReclaimHumongousObjects) { debug_time("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); @@ -566,8 +576,10 @@ const char* G1GCPhaseTimes::phase_name(GCParPhases phase) { "StringDedupQueueFixup", "StringDedupTableFixup", "RedirtyCards", + "ParFreeCSet", "YoungFreeCSet", "NonYoungFreeCSet", + "RebuildFreeList", "MergePSS" //GCParPhasesSentinel only used to tell end of enum }; diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index 0cd425ec34a..1b5da81f18e 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -76,8 +76,10 @@ class G1GCPhaseTimes : public CHeapObj { StringDedupQueueFixup, StringDedupTableFixup, RedirtyCards, + ParFreeCSet, YoungFreeCSet, NonYoungFreeCSet, + RebuildFreeList, MergePSS, GCParPhasesSentinel }; @@ -171,6 +173,10 @@ class G1GCPhaseTimes : public CHeapObj { double _recorded_serial_free_cset_time_ms; + double _recorded_total_rebuild_freelist_time_ms; + + double _recorded_serial_rebuild_freelist_time_ms; + double _cur_region_register_time; double _cur_fast_reclaim_humongous_time_ms; @@ -195,7 +201,7 @@ class G1GCPhaseTimes : public CHeapObj { void log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum) const; void debug_serial_phase(WorkerDataArray* phase, uint extra_indent = 0) const; void debug_phase(WorkerDataArray* phase, uint extra_indent = 0) const; - void trace_phase(WorkerDataArray* phase, bool print_sum = true) const; + void trace_phase(WorkerDataArray* phase, bool print_sum = true, uint extra_indent = 0) const; void info_time(const char* name, double value) const; void debug_time(const char* name, double value) const; @@ -318,6 +324,14 @@ class G1GCPhaseTimes : public CHeapObj { _recorded_serial_free_cset_time_ms = time_ms; } + void record_total_rebuild_freelist_time_ms(double time_ms) { + _recorded_total_rebuild_freelist_time_ms = time_ms; + } + + void record_serial_rebuild_freelist_time_ms(double time_ms) { + _recorded_serial_rebuild_freelist_time_ms = time_ms; + } + void record_register_regions(double time_ms, size_t total, size_t candidates) { _cur_region_register_time = time_ms; _cur_fast_reclaim_humongous_total = total; @@ -401,6 +415,10 @@ class G1GCPhaseTimes : public CHeapObj { return _recorded_total_free_cset_time_ms; } + double total_rebuild_freelist_time_ms() { + return _recorded_total_rebuild_freelist_time_ms; + } + double non_young_cset_choice_time_ms() { return _recorded_non_young_cset_choice_time_ms; } diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 38a04982490..1565dcd04d4 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -587,7 +587,7 @@ double G1Policy::other_time_ms(double pause_time_ms) const { } double G1Policy::constant_other_time_ms(double pause_time_ms) const { - return other_time_ms(pause_time_ms) - phase_times()->total_free_cset_time_ms(); + return other_time_ms(pause_time_ms) - phase_times()->total_free_cset_time_ms() - phase_times()->total_rebuild_freelist_time_ms(); } bool G1Policy::about_to_start_mixed_phase() const { diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index 4cda9fb903e..71d387aaf15 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -110,6 +110,19 @@ void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_hea } } +void HeapRegion::handle_evacuation_failure() { + uninstall_surv_rate_group(); + clear_young_index_in_cset(); + set_evacuation_failed(false); + set_old(); +} + +void HeapRegion::unlink_from_list() { + set_next(NULL); + set_prev(NULL); + set_containing_set(NULL); +} + void HeapRegion::hr_clear(bool keep_remset, bool clear_space, bool locked) { assert(_humongous_start_region == NULL, "we should have already filtered out humongous regions"); diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index a25299ddcd9..32c5213e107 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -464,14 +464,16 @@ class HeapRegion : public CHeapObj { void set_prev(HeapRegion* prev) { _prev = prev; } HeapRegion* prev() { return _prev; } + void unlink_from_list(); + // Every region added to a set is tagged with a reference to that // set. This is used for doing consistency checking to make sure that // the contents of a set are as they should be and it's only // available in non-product builds. #ifdef ASSERT void set_containing_set(HeapRegionSetBase* containing_set) { - assert((containing_set == NULL && _containing_set != NULL) || - (containing_set != NULL && _containing_set == NULL), + assert((containing_set != NULL && _containing_set == NULL) || + containing_set == NULL, "containing_set: " PTR_FORMAT " " "_containing_set: " PTR_FORMAT, p2i(containing_set), p2i(_containing_set)); @@ -559,6 +561,9 @@ class HeapRegion : public CHeapObj { return (HeapWord *) obj >= next_top_at_mark_start(); } + // Update the region state after a failed evacuation. + void handle_evacuation_failure(); + // Iterate over the objects overlapping the given memory region, applying cl // to all references in the region. This is a helper for // G1RemSet::refine_card*, and is tightly coupled with them. diff --git a/src/hotspot/share/gc/g1/heapRegionManager.cpp b/src/hotspot/share/gc/g1/heapRegionManager.cpp index 24ff61fe22a..a21a5fca0d6 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp @@ -614,3 +614,80 @@ bool HeapRegionClaimer::claim_region(uint region_index) { uint old_val = Atomic::cmpxchg(&_claims[region_index], Unclaimed, Claimed); return old_val == Unclaimed; } + +class G1RebuildFreeListTask : public AbstractGangTask { + HeapRegionManager* _hrm; + FreeRegionList* _worker_freelists; + uint _worker_chunk_size; + uint _num_workers; + +public: + G1RebuildFreeListTask(HeapRegionManager* hrm, uint num_workers) : + AbstractGangTask("G1 Rebuild Free List Task"), + _hrm(hrm), + _worker_freelists(NEW_C_HEAP_ARRAY(FreeRegionList, num_workers, mtGC)), + _worker_chunk_size((_hrm->max_length() + num_workers - 1) / num_workers), + _num_workers(num_workers) { + for (uint worker = 0; worker < _num_workers; worker++) { + ::new (&_worker_freelists[worker]) FreeRegionList("Appendable Worker Free List"); + } + } + + ~G1RebuildFreeListTask() { + for (uint worker = 0; worker < _num_workers; worker++) { + _worker_freelists[worker].~FreeRegionList(); + } + FREE_C_HEAP_ARRAY(FreeRegionList, _worker_freelists); + } + + FreeRegionList* worker_freelist(uint worker) { + return &_worker_freelists[worker]; + } + + // Each worker creates a free list for a chunk of the heap. The chunks won't + // be overlapping so we don't need to do any claiming. + void work(uint worker_id) { + Ticks start_time = Ticks::now(); + EventGCPhaseParallel event; + + uint start = worker_id * _worker_chunk_size; + uint end = MIN2(start + _worker_chunk_size, _hrm->max_length()); + + // If start is outside the heap, this worker has nothing to do. + if (start > end) { + return; + } + + FreeRegionList *free_list = worker_freelist(worker_id); + for (uint i = start; i < end; i++) { + HeapRegion *region = _hrm->at_or_null(i); + if (region != NULL && region->is_free()) { + // Need to clear old links to allow to be added to new freelist. + region->unlink_from_list(); + free_list->add_to_tail(region); + } + } + + event.commit(GCId::current(), worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::RebuildFreeList)); + G1CollectedHeap::heap()->phase_times()->record_time_secs(G1GCPhaseTimes::RebuildFreeList, worker_id, (Ticks::now() - start_time).seconds()); + } +}; + +void HeapRegionManager::rebuild_free_list(WorkGang* workers) { + // Abandon current free list to allow a rebuild. + _free_list.abandon(); + + uint const num_workers = clamp(max_length(), 1u, workers->active_workers()); + G1RebuildFreeListTask task(this, num_workers); + + log_debug(gc, ergo)("Running %s using %u workers for rebuilding free list of %u (%u) regions", + task.name(), num_workers, num_free_regions(), max_length()); + workers->run_task(&task, num_workers); + + // Link the partial free lists together. + Ticks serial_time = Ticks::now(); + for (uint worker = 0; worker < num_workers; worker++) { + _free_list.append_ordered(task.worker_freelist(worker)); + } + G1CollectedHeap::heap()->phase_times()->record_serial_rebuild_freelist_time_ms((Ticks::now() - serial_time).seconds() * 1000.0); +} diff --git a/src/hotspot/share/gc/g1/heapRegionManager.hpp b/src/hotspot/share/gc/g1/heapRegionManager.hpp index 3bb40e80b74..3e7ab58d52e 100644 --- a/src/hotspot/share/gc/g1/heapRegionManager.hpp +++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp @@ -172,6 +172,9 @@ class HeapRegionManager: public CHeapObj { // Insert the given region into the free region list. inline void insert_into_free_list(HeapRegion* hr); + // Rebuild the free region list from scratch. + void rebuild_free_list(WorkGang* workers); + // Insert the given region list into the global free region list. void insert_list_into_free_list(FreeRegionList* list) { _free_list.add_ordered(list); diff --git a/src/hotspot/share/gc/g1/heapRegionSet.cpp b/src/hotspot/share/gc/g1/heapRegionSet.cpp index 128d165ca17..f6b546951d8 100644 --- a/src/hotspot/share/gc/g1/heapRegionSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionSet.cpp @@ -90,6 +90,12 @@ void FreeRegionList::set_unrealistically_long_length(uint len) { _unrealistically_long_length = len; } +void FreeRegionList::abandon() { + check_mt_safety(); + clear(); + verify_optional(); +} + void FreeRegionList::remove_all() { check_mt_safety(); verify_optional(); @@ -112,10 +118,9 @@ void FreeRegionList::remove_all() { verify_optional(); } -void FreeRegionList::add_ordered(FreeRegionList* from_list) { +void FreeRegionList::add_list_common_start(FreeRegionList* from_list) { check_mt_safety(); from_list->check_mt_safety(); - verify_optional(); from_list->verify_optional(); @@ -138,6 +143,47 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { hr->set_containing_set(this); } #endif // ASSERT +} + +void FreeRegionList::add_list_common_end(FreeRegionList* from_list) { + _length += from_list->length(); + from_list->clear(); + + verify_optional(); + from_list->verify_optional(); +} + +void FreeRegionList::append_ordered(FreeRegionList* from_list) { + add_list_common_start(from_list); + + if (from_list->is_empty()) { + return; + } + + if (is_empty()) { + // Make from_list the current list. + assert_free_region_list(length() == 0 && _tail == NULL, "invariant"); + _head = from_list->_head; + _tail = from_list->_tail; + } else { + // Add the from_list to the end of the current list. + assert(_tail->hrm_index() < from_list->_head->hrm_index(), "Should be sorted %u < %u", + _tail->hrm_index(), from_list->_head->hrm_index()); + + _tail->set_next(from_list->_head); + from_list->_head->set_prev(_tail); + _tail = from_list->_tail; + } + + add_list_common_end(from_list); +} + +void FreeRegionList::add_ordered(FreeRegionList* from_list) { + add_list_common_start(from_list); + + if (from_list->is_empty()) { + return; + } if (is_empty()) { assert_free_region_list(length() == 0 && _tail == NULL, "invariant"); @@ -178,11 +224,7 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { } } - _length += from_list->length(); - from_list->clear(); - - verify_optional(); - from_list->verify_optional(); + add_list_common_end(from_list); } void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) { diff --git a/src/hotspot/share/gc/g1/heapRegionSet.hpp b/src/hotspot/share/gc/g1/heapRegionSet.hpp index 9ed947f060c..eeed90c73f3 100644 --- a/src/hotspot/share/gc/g1/heapRegionSet.hpp +++ b/src/hotspot/share/gc/g1/heapRegionSet.hpp @@ -180,6 +180,10 @@ class FreeRegionList : public HeapRegionSetBase { inline void increase_length(uint node_index); inline void decrease_length(uint node_index); + // Common checks for adding a list. + void add_list_common_start(FreeRegionList* from_list); + void add_list_common_end(FreeRegionList* from_list); + protected: // See the comment for HeapRegionSetBase::clear() virtual void clear(); @@ -202,6 +206,8 @@ class FreeRegionList : public HeapRegionSetBase { // Assumes that the list is ordered and will preserve that order. The order // is determined by hrm_index. inline void add_ordered(HeapRegion* hr); + // Same restrictions as above, but adds the region last in the list. + inline void add_to_tail(HeapRegion* region_to_add); // Removes from head or tail based on the given argument. HeapRegion* remove_region(bool from_head); @@ -212,10 +218,15 @@ class FreeRegionList : public HeapRegionSetBase { // Merge two ordered lists. The result is also ordered. The order is // determined by hrm_index. void add_ordered(FreeRegionList* from_list); + void append_ordered(FreeRegionList* from_list); // It empties the list by removing all regions from it. void remove_all(); + // Abandon current free list. Requires that all regions in the current list + // are taken care of separately, to allow a rebuild. + void abandon(); + // Remove all (contiguous) regions from first to first + num_regions -1 from // this list. // Num_regions must be > 1. diff --git a/src/hotspot/share/gc/g1/heapRegionSet.inline.hpp b/src/hotspot/share/gc/g1/heapRegionSet.inline.hpp index ccf3c288b71..6e34c6a60cb 100644 --- a/src/hotspot/share/gc/g1/heapRegionSet.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegionSet.inline.hpp @@ -50,6 +50,26 @@ inline void HeapRegionSetBase::remove(HeapRegion* hr) { _length--; } +inline void FreeRegionList::add_to_tail(HeapRegion* region_to_add) { + assert_free_region_list((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) || + (length() > 0 && _head != NULL && _tail != NULL && _tail->hrm_index() < region_to_add->hrm_index()), + "invariant"); + // add() will verify the region and check mt safety. + add(region_to_add); + + if (_head != NULL) { + // Link into list, next is already NULL, no need to set. + region_to_add->set_prev(_tail); + _tail->set_next(region_to_add); + _tail = region_to_add; + } else { + // Empty list, this region is now the list. + _head = region_to_add; + _tail = region_to_add; + } + increase_length(region_to_add->node_index()); +} + inline void FreeRegionList::add_ordered(HeapRegion* hr) { assert_free_region_list((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) || (length() > 0 && _head != NULL && _tail != NULL), diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index e9cc6966089..5e0b70a200f 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -145,9 +145,15 @@ public boolean isAvailable() { new LogMessageWithLevel("Prepare Heap Roots", Level.DEBUG), // Free CSet new LogMessageWithLevel("Free Collection Set", Level.DEBUG), - new LogMessageWithLevel("Free Collection Set Serial", Level.TRACE), + new LogMessageWithLevel("Serial Free Collection Set", Level.TRACE), + new LogMessageWithLevel("Parallel Free Collection Set", Level.TRACE), new LogMessageWithLevel("Young Free Collection Set", Level.TRACE), new LogMessageWithLevel("Non-Young Free Collection Set", Level.TRACE), + // Rebuild Free List + new LogMessageWithLevel("Rebuild Free List", Level.DEBUG), + new LogMessageWithLevel("Serial Rebuild Free List", Level.TRACE), + new LogMessageWithLevel("Parallel Rebuild Free List", Level.TRACE), + // Humongous Eager Reclaim new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), // Merge PSS diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java index 76b1072d210..3c4580ce419 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java @@ -110,8 +110,10 @@ public static void main(String[] args) throws IOException { "StringDedupQueueFixup", "StringDedupTableFixup", "RedirtyCards", + "ParFreeCSet", "NonYoungFreeCSet", - "YoungFreeCSet" + "YoungFreeCSet", + "RebuildFreeList" ); // Some GC phases may or may not occur depending on environment. Filter them out From 3ea25ecdfe7bb58be0e3250e56e97d59fc1f2d05 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Mon, 9 Dec 2019 12:06:26 +0000 Subject: [PATCH 12/32] 8233319: Deprecate MulticastSocket methods that operate on java.net.InetAddress Deprecate any method that operates on InetAddress as well as getLoopbackMode and setLoopbackMode Reviewed-by: chegar, dfuchs, alanb --- .../classes/java/net/MulticastSocket.java | 196 ++++++++++-------- .../java/net/StandardSocketOptions.java | 4 +- 2 files changed, 107 insertions(+), 93 deletions(-) diff --git a/src/java.base/share/classes/java/net/MulticastSocket.java b/src/java.base/share/classes/java/net/MulticastSocket.java index bf0c371e488..a7cac8f31f1 100644 --- a/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/src/java.base/share/classes/java/net/MulticastSocket.java @@ -29,17 +29,16 @@ import java.util.Collections; import java.util.Enumeration; import java.util.Set; -import java.net.PortUnreachableException; /** * The multicast datagram socket class is useful for sending - * and receiving IP multicast packets. A MulticastSocket is + * and receiving IP multicast packets. A MulticastSocket is * a (UDP) DatagramSocket, with additional capabilities for * joining "groups" of other multicast hosts on the internet. *

* A multicast group is specified by a class D IP address * and by a standard UDP port number. Class D IP addresses - * are in the range 224.0.0.0 to 239.255.255.255, + * are in the range {@code 224.0.0.0} to {@code 239.255.255.255}, * inclusive. The address 224.0.0.0 is reserved and should not be used. *

* One would join a multicast group by first creating a MulticastSocket @@ -50,9 +49,12 @@ * // join a Multicast group and send the group salutations * ... * String msg = "Hello"; - * InetAddress group = InetAddress.getByName("228.5.6.7"); + * InetAddress mcastaddr = InetAddress.getByName("228.5.6.7"); + * InetSocketAddress group = new InetSocketAddress(mcastaddr, port); + * NetworkInterface netIf = NetworkInterface.getByName("bge0"); * MulticastSocket s = new MulticastSocket(6789); - * s.joinGroup(group); + * + * s.joinGroup(group, netIf); * byte[] msgBytes = msg.getBytes(StandardCharsets.UTF_8); * DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, * group, 6789); @@ -63,25 +65,24 @@ * s.receive(recv); * ... * // OK, I'm done talking - leave the group... - * s.leaveGroup(group); + * s.leaveGroup(group, netIf); * * * When one sends a message to a multicast group, all subscribing * recipients to that host and port receive the message (within the - * time-to-live range of the packet, see below). The socket needn't + * time-to-live range of the packet, see below). The socket needn't * be a member of the multicast group to send messages to it. *

* When a socket subscribes to a multicast group/port, it receives * datagrams sent by other hosts to the group/port, as do all other * members of the group and port. A socket relinquishes membership - * in a group by the leaveGroup(InetAddress addr) method. - * Multiple MulticastSocket's may subscribe to a multicast group + * in a group by the leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) + * method. + * Multiple MulticastSockets may subscribe to a multicast group * and port concurrently, and they will all receive group datagrams. - *

- * Currently applets are not allowed to use multicast sockets. * * @author Pavani Diwanji - * @since 1.1 + * @since 1.1 */ public class MulticastSocket extends DatagramSocket { @@ -287,20 +288,21 @@ public int getTimeToLive() throws IOException { * {@code setInterface} or {@code setNetworkInterface}. * *

If there is a security manager, this method first - * calls its {@code checkMulticast} method - * with the {@code mcastaddr} argument - * as its argument. - * - * @param mcastaddr is the multicast address to join - * - * @throws IOException if there is an error joining, or when the address - * is not a multicast address, or the platform does not support - * multicasting - * @throws SecurityException if a security manager exists and its - * {@code checkMulticast} method doesn't allow the join. - * - * @see SecurityManager#checkMulticast(InetAddress) + * calls its {@code checkMulticast} method with the + * {@code mcastaddr} argument as its argument. + * + * @param mcastaddr is the multicast address to join + * @throws IOException if there is an error joining, + * or when the address is not a multicast address, + * or the platform does not support multicasting + * @throws SecurityException if a security manager exists and its + * {@code checkMulticast} method doesn't allow the join. + * @deprecated This method does not accept the network interface on + * which to join the multicast group. Use + * {@link #joinGroup(SocketAddress, NetworkInterface)} instead. + * @see SecurityManager#checkMulticast(InetAddress) */ + @Deprecated(since="14") public void joinGroup(InetAddress mcastaddr) throws IOException { if (isClosed()) { throw new SocketException("Socket is closed"); @@ -334,18 +336,20 @@ public void joinGroup(InetAddress mcastaddr) throws IOException { * {@code setInterface} or {@code setNetworkInterface}. * *

If there is a security manager, this method first - * calls its {@code checkMulticast} method - * with the {@code mcastaddr} argument - * as its argument. - * - * @param mcastaddr is the multicast address to leave - * @throws IOException if there is an error leaving - * or when the address is not a multicast address. - * @throws SecurityException if a security manager exists and its - * {@code checkMulticast} method doesn't allow the operation. - * - * @see SecurityManager#checkMulticast(InetAddress) + * calls its {@code checkMulticast} method with the + * {@code mcastaddr} argument as its argument. + * + * @param mcastaddr is the multicast address to leave + * @throws IOException if there is an error leaving + * or when the address is not a multicast address. + * @throws SecurityException if a security manager exists and its + * {@code checkMulticast} method doesn't allow the operation. + * @deprecated This method does not accept the network interface on which + * to leave the multicast group. Use + * {@link #leaveGroup(SocketAddress, NetworkInterface)} instead. + * @see SecurityManager#checkMulticast(InetAddress) */ + @Deprecated(since="14") public void leaveGroup(InetAddress mcastaddr) throws IOException { if (isClosed()) { throw new SocketException("Socket is closed"); @@ -372,22 +376,20 @@ public void leaveGroup(InetAddress mcastaddr) throws IOException { * with the {@code mcastaddr} argument * as its argument. * - * @param mcastaddr is the multicast address to join - * @param netIf specifies the local interface to receive multicast - * datagram packets, or null to defer to the interface set by - * {@link MulticastSocket#setInterface(InetAddress)} or - * {@link MulticastSocket#setNetworkInterface(NetworkInterface)} - * - * @throws IOException if there is an error joining, or when the address - * is not a multicast address, or the platform does not support - * multicasting - * @throws SecurityException if a security manager exists and its - * {@code checkMulticast} method doesn't allow the join. - * @throws IllegalArgumentException if mcastaddr is null or is a - * SocketAddress subclass not supported by this socket - * - * @see SecurityManager#checkMulticast(InetAddress) - * @since 1.4 + * @param mcastaddr is the multicast address to join + * @param netIf specifies the local interface to receive multicast + * datagram packets, or null to defer to the interface set by + * {@link MulticastSocket#setInterface(InetAddress)} or + * {@link MulticastSocket#setNetworkInterface(NetworkInterface)} + * @throws IOException if there is an error joining, or when the address + * is not a multicast address, or the platform does not support + * multicasting + * @throws SecurityException if a security manager exists and its + * {@code checkMulticast} method doesn't allow the join. + * @throws IllegalArgumentException if mcastaddr is null or is a + * SocketAddress subclass not supported by this socket + * @see SecurityManager#checkMulticast(InetAddress) + * @since 1.4 */ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException { @@ -417,24 +419,22 @@ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) * Leave a multicast group on a specified local interface. * *

If there is a security manager, this method first - * calls its {@code checkMulticast} method - * with the {@code mcastaddr} argument - * as its argument. - * - * @param mcastaddr is the multicast address to leave - * @param netIf specifies the local interface or null to defer - * to the interface set by - * {@link MulticastSocket#setInterface(InetAddress)} or - * {@link MulticastSocket#setNetworkInterface(NetworkInterface)} - * @throws IOException if there is an error leaving - * or when the address is not a multicast address. - * @throws SecurityException if a security manager exists and its - * {@code checkMulticast} method doesn't allow the operation. - * @throws IllegalArgumentException if mcastaddr is null or is a - * SocketAddress subclass not supported by this socket - * - * @see SecurityManager#checkMulticast(InetAddress) - * @since 1.4 + * calls its {@code checkMulticast} method with the + * {@code mcastaddr} argument as its argument. + * + * @param mcastaddr is the multicast address to leave + * @param netIf specifies the local interface or null to defer + * to the interface set by + * {@link MulticastSocket#setInterface(InetAddress)} or + * {@link MulticastSocket#setNetworkInterface(NetworkInterface)} + * @throws IOException if there is an error leaving or when the address + * is not a multicast address. + * @throws SecurityException if a security manager exists and its + * {@code checkMulticast} method doesn't allow the operation. + * @throws IllegalArgumentException if mcastaddr is null or is a + * SocketAddress subclass not supported by this socket. + * @see SecurityManager#checkMulticast(InetAddress) + * @since 1.4 */ public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException { @@ -464,11 +464,16 @@ public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) * Set the multicast network interface used by methods * whose behavior would be affected by the value of the * network interface. Useful for multihomed hosts. - * @param inf the InetAddress - * @throws SocketException if there is an error in - * the underlying protocol, such as a TCP error. - * @see #getInterface() + * + * @param inf the InetAddress + * @throws SocketException if there is an error in + * the underlying protocol, such as a TCP error. + * @deprecated The InetAddress may not uniquely identify + * the network interface. Use + * {@link #setNetworkInterface(NetworkInterface)} instead. + * @see #getInterface() */ + @Deprecated(since="14") public void setInterface(InetAddress inf) throws SocketException { if (isClosed()) { throw new SocketException("Socket is closed"); @@ -485,15 +490,16 @@ public void setInterface(InetAddress inf) throws SocketException { * Retrieve the address of the network interface used for * multicast packets. * - * @return An {@code InetAddress} representing - * the address of the network interface used for - * multicast packets. - * - * @throws SocketException if there is an error in - * the underlying protocol, such as a TCP error. - * - * @see #setInterface(java.net.InetAddress) + * @return An {@code InetAddress} representing the address + * of the network interface used for multicast packets. + * @throws SocketException if there is an error in the + * underlying protocol, such as a TCP error. + * @deprecated The network interface may not be uniquely identified by + * the InetAddress returned. + * Use {@link #getNetworkInterface()} instead. + * @see #setInterface(java.net.InetAddress) */ + @Deprecated(since="14") public InetAddress getInterface() throws SocketException { if (isClosed()) { throw new SocketException("Socket is closed"); @@ -594,11 +600,17 @@ public NetworkInterface getNetworkInterface() throws SocketException { *

Because this option is a hint, applications that want to * verify what loopback mode is set to should call * {@link #getLoopbackMode()} - * @param disable {@code true} to disable the LoopbackMode - * @throws SocketException if an error occurs while setting the value - * @since 1.4 - * @see #getLoopbackMode + * @param disable {@code true} to disable the LoopbackMode + * @throws SocketException if an error occurs while setting the value + * @since 1.4 + * @deprecated Use {@link #setOption(SocketOption, Object)} with + * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} + * instead. The loopback mode is enabled by default, + * {@code MulticastSocket.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false)} + * disables it. + * @see #getLoopbackMode */ + @Deprecated(since="14") public void setLoopbackMode(boolean disable) throws SocketException { getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable)); } @@ -606,11 +618,15 @@ public void setLoopbackMode(boolean disable) throws SocketException { /** * Get the setting for local loopback of multicast datagrams. * - * @throws SocketException if an error occurs while getting the value - * @return true if the LoopbackMode has been disabled - * @since 1.4 - * @see #setLoopbackMode + * @throws SocketException if an error occurs while getting the value + * @return true if the LoopbackMode has been disabled + * @since 1.4 + * @deprecated Use {@link #getOption(SocketOption)} with + * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} + * instead. + * @see #setLoopbackMode */ + @Deprecated(since="14") public boolean getLoopbackMode() throws SocketException { return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue(); } diff --git a/src/java.base/share/classes/java/net/StandardSocketOptions.java b/src/java.base/share/classes/java/net/StandardSocketOptions.java index ae47845fae3..bf5a9df5797 100644 --- a/src/java.base/share/classes/java/net/StandardSocketOptions.java +++ b/src/java.base/share/classes/java/net/StandardSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -291,7 +291,6 @@ private StandardSocketOptions() { } * is system dependent. * * @see java.nio.channels.MulticastChannel - * @see MulticastSocket#setInterface */ public static final SocketOption IP_MULTICAST_IF = new StdSocketOption("IP_MULTICAST_IF", NetworkInterface.class); @@ -343,7 +342,6 @@ private StandardSocketOptions() { } * binding the socket is system dependent. * * @see java.nio.channels.MulticastChannel - * @see MulticastSocket#setLoopbackMode */ public static final SocketOption IP_MULTICAST_LOOP = new StdSocketOption("IP_MULTICAST_LOOP", Boolean.class); From 07fc539a85ac6f31452690684e7fdbdbca37800c Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Mon, 9 Dec 2019 12:46:12 +0000 Subject: [PATCH 13/32] 8232513: java/net/DatagramSocket/PortUnreachable.java still fails intermittently with BindException Increase the number of bind retries and test repeats, best effort only Reviewed-by: msheppar, dfuchs, vtewari --- .../net/DatagramSocket/PortUnreachable.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/test/jdk/java/net/DatagramSocket/PortUnreachable.java b/test/jdk/java/net/DatagramSocket/PortUnreachable.java index 5fc64909a82..b60112b22fb 100644 --- a/test/jdk/java/net/DatagramSocket/PortUnreachable.java +++ b/test/jdk/java/net/DatagramSocket/PortUnreachable.java @@ -25,10 +25,12 @@ * @test * @bug 4361783 * @key intermittent - * @summary Test to see if ICMP Port Unreachable on non-connected - * DatagramSocket causes a SocketException "socket closed" - * exception on Windows 2000. + * @summary Test to see if ICMP Port Unreachable on non-connected + * DatagramSocket causes a SocketException "socket closed" + * exception on Windows 2000. + * @run main/othervm PortUnreachable */ + import java.net.BindException; import java.net.DatagramPacket; import java.net.DatagramSocket; @@ -56,6 +58,7 @@ public void serverSend() { b = "Greetings from the server".getBytes(); packet = new DatagramPacket(b, b.length, addr, clientPort); sock.send(packet); + Thread.sleep(500); // give time to the kernel to send packet sock.close(); } catch (Exception e) { e.printStackTrace(); @@ -70,15 +73,15 @@ DatagramSocket recreateServerSocket (int serverPort) throws Exception { serverPort); // it's possible that this method intermittently fails, if some other // process running on the machine grabs the port we want before us, - // and doesn't release it before the 5 * 500 ms are elapsed... + // and doesn't release it before the 10 * 500 ms are elapsed... while (serverSocket == null) { try { serverSocket = new DatagramSocket(serverPort, InetAddress.getLocalHost()); } catch (BindException bEx) { - if (retryCount++ < 5) { - sleeptime += sleepAtLeast(500); + if (retryCount++ < 10) { + sleeptime += sleepAtLeast(500); } else { - System.out.println("Give up after 5 retries and " + sleeptime(sleeptime)); + System.out.println("Give up after 10 retries and " + sleeptime(sleeptime)); System.out.println("Has some other process grabbed port " + serverPort + "?"); throw bEx; } @@ -154,6 +157,7 @@ void execute () throws Exception{ clientSock.send(packet); serverSend(); + // try to receive b = new byte[25]; packet = new DatagramPacket(b, b.length, addr, serverPort); @@ -166,8 +170,20 @@ void execute () throws Exception{ } public static void main(String[] args) throws Exception { - PortUnreachable test = new PortUnreachable(); - test.execute(); - } + // A BindException might be thrown intermittently. In that case retry + // 3 times before propagating the exception to finish execution. + int catchCount = 0; + while (true) { + try { + PortUnreachable test = new PortUnreachable(); + test.execute(); + return; + } catch (BindException bEx) { + if (++catchCount > 3) { + throw bEx; + } + } + } + } } From 3c8ec642ffd7d65352f574d9eeaa09ca8c2c0dfd Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Mon, 9 Dec 2019 15:01:57 +0100 Subject: [PATCH 14/32] 8235403: Further cleanup to test serviceability/sa/ClhsdbCDSCore.java Reviewed-by: iklam, iignatyev --- .../serviceability/sa/ClhsdbCDSCore.java | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java index c3d66f83e5f..48f86320c33 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java @@ -112,35 +112,31 @@ public static void main(String[] args) throws Exception { if (Platform.isOSX()) { File coresDir = new File("/cores"); if (!coresDir.isDirectory()) { - throw new Error("cores is not a directory"); + cleanup(); + throw new Error(coresDir + " is not a directory"); } // the /cores directory is usually not writable on macOS 10.15 - final String osVersion = System.getProperty("os.version"); - if (osVersion == null) { - throw new Error("Cannot query the 'os.version' property!"); - } if (!coresDir.canWrite()) { - if (osVersion.startsWith("10.15")) { - throw new SkippedException("/cores is not writable"); - } else { - throw new Error("cores does not have write permissions"); - } + cleanup(); + throw new SkippedException("Directory \"" + coresDir + + "\" is not writable"); } } else if (Platform.isLinux()) { // Check if a crash report tool is installed. File corePatternFile = new File(CORE_PATTERN_FILE_NAME); - Scanner scanner = new Scanner(corePatternFile); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - line = line.trim(); - System.out.println(line); - if (line.startsWith("|")) { - System.out.println( - "\nThis system uses a crash report tool ($cat /proc/sys/kernel/core_pattern).\n" + - "Core files might not be generated. Please reset /proc/sys/kernel/core_pattern\n" + - "to enable core generation. Skipping this test."); - cleanup(); - throw new SkippedException("This system uses a crash report tool"); + try (Scanner scanner = new Scanner(corePatternFile)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + line = line.trim(); + System.out.println(line); + if (line.startsWith("|")) { + System.out.println( + "\nThis system uses a crash report tool ($cat /proc/sys/kernel/core_pattern).\n" + + "Core files might not be generated. Please reset /proc/sys/kernel/core_pattern\n" + + "to enable core generation. Skipping this test."); + cleanup(); + throw new SkippedException("This system uses a crash report tool"); + } } } } From 3f259d8e3a57c073cc0e8777c4198f48df20b0ca Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Mon, 9 Dec 2019 14:07:26 +0000 Subject: [PATCH 15/32] 8141685: com/sun/jndi/ldap/InvalidLdapFilters.java initializes context failed Reviewed-by: dfuchs, vtewari --- .../com/sun/jndi/ldap/InvalidLdapFilters.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/test/jdk/com/sun/jndi/ldap/InvalidLdapFilters.java b/test/jdk/com/sun/jndi/ldap/InvalidLdapFilters.java index e846964819c..39ff7b19331 100644 --- a/test/jdk/com/sun/jndi/ldap/InvalidLdapFilters.java +++ b/test/jdk/com/sun/jndi/ldap/InvalidLdapFilters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /** * @test * @bug 6916202 7041125 + * @library /test/lib * @summary More cases of invalid ldap filters accepted and processed * LDAP API does not catch malformed filters that contain two operands * for the ! operator @@ -87,12 +88,16 @@ import java.io.*; import javax.naming.*; import javax.naming.directory.*; -import java.util.Properties; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Hashtable; import java.net.Socket; import java.net.ServerSocket; +import jdk.test.lib.net.URIBuilder; + public class InvalidLdapFilters { // Should we run the client or server in a separate thread? // @@ -111,9 +116,13 @@ public class InvalidLdapFilters { // If the server prematurely exits, serverReady will be set to true // to avoid infinite hangs. void doServerSide() throws Exception { - ServerSocket serverSock = new ServerSocket(serverPort); + ServerSocket serverSock = new ServerSocket(); + SocketAddress sockAddr = new InetSocketAddress( + InetAddress.getLoopbackAddress(), serverPort); + // Bind server socket + serverSock.bind(sockAddr); - // signal client, it's ready to accecpt connection + // signal client, it's ready to accept connection serverPort = serverSock.getLocalPort(); serverReady = true; @@ -160,10 +169,16 @@ void doClientSide() throws Exception { } // set up the environment for creating the initial context - Hashtable env = new Hashtable(); + Hashtable env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort); + String providerUrl = URIBuilder.newBuilder() + .scheme("ldap") + .loopback() + .port(serverPort) + .build() + .toString(); + env.put(Context.PROVIDER_URL, providerUrl); env.put("com.sun.jndi.ldap.read.timeout", "1000"); // env.put(Context.SECURITY_AUTHENTICATION, "simple"); From 22e26b2a81be87dd10b54772d0a40ed64e4a5683 Mon Sep 17 00:00:00 2001 From: Patrick Concannon Date: Mon, 9 Dec 2019 14:25:37 +0000 Subject: [PATCH 16/32] 8234148: DatagramSocket.setOption/getOption/supportedOption should support multicast options Fix adds multicast socket options to DatagramSocket Reviewed-by: alanb, dfuchs, vtewari --- .../net/AbstractPlainDatagramSocketImpl.java | 17 ------ .../net/DualStackPlainDatagramSocketImpl.java | 18 ++++++ .../DatagramSocket/SupportedOptionsCheck.java | 58 +++++++++++++++++++ .../net/SocketOption/SupportedOptionsSet.java | 28 +++------ 4 files changed, 83 insertions(+), 38 deletions(-) create mode 100644 test/jdk/java/net/DatagramSocket/SupportedOptionsCheck.java diff --git a/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index 2c770037143..8ed0a068da9 100644 --- a/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -404,22 +404,8 @@ public Object getOption(int optID) throws SocketException { ExtendedSocketOptions.getInstance(); private static final Set> datagramSocketOptions = datagramSocketOptions(); - private static final Set> multicastSocketOptions = multicastSocketOptions(); private static Set> datagramSocketOptions() { - HashSet> options = new HashSet<>(); - options.add(StandardSocketOptions.SO_SNDBUF); - options.add(StandardSocketOptions.SO_RCVBUF); - options.add(StandardSocketOptions.SO_REUSEADDR); - options.add(StandardSocketOptions.SO_BROADCAST); - options.add(StandardSocketOptions.IP_TOS); - if (isReusePortAvailable()) - options.add(StandardSocketOptions.SO_REUSEPORT); - options.addAll(ExtendedSocketOptions.datagramSocketOptions()); - return Collections.unmodifiableSet(options); - } - - private static Set> multicastSocketOptions() { HashSet> options = new HashSet<>(); options.add(StandardSocketOptions.SO_SNDBUF); options.add(StandardSocketOptions.SO_RCVBUF); @@ -437,9 +423,6 @@ private static Set> multicastSocketOptions() { @Override protected Set> supportedOptions() { - if (isMulticast) - return multicastSocketOptions; - else return datagramSocketOptions; } diff --git a/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 02a3f3f4000..65464081b63 100644 --- a/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -25,9 +25,14 @@ package java.net; import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import jdk.internal.access.SharedSecrets; import jdk.internal.access.JavaIOFileDescriptorAccess; +import sun.net.ext.ExtendedSocketOptions; + /** * This class defines the plain DatagramSocketImpl that is used on * Windows platforms greater than or equal to Windows Vista. These @@ -230,6 +235,19 @@ protected Object socketGetOption(int opt) throws SocketException { return returnValue; } + @Override + protected Set> supportedOptions() { + HashSet> options = new HashSet<>(); + options.add(StandardSocketOptions.SO_SNDBUF); + options.add(StandardSocketOptions.SO_RCVBUF); + options.add(StandardSocketOptions.SO_REUSEADDR); + options.add(StandardSocketOptions.SO_BROADCAST); + options.add(StandardSocketOptions.IP_TOS); + + options.addAll(ExtendedSocketOptions.datagramSocketOptions()); + return Collections.unmodifiableSet(options); + } + /* Multicast specific methods. * Multicasting on a dual layer TCP/IP stack is always done with * TwoStacksPlainDatagramSocketImpl. This is to overcome the lack diff --git a/test/jdk/java/net/DatagramSocket/SupportedOptionsCheck.java b/test/jdk/java/net/DatagramSocket/SupportedOptionsCheck.java new file mode 100644 index 00000000000..9ad381be73c --- /dev/null +++ b/test/jdk/java/net/DatagramSocket/SupportedOptionsCheck.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8234148 + * @library /test/lib + * @summary checks that the DatagramSocket supportedOptions set contains all + * MulticastSocket socket options + * @run testng SupportedOptionsCheck + */ + +import jdk.test.lib.Platform; +import org.testng.annotations.Test; + +import java.net.DatagramSocket; +import java.net.StandardSocketOptions; +import java.util.Set; + +import static org.testng.Assert.assertTrue; + +public class SupportedOptionsCheck { + + @Test + public void checkMulticastOptionsAreReturned() throws Exception { + try (DatagramSocket ds = new DatagramSocket()) + { + Set options = ds.supportedOptions(); + Set multicastOptions = Set.of( + StandardSocketOptions.IP_MULTICAST_IF, + StandardSocketOptions.IP_MULTICAST_TTL, + StandardSocketOptions.IP_MULTICAST_LOOP); + + if (!Platform.isWindows()) + assertTrue(options.containsAll(multicastOptions)); + } + } +} diff --git a/test/jdk/java/net/SocketOption/SupportedOptionsSet.java b/test/jdk/java/net/SocketOption/SupportedOptionsSet.java index 3bb80971fe3..2f34c3bbd74 100644 --- a/test/jdk/java/net/SocketOption/SupportedOptionsSet.java +++ b/test/jdk/java/net/SocketOption/SupportedOptionsSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,8 @@ */ import java.io.IOException; -import java.net.*; +import java.net.ServerSocket; +import java.net.Socket; import java.util.Set; import static java.lang.System.out; import jdk.test.lib.net.IPSupport; @@ -54,39 +55,24 @@ else if (args[0].equals("second")) static void first() throws IOException { try (Socket s = new Socket(); - ServerSocket ss = new ServerSocket(); - DatagramSocket ds = new DatagramSocket(); - MulticastSocket ms = new MulticastSocket()) { - + ServerSocket ss = new ServerSocket()) + { Set first = s.supportedOptions(); Set second = ss.supportedOptions(); assertNotEqual(first, second, "Socket and ServerSocket should have different options."); - - first = ds.supportedOptions(); - second = ms.supportedOptions(); - assertNotEqual(first, second, - "DatagramSocket and MulticastSocket should have different options."); } } /** Tests with the order of access to supportedOptions reversed. */ static void second() throws IOException { try (ServerSocket ss = new ServerSocket(); - Socket s = new Socket(); - DatagramSocket ds = new DatagramSocket(); - MulticastSocket ms = new MulticastSocket()) { - + Socket s = new Socket()) + { Set first = ss.supportedOptions(); Set second = s.supportedOptions(); assertNotEqual(first, second, "ServerSocket and Socket should have different options."); - - first = ms.supportedOptions(); - second = ds.supportedOptions(); - assertNotEqual(first, second, - "MulticastSocket and DatagramSocket should have different options."); - } } From 3cccc62e56e1b6e65d25f101e904a90381df5212 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 9 Dec 2019 16:46:29 +0100 Subject: [PATCH 17/32] 8234735: InstanceKlass:find_method_index regression after JDK-8231610 Reviewed-by: iklam, coleenp --- src/hotspot/share/oops/instanceKlass.cpp | 27 +++++++++++++++--------- src/hotspot/share/oops/instanceKlass.hpp | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 8f1ed169f6a..7ddc0ced5e1 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1595,27 +1595,34 @@ static int linear_search(const Array* methods, bool InstanceKlass::_disable_method_binary_search = false; -int InstanceKlass::quick_search(const Array* methods, const Symbol* name) { +NOINLINE int linear_search(const Array* methods, const Symbol* name) { int len = methods->length(); int l = 0; int h = len - 1; + while (l <= h) { + Method* m = methods->at(l); + if (m->name() == name) { + return l; + } + l++; + } + return -1; +} +inline int InstanceKlass::quick_search(const Array* methods, const Symbol* name) { if (_disable_method_binary_search) { + assert(DynamicDumpSharedSpaces, "must be"); // At the final stage of dynamic dumping, the methods array may not be sorted // by ascending addresses of their names, so we can't use binary search anymore. // However, methods with the same name are still laid out consecutively inside the // methods array, so let's look for the first one that matches. - assert(DynamicDumpSharedSpaces, "must be"); - while (l <= h) { - Method* m = methods->at(l); - if (m->name() == name) { - return l; - } - l ++; - } - return -1; + return linear_search(methods, name); } + int len = methods->length(); + int l = 0; + int h = len - 1; + // methods are sorted by ascending addresses of their names, so do binary search while (l <= h) { int mid = (l + h) >> 1; diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 0203ac88601..2141eaf3386 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -579,7 +579,7 @@ class InstanceKlass: public Klass { bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const; private: - static int quick_search(const Array* methods, const Symbol* name); + inline static int quick_search(const Array* methods, const Symbol* name); public: static void disable_method_binary_search() { From 12e43e216e7c87292ea34b5f44ec1676858d16c5 Mon Sep 17 00:00:00 2001 From: Patrick Concannon Date: Mon, 9 Dec 2019 15:54:44 +0000 Subject: [PATCH 18/32] 8233191: MulticastSocket joinGroup/leaveGroup do not specify their behavior when the outgoing interface has not been set Clarifies the behaviour of 2-arg joinGroup/leaveGroup methods when null is passed for the NetworkInteface argument. The fix also clarifies what is returned by getInterface() and getNetworkInterface() methods when no previous NetworkInterface has been set. Reviewed-by: alanb, chegar, dfuchs --- .../classes/java/net/MulticastSocket.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/net/MulticastSocket.java b/src/java.base/share/classes/java/net/MulticastSocket.java index a7cac8f31f1..158c4196837 100644 --- a/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/src/java.base/share/classes/java/net/MulticastSocket.java @@ -29,7 +29,6 @@ import java.util.Collections; import java.util.Enumeration; import java.util.Set; - /** * The multicast datagram socket class is useful for sending * and receiving IP multicast packets. A MulticastSocket is @@ -378,15 +377,18 @@ public void leaveGroup(InetAddress mcastaddr) throws IOException { * * @param mcastaddr is the multicast address to join * @param netIf specifies the local interface to receive multicast - * datagram packets, or null to defer to the interface set by + * datagram packets, or {@code null} to defer to the interface set by * {@link MulticastSocket#setInterface(InetAddress)} or - * {@link MulticastSocket#setNetworkInterface(NetworkInterface)} + * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. + * If {@code null}, and no interface has been set, the behaviour is + * unspecified: any interface may be selected or the operation may fail + * with a {@code SocketException}. * @throws IOException if there is an error joining, or when the address * is not a multicast address, or the platform does not support * multicasting * @throws SecurityException if a security manager exists and its * {@code checkMulticast} method doesn't allow the join. - * @throws IllegalArgumentException if mcastaddr is null or is a + * @throws IllegalArgumentException if mcastaddr is {@code null} or is a * SocketAddress subclass not supported by this socket * @see SecurityManager#checkMulticast(InetAddress) * @since 1.4 @@ -423,15 +425,18 @@ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) * {@code mcastaddr} argument as its argument. * * @param mcastaddr is the multicast address to leave - * @param netIf specifies the local interface or null to defer + * @param netIf specifies the local interface or {@code null} to defer * to the interface set by * {@link MulticastSocket#setInterface(InetAddress)} or - * {@link MulticastSocket#setNetworkInterface(NetworkInterface)} + * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. + * If {@code null}, and no interface has been set, the behaviour + * is unspecified: any interface may be selected or the operation + * may fail with a {@code SocketException}. * @throws IOException if there is an error leaving or when the address * is not a multicast address. * @throws SecurityException if a security manager exists and its * {@code checkMulticast} method doesn't allow the operation. - * @throws IllegalArgumentException if mcastaddr is null or is a + * @throws IllegalArgumentException if mcastaddr is {@code null} or is a * SocketAddress subclass not supported by this socket. * @see SecurityManager#checkMulticast(InetAddress) * @since 1.4 @@ -491,7 +496,9 @@ public void setInterface(InetAddress inf) throws SocketException { * multicast packets. * * @return An {@code InetAddress} representing the address - * of the network interface used for multicast packets. + * of the network interface used for multicast packets, + * or if no interface has been set, an {@code InetAddress} + * representing any local address. * @throws SocketException if there is an error in the * underlying protocol, such as a TCP error. * @deprecated The network interface may not be uniquely identified by @@ -573,11 +580,13 @@ public void setNetworkInterface(NetworkInterface netIf) /** * Get the multicast network interface set. * - * @throws SocketException if there is an error in - * the underlying protocol, such as a TCP error. - * @return the multicast {@code NetworkInterface} currently set - * @see #setNetworkInterface(NetworkInterface) - * @since 1.4 + * @throws SocketException if there is an error in + * the underlying protocol, such as a TCP error. + * @return The multicast {@code NetworkInterface} currently set. A placeholder + * NetworkInterface is returned when there is no interface set; it has + * a single InetAddress to represent any local address. + * @see #setNetworkInterface(NetworkInterface) + * @since 1.4 */ public NetworkInterface getNetworkInterface() throws SocketException { NetworkInterface ni From eabb5cc21fdbbb6d637fb85cc5c5ea4427aba7cd Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 9 Dec 2019 19:29:35 +0300 Subject: [PATCH 19/32] 8226411: C2: Avoid memory barriers around off-heap unsafe accesses Reviewed-by: kvn, thartmann, eosterlund, jrose, rkennke --- src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp | 5 ++++- src/hotspot/share/gc/shared/c2/barrierSetC2.cpp | 17 +++++++++++------ src/hotspot/share/oops/accessDecorators.hpp | 4 ++-- src/hotspot/share/opto/library_call.cpp | 12 ++++++++---- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 232297e621c..027b4d65f58 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -597,12 +597,15 @@ Node* G1BarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) c Node* adr = access.addr().node(); Node* obj = access.base(); + bool anonymous = (decorators & C2_UNSAFE_ACCESS) != 0; bool mismatched = (decorators & C2_MISMATCHED) != 0; bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0; bool in_heap = (decorators & IN_HEAP) != 0; + bool in_native = (decorators & IN_NATIVE) != 0; bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; bool is_unordered = (decorators & MO_UNORDERED) != 0; - bool need_cpu_mem_bar = !is_unordered || mismatched || !in_heap; + bool is_mixed = !in_heap && !in_native; + bool need_cpu_mem_bar = !is_unordered || mismatched || is_mixed; Node* top = Compile::current()->top(); Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top; diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index b6431a130d9..1f7cce22cc9 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -43,13 +43,16 @@ void* C2ParseAccess::barrier_set_state() const { PhaseGVN& C2ParseAccess::gvn() const { return _kit->gvn(); } bool C2Access::needs_cpu_membar() const { - bool mismatched = (_decorators & C2_MISMATCHED) != 0; + bool mismatched = (_decorators & C2_MISMATCHED) != 0; bool is_unordered = (_decorators & MO_UNORDERED) != 0; + bool anonymous = (_decorators & C2_UNSAFE_ACCESS) != 0; - bool in_heap = (_decorators & IN_HEAP) != 0; + bool in_heap = (_decorators & IN_HEAP) != 0; + bool in_native = (_decorators & IN_NATIVE) != 0; + bool is_mixed = !in_heap && !in_native; - bool is_write = (_decorators & C2_WRITE_ACCESS) != 0; - bool is_read = (_decorators & C2_READ_ACCESS) != 0; + bool is_write = (_decorators & C2_WRITE_ACCESS) != 0; + bool is_read = (_decorators & C2_READ_ACCESS) != 0; bool is_atomic = is_read && is_write; if (is_atomic) { @@ -63,9 +66,11 @@ bool C2Access::needs_cpu_membar() const { // the barriers get omitted and the unsafe reference begins to "pollute" // the alias analysis of the rest of the graph, either Compile::can_alias // or Compile::must_alias will throw a diagnostic assert.) - if (!in_heap || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) { + if (is_mixed || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) { return true; } + } else { + assert(!is_mixed, "not unsafe"); } return false; @@ -80,7 +85,7 @@ Node* BarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) cons bool requires_atomic_access = (decorators & MO_UNORDERED) == 0; bool in_native = (decorators & IN_NATIVE) != 0; - assert(!in_native, "not supported yet"); + assert(!in_native || (unsafe && !access.is_oop()), "not supported yet"); MemNode::MemOrd mo = access.mem_node_mo(); diff --git a/src/hotspot/share/oops/accessDecorators.hpp b/src/hotspot/share/oops/accessDecorators.hpp index 33a74d6bfd3..55233e12bc7 100644 --- a/src/hotspot/share/oops/accessDecorators.hpp +++ b/src/hotspot/share/oops/accessDecorators.hpp @@ -176,11 +176,11 @@ const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF; // === Access Location === -// Accesses can take place in, e.g. the heap, old or young generation and different native roots. +// Accesses can take place in, e.g. the heap, old or young generation, different native roots, or native memory off the heap. // The location is important to the GC as it may imply different actions. The following decorators are used: // * IN_HEAP: The access is performed in the heap. Many barriers such as card marking will // be omitted if this decorator is not set. -// * IN_NATIVE: The access is performed in an off-heap data structure pointing into the Java heap. +// * IN_NATIVE: The access is performed in an off-heap data structure. const DecoratorSet IN_HEAP = UCONST64(1) << 19; const DecoratorSet IN_NATIVE = UCONST64(1) << 20; const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE; diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 984cda5cad1..520c9c36efd 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -2447,10 +2447,14 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c offset = ConvL2X(offset); adr = make_unsafe_address(base, offset, is_store ? ACCESS_WRITE : ACCESS_READ, type, kind == Relaxed); - if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) { - heap_base_oop = base; - } else if (type == T_OBJECT) { - return false; // off-heap oop accesses are not supported + if (_gvn.type(base)->isa_ptr() == TypePtr::NULL_PTR) { + if (type != T_OBJECT) { + decorators |= IN_NATIVE; // off-heap primitive access + } else { + return false; // off-heap oop accesses are not supported + } + } else { + heap_base_oop = base; // on-heap or mixed access } // Can base be NULL? Otherwise, always on-heap access. From e8496cea836af97d628f501db31bc8c9b3f38ede Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 9 Dec 2019 19:29:39 +0300 Subject: [PATCH 20/32] 8235143: C2: No memory state needed in Thread::currentThread() intrinsic Reviewed-by: mdoerr, jrose --- src/hotspot/share/opto/library_call.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 520c9c36efd..0b7bb361253 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1087,7 +1087,7 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) { const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull); Node* thread = _gvn.transform(new ThreadLocalNode()); Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset())); - Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT, MemNode::unordered); + Node* threadObj = _gvn.transform(LoadNode::make(_gvn, NULL, immutable_memory(), p, p->bottom_type()->is_ptr(), thread_type, T_OBJECT, MemNode::unordered)); tls_output = thread; return threadObj; } From 0ca9d9a032fc2800cc936799e9ed239076564fda Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 9 Dec 2019 23:00:13 +0530 Subject: [PATCH 21/32] 8225562: jlink --module-path behavior inconsistent with help/errors Reviewed-by: alanb --- .../classes/jdk/tools/jlink/resources/jlink.properties | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties index 0353896d660..34d4d1bf245 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties @@ -38,7 +38,12 @@ main.opt.version=\ \ --version Version information main.opt.module-path=\ -\ -p, --module-path Module path +\ -p, --module-path Module path.\n\ +\ If not specified, the JDK's jmods directory\n\ +\ will be used, if it exists. If specified,\n\ +\ but it does not contain the java.base module,\n\ +\ the JDK's jmods directory will be added,\n\ +\ if it exists. main.opt.add-modules=\ \ --add-modules [,...] Root modules to resolve @@ -115,7 +120,7 @@ err.launcher.main.class.empty:launcher main class name cannot be empty: {0} err.launcher.module.name.empty:launcher module name cannot be empty: {0} err.launcher.value.format:launcher value should be of form =[/]: {0} err.output.must.be.specified:--output must be specified -err.modulepath.must.be.specified:--module-path must be specified +err.modulepath.must.be.specified:--module-path is not specified and this runtime image does not contain jmods directory. err.mods.must.be.specified:no modules specified to {0} err.path.not.found=path not found: {0} err.path.not.valid=invalid path: {0} From 72caf85c0f7f5ce0930466c2539676d5217e3396 Mon Sep 17 00:00:00 2001 From: Andy Herrick Date: Mon, 9 Dec 2019 13:01:02 -0500 Subject: [PATCH 22/32] 8235453: tools/jpackage/junit/junit.java failed Reviewed-by: prr --- test/jdk/tools/jpackage/junit/junit.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/tools/jpackage/junit/junit.java b/test/jdk/tools/jpackage/junit/junit.java index fede8895685..ce9441baf49 100644 --- a/test/jdk/tools/jpackage/junit/junit.java +++ b/test/jdk/tools/jpackage/junit/junit.java @@ -27,5 +27,6 @@ * @test * @summary jpackage unit tests * @library ${jtreg.home}/lib/junit.jar + * @modules jdk.incubator.jpackage * @run shell run_junit.sh */ From 749bda0e2dc07881b2d9a1d60b8d559d4aaa6ad0 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Mon, 9 Dec 2019 09:59:03 -0800 Subject: [PATCH 23/32] 8235490: AppCDS DynamicArchiveRelocationTest.java failed: 'always map archive(s) at an alternative address' missing Reviewed-by: coleenp, ccheung --- src/hotspot/share/memory/metaspaceShared.cpp | 1 + .../hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java | 2 +- .../cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index eb7dfee76e7..e6a70f5f849 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -2052,6 +2052,7 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { if (result == MAP_ARCHIVE_MMAP_FAILURE) { // Mapping has failed (probably due to ASLR). Let's map at an address chosen // by the OS. + log_info(cds)("Try to map archive(s) at an alternative address"); result = map_archives(static_mapinfo, dynamic_mapinfo, false); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java index 935a0af6139..c43e383a0e6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java @@ -80,7 +80,7 @@ static void test(boolean dump_reloc, boolean run_reloc) throws Exception { TestCommon.run("-cp", appJar, unlockArg, runRelocArg, logArg, mainClass) .assertNormalExit(output -> { if (run_reloc) { - output.shouldContain("ArchiveRelocationMode == 1: always map archive(s) at an alternative address"); + output.shouldContain("Try to map archive(s) at an alternative address"); } }); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java index dd7dac149aa..c17a1b55faf 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java @@ -88,7 +88,7 @@ static void doTest() throws Exception { String baseArchiveName = getNewArchiveName("base"); String topArchiveName = getNewArchiveName("top"); - String runtimeMsg = "ArchiveRelocationMode == 1: always map archive(s) at an alternative address"; + String runtimeMsg = "Try to map archive(s) at an alternative address"; String unlockArg = "-XX:+UnlockDiagnosticVMOptions"; // (1) Dump base archive (static) From 45b8d09e1bc2e41ddda79ac7881d840eb6e2d49a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 9 Dec 2019 10:44:02 -0800 Subject: [PATCH 24/32] 8234211: allow discoverable javac plugins to be invoked by default Reviewed-by: jlahoda --- .../classes/com/sun/source/util/Plugin.java | 18 +- .../sun/tools/javac/api/BasicJavacTask.java | 16 +- .../com/sun/tools/javac/main/Main.java | 8 +- .../tools/javac/plugin/AutostartPlugins.java | 175 ++++++++++++++++++ 4 files changed, 208 insertions(+), 9 deletions(-) create mode 100644 test/langtools/tools/javac/plugin/AutostartPlugins.java diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/Plugin.java b/src/jdk.compiler/share/classes/com/sun/source/util/Plugin.java index 68c14f7e454..9a41396d84d 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/Plugin.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/Plugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,4 +62,20 @@ public interface Plugin { * @param args Arguments, if any, for the plug-in */ void init(JavacTask task, String... args); + + /** + * Returns whether or not this plugin should be automatically started, + * even if not explicitly specified in the command-line options. + * + *

This method will be called by javac for all plugins located by the + * service loader. If the method returns {@code true}, the plugin will be + * {@link #init(JavacTask,String[]) initialized} with an empty array of + * string arguments if it is not otherwise initialized due to an explicit + * command-line option. + * + * @return whether or not this plugin should be automatically started + */ + default boolean autoStart() { + return false; + } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java index 0861412f291..a7e877dd1e1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java @@ -208,16 +208,18 @@ public void initPlugins(Set> pluginOpts) { } } - if (pluginOpts.isEmpty()) - return; - Set> pluginsToCall = new LinkedHashSet<>(pluginOpts); JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context); ServiceLoader sl = pEnv.getServiceLoader(Plugin.class); + Set autoStart = new LinkedHashSet<>(); for (Plugin plugin : sl) { + if (plugin.autoStart()) { + autoStart.add(plugin); + } for (List p : pluginsToCall) { if (plugin.getName().equals(p.head)) { pluginsToCall.remove(p); + autoStart.remove(plugin); try { plugin.init(this, p.tail.toArray(new String[p.tail.size()])); } catch (RuntimeException ex) { @@ -230,6 +232,14 @@ public void initPlugins(Set> pluginOpts) { for (List p: pluginsToCall) { Log.instance(context).error(Errors.PluginNotFound(p.head)); } + for (Plugin plugin : autoStart) { + try { + plugin.init(this, new String[0]); + } catch (RuntimeException ex) { + throw new PropagatedException(ex); + } + + } } public void initDocLint(List docLintOpts) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java index a6a01570350..4f5a2a4f113 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java @@ -284,12 +284,11 @@ public void put(String name, String value) { } Dependencies.GraphDependencies.preRegister(context); } + BasicJavacTask t = (BasicJavacTask) BasicJavacTask.instance(context); + // init plugins Set> pluginOpts = args.getPluginOpts(); - if (!pluginOpts.isEmpty() || context.get(PlatformDescription.class) != null) { - BasicJavacTask t = (BasicJavacTask) BasicJavacTask.instance(context); - t.initPlugins(pluginOpts); - } + t.initPlugins(pluginOpts); // init multi-release jar handling if (fileManager.isSupportedOption(Option.MULTIRELEASE.primaryName) == 1) { @@ -304,7 +303,6 @@ public void put(String name, String value) { } // init doclint List docLintOpts = args.getDocLintOpts(); if (!docLintOpts.isEmpty()) { - BasicJavacTask t = (BasicJavacTask) BasicJavacTask.instance(context); t.initDocLint(docLintOpts); } diff --git a/test/langtools/tools/javac/plugin/AutostartPlugins.java b/test/langtools/tools/javac/plugin/AutostartPlugins.java new file mode 100644 index 00000000000..30116d68b43 --- /dev/null +++ b/test/langtools/tools/javac/plugin/AutostartPlugins.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8234211 + * @summary allow discoverable javac plugins to be invoked by default + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jlink + * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask + * @run main AutostartPlugins + */ + +import java.io.IOException; +import java.util.List; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.spi.ToolProvider; + +import toolbox.ExecTask; +import toolbox.JarTask; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class AutostartPlugins extends TestRunner { + public static void main(String... args) throws Exception { + new AutostartPlugins().run(); + } + + AutostartPlugins() { + super(System.out); + } + + ToolBox tb = new ToolBox(); + + Path pluginJar; + Path mclasses; + + void run() throws Exception { + Path src = Path.of("src"); + tb.writeJavaFiles(src, + "package p;\n" + + "import com.sun.source.util.*;\n" + + "public class C implements Plugin {\n" + + " public String getName() { return \"TestPlugin\"; }\n" + + " public boolean autoStart() { return true; }\n" + + " public void init(JavacTask task, String... args) {\n" + + " System.out.println(\"C.init \" + java.util.Arrays.toString(args));\n" + + " }\n" + + "}\n"); + + Path msrc = Path.of("msrc"); + tb.writeJavaFiles(msrc, + "module m {\n" + + " requires jdk.compiler;\n" + + " provides com.sun.source.util.Plugin with p.C;\n" + + "}\n"); + + Path classes = Files.createDirectories(Path.of("classes")); + new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); + + tb.writeFile(classes.resolve("META-INF").resolve("services").resolve("com.sun.source.util.Plugin"), + "p.C\n"); + + pluginJar = Path.of("plugin.jar"); + new JarTask(tb, pluginJar) + .baseDir(classes) + .files(".") + .run(); + + mclasses = Files.createDirectories(Path.of("mclasses")); + new JavacTask(tb) + .outdir(mclasses) + .sourcepath(msrc, src) + .files(tb.findJavaFiles(msrc)) + .run() + .writeAll(); + + Path hw = Path.of("hw"); + tb.writeJavaFiles(hw, + "public class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World!\");\n" + + " }\n" + + "}\n"); + + runTests(m -> new Object[] { Path.of(m.getName()) }); + } + + @Test + public void testClassPath(Path base) throws Exception { + List stdout = new JavacTask(tb) + .classpath(pluginJar) + .outdir(Files.createDirectories(base.resolve("out"))) + .files(tb.findJavaFiles(Path.of("hw"))) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + tb.checkEqual(stdout, List.of("C.init []")); + } + + @Test + public void testModulePath(Path base) throws IOException { + List stdout = new JavacTask(tb) + .options("--processor-module-path", mclasses.toString()) + .outdir(Files.createDirectories(base.resolve("out"))) + .files(tb.findJavaFiles(Path.of("hw"))) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + tb.checkEqual(stdout, List.of("C.init []")); + } + + @Test + public void testImage(Path base) throws Exception { + Path tmpJDK = base.resolve("tmpJDK"); + ToolProvider jlink = ToolProvider.findFirst("jlink") + .orElseThrow(() -> new Exception("cannot find jlink")); + jlink.run(System.out, System.err, + "--module-path", mclasses.toString(), + "--add-modules", "jdk.compiler,jdk.zipfs,m", + "--output", tmpJDK.toString()); + + String suffix = tb.isWindows() ? ".exe" : ""; + List stdout = new ExecTask(tb, tmpJDK.resolve("bin").resolve("javac" + suffix)) + .args("-d", Files.createDirectories(base.resolve("out")).toString(), + Path.of("hw").resolve("HelloWorld.java").toString()) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + tb.checkEqual(stdout, List.of("C.init []")); + } + + @Test + public void testOverride(Path base) throws IOException { + List stdout = new JavacTask(tb) + .classpath(pluginJar) + .outdir(Files.createDirectories(base.resolve("out"))) + .options("-Xplugin:TestPlugin -args") + .files(tb.findJavaFiles(Path.of("hw"))) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + tb.checkEqual(stdout, List.of("C.init [-args]")); + } +} + From baebce3d2f996cf2731be8c5d387e709f1213d30 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Mon, 9 Dec 2019 10:56:27 -0800 Subject: [PATCH 25/32] 8235448: code cleanup in SSLContextImpl.java Reviewed-by: jnimeh --- .../sun/security/ssl/SSLContextImpl.java | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 0824f2d702d..53ff1454a53 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -25,7 +25,7 @@ package sun.security.ssl; -import java.io.*; +import java.io.FileInputStream; import java.net.Socket; import java.security.*; import java.security.cert.*; @@ -71,7 +71,8 @@ public abstract class SSLContextImpl extends SSLContextSpi { private volatile StatusResponseManager statusResponseManager; private final ReentrantLock contextLock = new ReentrantLock(); - final HashMap keyHashMap = new HashMap<>(); + final HashMap keyHashMap = new HashMap<>(); SSLContextImpl() { @@ -594,17 +595,6 @@ SSLEngine createSSLEngineImpl(String host, int port) { boolean isDTLS() { return false; } - - static ProtocolVersion[] getSupportedProtocols() { - return new ProtocolVersion[]{ - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30, - ProtocolVersion.SSL20Hello - }; - } } /* @@ -858,9 +848,24 @@ private static List customizedProtocols( ProtocolVersion[] candidates; if (refactored.isEmpty()) { if (client) { - candidates = getProtocols(); + // default client protocols + candidates = new ProtocolVersion[] { + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30 + }; + } else { - candidates = getSupportedProtocols(); + candidates = new ProtocolVersion[] { + ProtocolVersion.TLS13, + ProtocolVersion.TLS12, + ProtocolVersion.TLS11, + ProtocolVersion.TLS10, + ProtocolVersion.SSL30, + ProtocolVersion.SSL20Hello + }; } } else { // Use the customized TLS protocols. @@ -871,16 +876,6 @@ private static List customizedProtocols( return getAvailableProtocols(candidates); } - static ProtocolVersion[] getProtocols() { - return new ProtocolVersion[]{ - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, - ProtocolVersion.TLS11, - ProtocolVersion.TLS10, - ProtocolVersion.SSL30 - }; - } - protected CustomizedTLSContext() { if (reservedException != null) { throw reservedException; @@ -906,8 +901,6 @@ List getClientDefaultCipherSuites() { List getServerDefaultCipherSuites() { return serverDefaultCipherSuites; } - - } /* @@ -1183,7 +1176,6 @@ private abstract static class AbstractDTLSContext extends SSLContextImpl { private static final List serverDefaultCipherSuites; static { - // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode. supportedProtocols = Arrays.asList( ProtocolVersion.DTLS12, ProtocolVersion.DTLS10 From 93286c94dce309858419841ff0a35bdf984bec14 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Mon, 9 Dec 2019 14:01:03 -0500 Subject: [PATCH 26/32] 8235586: Shenandoah: Traversal GC still uses old CLD::oops_do API Reviewed-by: rkennke --- src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp index c3966073948..205d1b4bc86 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp @@ -140,7 +140,7 @@ class ShenandoahMarkCLDClosure : public CLDClosure { public: ShenandoahMarkCLDClosure(OopClosure* cl) : _cl(cl) {} void do_cld(ClassLoaderData* cld) { - cld->oops_do(_cl, true, true); + cld->oops_do(_cl, ClassLoaderData::_claim_strong, true); } }; @@ -152,7 +152,7 @@ class ShenandoahRemarkCLDClosure : public CLDClosure { ShenandoahRemarkCLDClosure(OopClosure* cl) : _cl(cl) {} void do_cld(ClassLoaderData* cld) { if (cld->has_modified_oops()) { - cld->oops_do(_cl, true, true); + cld->oops_do(_cl, ClassLoaderData::_claim_strong, true); } } }; From 589f23568a4c83e51d382c1335a89dae1809eebf Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 9 Dec 2019 12:27:57 -0800 Subject: [PATCH 27/32] 8234689: facilitate writing additional custom attributes in a class file Reviewed-by: jlahoda --- .../com/sun/tools/javac/jvm/ClassWriter.java | 36 +++- .../javac/classwriter/ExtraAttributes.java | 155 ++++++++++++++++++ 2 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 test/langtools/tools/javac/classwriter/ExtraAttributes.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 474e74dc5be..f4b893f1a26 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Set; import java.util.LinkedHashSet; +import java.util.function.Function; import javax.tools.JavaFileManager; import javax.tools.FileObject; @@ -113,6 +114,8 @@ public class ClassWriter extends ClassFile { */ public boolean multiModuleMode; + private List> extraAttributeHooks = List.nil(); + /** The initial sizes of the data and constant pool buffers. * Sizes are increased when buffers get full. */ @@ -121,7 +124,7 @@ public class ClassWriter extends ClassFile { /** An output buffer for member info. */ - ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE); + public ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE); /** An output buffer for the constant pool. */ @@ -188,6 +191,10 @@ protected ClassWriter(Context context) { } } + public void addExtraAttributes(Function addExtraAttributes) { + extraAttributeHooks = extraAttributeHooks.prepend(addExtraAttributes); + } + /****************************************************************** * Diagnostics: dump generated class names and modifiers ******************************************************************/ @@ -276,7 +283,7 @@ public StringOverflow(String s) { /** Write header for an attribute to data buffer and return * position past attribute length index. */ - int writeAttr(Name attrName) { + public int writeAttr(Name attrName) { int index = poolWriter.putName(attrName); databuf.appendChar(index); databuf.appendInt(0); @@ -285,7 +292,7 @@ int writeAttr(Name attrName) { /** Fill in attribute length. */ - void endAttr(int index) { + public void endAttr(int index) { putInt(databuf, index - 4, databuf.length - index); } @@ -942,6 +949,7 @@ void writeField(VarSymbol v) { acount++; } acount += writeMemberAttrs(v, false); + acount += writeExtraAttributes(v); endAttrs(acountIdx, acount); } @@ -988,6 +996,7 @@ void writeMethod(MethodSymbol m) { acount += writeMemberAttrs(m, false); if (!m.isLambdaMethod()) acount += writeParameterAttrs(m.params); + acount += writeExtraAttributes(m); endAttrs(acountIdx, acount); } @@ -1605,6 +1614,7 @@ public void writeClassFile(OutputStream out, ClassSymbol c) acount += writeFlagAttrs(c.owner.flags() & ~DEPRECATED); } acount += writeExtraClassAttributes(c); + acount += writeExtraAttributes(c); poolbuf.appendInt(JAVA_MAGIC); if (preview.isEnabled()) { @@ -1643,14 +1653,26 @@ public void writeClassFile(OutputStream out, ClassSymbol c) poolWriter.reset(); // to save space out.write(databuf.elems, 0, databuf.length); - } + } + + /**Allows subclasses to write additional class attributes + * + * @return the number of attributes written + */ + protected int writeExtraClassAttributes(ClassSymbol c) { + return 0; + } - /**Allows subclasses to write additional class attributes + /**Allows friends to write additional attributes * * @return the number of attributes written */ - protected int writeExtraClassAttributes(ClassSymbol c) { - return 0; + protected int writeExtraAttributes(Symbol sym) { + int i = 0; + for (Function hook : extraAttributeHooks) { + i += hook.apply(sym); + } + return i; } int adjustFlags(final long flags) { diff --git a/test/langtools/tools/javac/classwriter/ExtraAttributes.java b/test/langtools/tools/javac/classwriter/ExtraAttributes.java new file mode 100644 index 00000000000..22bc46327e4 --- /dev/null +++ b/test/langtools/tools/javac/classwriter/ExtraAttributes.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8234689 + * @summary facilitate writing additional custom attributes in a class file + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.jvm + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.JarTask toolbox.JavacTask toolbox.JavapTask toolbox.ToolBox + * @run main ExtraAttributes + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.Plugin; + +import com.sun.tools.javac.api.BasicJavacTask; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.jvm.ClassWriter; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Names; + +import toolbox.JarTask; +import toolbox.JavapTask; +import toolbox.Task; +import toolbox.ToolBox; + + +public class ExtraAttributes implements Plugin { + public static void main(String... args) throws Exception { + new ExtraAttributes().run(); + } + + void run() throws Exception { + ToolBox tb = new ToolBox(); + Path pluginClasses = Path.of("plugin-classes"); + tb.writeFile(pluginClasses.resolve("META-INF").resolve("services").resolve(Plugin.class.getName()), + ExtraAttributes.class.getName() + "\n"); + Files.copy(Path.of(ToolBox.testClasses).resolve("ExtraAttributes.class"), + pluginClasses.resolve("ExtraAttributes.class")); + + Path pluginJar = Path.of("plugin.jar"); + new JarTask(tb, pluginJar) + .baseDir(pluginClasses) + .files(".") + .run(); + + Path src = Path.of("src"); + tb.writeJavaFiles(src, + "public class HelloWorld {\n" + + " public static String message = \"Hello World!\";\n" + + " public static void main(String... args) {\n" + + " System.out.println(message);\n" + + " }\n" + + "}\n"); + + List stdout = new toolbox.JavacTask(tb) + .classpath(pluginJar) + .options("-Xplugin:ExtraAttributes") + .outdir(Files.createDirectories(Path.of("classes"))) + .files(tb.findJavaFiles(src)) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.STDOUT); + + // cannot rely on order of output, so sort it + stdout.sort(CharSequence::compare); + + tb.checkEqual(stdout, + List.of( + "Add attributes for ()", + "Add attributes for HelloWorld", + "Add attributes for HelloWorld()", + "Add attributes for main(java.lang.String...)", + "Add attributes for message" + )); + + List lines = new JavapTask(tb) + .options("-p", + "-v", + Path.of("classes").resolve("HelloWorld.class").toString()) + .run() + .getOutputLines(Task.OutputKind.DIRECT); + + long attrs = lines.stream() + .filter(s -> s.contains("testAttr:")) + .count(); + if (attrs != 5) { + throw new Exception("expected attributes not found; expected: 5; found: " + attrs); + } + } + + // Plugin impl... + + private ClassWriter classWriter; + private Names names; + + @Override + public String getName() { return "ExtraAttributes"; } + + @Override + public void init(JavacTask task, String... args) { + Context c = ((BasicJavacTask) task).getContext(); + classWriter = ClassWriter.instance(c); + names = Names.instance(c); + + // register callback + classWriter.addExtraAttributes(this::addExtraAttributes); + } + + @Override + public boolean autoStart() { + return true; + } + + private int addExtraAttributes(Symbol sym) { + System.out.println("Add attributes for " + sym); + Name testAttr = names.fromString("testAttr"); + int alenIdx = classWriter.writeAttr(testAttr); + classWriter.databuf.appendChar(42); + classWriter.endAttr(alenIdx); + return 1; + } +} + From dc0cc5520c2299375e829d0de64d7d6e14990ba5 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Mon, 9 Dec 2019 13:02:07 -0800 Subject: [PATCH 28/32] 8235530: Removed duplicated threadByName methods in nsk/jdi tests Reviewed-by: dholmes, sspitsyn --- .../BooleanType/_itself_/booleantype001.java | 23 +-- .../addInstanceFilter/instancefilter002.java | 22 +-- .../addInstanceFilter/instancefilter003.java | 22 +-- .../addThreadFilter/threadfilter002.java | 21 +-- .../addThreadFilter/threadfilter003.java | 150 ++++++++---------- .../location/location001.java | 22 +-- .../jdi/ByteType/_itself_/bytetype001.java | 21 +-- .../jdi/CharType/_itself_/chartype001.java | 21 +-- .../definedClasses/definedclasses001.java | 22 +-- .../visibleClasses/visibleclasses001.java | 23 +-- .../addClassExclusionFilter/filter003.java | 22 +-- .../addClassFilter_rt/filter_rt002.java | 22 +-- .../addClassFilter_s/filter_s002.java | 22 +-- .../invokeMethod/invokemethod015.java | 13 -- .../DoubleType/_itself_/doubletype001.java | 22 +-- .../nsk/jdi/Event/request/request001.java | 22 +-- .../EventIterator/nextEvent/nextevent001.java | 22 +-- .../nsk/jdi/EventQueue/remove/remove004.java | 22 +-- .../jdi/EventQueue/remove_l/remove_l004.java | 22 +-- .../addCountFilter/addcountfilter001.java | 24 +-- .../jdi/EventRequest/disable/disable001.java | 24 +-- .../jdi/EventRequest/disable/disable002.java | 24 +-- .../jdi/EventRequest/enable/enable001.java | 24 +-- .../jdi/EventRequest/enable/enable002.java | 24 +-- .../getProperty/getproperty001.java | 24 +-- .../EventRequest/hashCode/hashcode001.java | 15 +- .../EventRequest/isEnabled/isenabled001.java | 24 +-- .../putProperty/putproperty001.java | 24 +-- .../setEnabled/setenabled001.java | 24 +-- .../setEnabled/setenabled002.java | 24 +-- .../setEnabled/setenabled003.java | 21 +-- .../setSuspendPolicy/setsuspendpolicy001.java | 24 +-- .../suspendPolicy/suspendpolicy001.java | 23 +-- .../accwtchpreq002.java | 21 +-- .../breakpointRequests/breakpreq002.java | 22 +-- .../classPrepareRequests/clsprepreq002.java | 22 +-- .../classUnloadRequests/clsunlreq002.java | 22 +-- .../craccwtchpreq003.java | 22 +-- .../crbreakpreq003.java | 22 +-- .../createClassPrepareRequest/cpreg001.java | 21 +-- .../createClassUnloadRequest/cureg001.java | 22 +-- .../createExceptionRequest/crexreq009.java | 22 +-- .../createExceptionRequest/crexreq010.java | 22 +-- .../createMethodEntryRequest/menreg001.java | 22 +-- .../createMethodExitRequest/mexreg001.java | 21 +-- .../crmodwtchpreq003.java | 21 +-- .../createStepRequest/crstepreq002.java | 24 +-- .../createStepRequest/crstepreq003.java | 17 +- .../createStepRequest/crstepreq004.java | 17 +- .../createStepRequest/crstepreq005.java | 15 +- .../createStepRequest/crstepreq006.java | 15 +- .../createStepRequest/crstepreq007.java | 15 +- .../createStepRequest/crstepreq008.java | 15 +- .../createStepRequest/crstepreq009.java | 15 +- .../createStepRequest/crstepreq010.java | 15 +- .../createThreadDeathRequest/tdreg001.java | 22 +-- .../createThreadStartRequest/tsreg001.java | 22 +-- .../createVMDeathRequest/vmdreg001.java | 22 +-- .../deleteAllBreakpoints/delallbreakp002.java | 22 +-- .../deleteEventRequest/delevtreq002.java | 22 +-- .../deleteEventRequests/delevtreqs002.java | 22 +-- .../exceptionRequests/excreq002.java | 22 +-- .../methodEntryRequests/methentreq002.java | 22 +-- .../methodExitRequests/methexitreq002.java | 22 +-- .../modwtchpreq002.java | 22 +-- .../stepRequests/stepreq002.java | 22 +-- .../threadDeathRequests/thrdeathreq002.java | 22 +-- .../threadStartRequests/thrstartreq002.java | 22 +-- .../vmDeathRequests/vmdeathreq001.java | 22 +-- .../eventIterator/eventiterator001.java | 22 +-- .../eventIterator/eventiterator002.java | 22 +-- .../eventIterator/eventiterator003.java | 21 +-- .../eventIterator/eventiterator004.java | 22 +-- .../nsk/jdi/EventSet/resume/resume002.java | 22 +-- .../nsk/jdi/EventSet/resume/resume003.java | 22 +-- .../nsk/jdi/EventSet/resume/resume004.java | 22 +-- .../nsk/jdi/EventSet/resume/resume005.java | 22 +-- .../nsk/jdi/EventSet/resume/resume006.java | 22 +-- .../nsk/jdi/EventSet/resume/resume007.java | 22 +-- .../nsk/jdi/EventSet/resume/resume010.java | 22 +-- .../nsk/jdi/EventSet/resume/resume011.java | 22 +-- .../nsk/jdi/EventSet/resume/resume012.java | 22 +-- .../nsk/jdi/EventSet/resume/resume013.java | 22 +-- .../suspendPolicy/suspendpolicy001.java | 22 +-- .../suspendPolicy/suspendpolicy002.java | 22 +-- .../suspendPolicy/suspendpolicy003.java | 22 +-- .../suspendPolicy/suspendpolicy004.java | 22 +-- .../suspendPolicy/suspendpolicy005.java | 22 +-- .../suspendPolicy/suspendpolicy006.java | 22 +-- .../suspendPolicy/suspendpolicy007.java | 22 +-- .../suspendPolicy/suspendpolicy008.java | 22 +-- .../suspendPolicy/suspendpolicy009.java | 22 +-- .../suspendPolicy/suspendpolicy010.java | 22 +-- .../suspendPolicy/suspendpolicy011.java | 22 +-- .../suspendPolicy/suspendpolicy012.java | 22 +-- .../suspendPolicy/suspendpolicy013.java | 22 +-- .../suspendPolicy/suspendpolicy014.java | 22 +-- .../suspendPolicy/suspendpolicy015.java | 22 +-- .../suspendPolicy/suspendpolicy016.java | 21 +-- .../suspendPolicy/suspendpolicy017.java | 22 +-- .../addClassExclusionFilter/filter002.java | 22 +-- .../addClassFilter_rt/filter_rt002.java | 22 +-- .../addClassFilter_s/filter_s002.java | 22 +-- .../addInstanceFilter/instancefilter002.java | 22 +-- .../addInstanceFilter/instancefilter003.java | 22 +-- .../addThreadFilter/threadfilter002.java | 22 +-- .../addThreadFilter/threadfilter003.java | 22 +-- .../exception/exception001.java | 22 +-- .../notifyCaught/notifycaught001.java | 22 +-- .../notifyUncaught/notifyuncaught001.java | 22 +-- .../jdi/FloatType/_itself_/floattype001.java | 22 +-- .../IntegerType/_itself_/integertype001.java | 22 +-- .../jdi/LocatableEvent/thread/thread001.java | 22 +-- .../jdi/LongType/_itself_/longtype001.java | 22 +-- .../addClassExclusionFilter/filter002.java | 22 +-- .../addClassFilter_rt/filter_rt002.java | 22 +-- .../addClassFilter_s/filter_s002.java | 22 +-- .../addInstanceFilter/instancefilter002.java | 22 +-- .../addInstanceFilter/instancefilter003.java | 22 +-- .../addThreadFilter/threadfilter002.java | 22 +-- .../addThreadFilter/threadfilter003.java | 22 +-- .../addClassExclusionFilter/filter002.java | 22 +-- .../addClassFilter_rt/filter_rt002.java | 22 +-- .../addClassFilter_s/filter_s002.java | 22 +-- .../addInstanceFilter/instancefilter002.java | 22 +-- .../addInstanceFilter/instancefilter003.java | 22 +-- .../addThreadFilter/threadfilter002.java | 22 +-- .../addThreadFilter/threadfilter003.java | 22 +-- .../_itself_/mwevent001.java | 22 +-- .../disablecollection002.java | 22 +-- .../classPath/classpath001.java | 22 +-- .../_itself_/primitivetype001.java | 22 +-- .../classLoader/classloader001.java | 22 +-- .../ReferenceType/getValue/getvalue001.java | 22 +-- .../ReferenceType/getValue/getvalue002.java | 22 +-- .../ReferenceType/getValue/getvalue003.java | 22 +-- .../ReferenceType/getValues/getvalues001.java | 22 +-- .../jdi/ReferenceType/isFinal/isfinal001.java | 22 +-- .../ReferenceType/isStatic/isstatic001.java | 22 +-- .../ReferenceType/isStatic/isstatic002.java | 22 +-- .../nestedTypes/nestedtypes001.java | 22 +-- .../nestedTypes/nestedtypes002.java | 22 +-- .../jdi/ShortType/_itself_/shorttype001.java | 22 +-- .../addClassExclusionFilter/filter002.java | 24 +-- .../addClassFilter_rt/filter_rt002.java | 24 +-- .../addClassFilter_s/filter_s002.java | 24 +-- .../addInstanceFilter/instancefilter002.java | 22 +-- .../addInstanceFilter/instancefilter003.java | 22 +-- .../nsk/jdi/StepRequest/depth/depth001.java | 24 +-- .../nsk/jdi/StepRequest/depth/depth002.java | 24 +-- .../nsk/jdi/StepRequest/depth/depth003.java | 24 +-- .../nsk/jdi/StepRequest/size/size001.java | 24 +-- .../nsk/jdi/StepRequest/size/size002.java | 24 +-- .../nsk/jdi/StepRequest/thread/thread001.java | 24 +-- .../addThreadFilter/addthreadfilter001.java | 22 +-- .../addThreadFilter/addthreadfilter002.java | 22 +-- .../addThreadFilter/addthreadfilter003.java | 22 +-- .../addThreadFilter/addthreadfilter005.java | 22 +-- .../popFrames/popframes001.java | 26 +-- .../popFrames/popframes002.java | 26 +-- .../popFrames/popframes003.java | 27 +--- .../popFrames/popframes004.java | 24 +-- .../popFrames/popframes005.java | 24 +-- .../addThreadFilter/addthreadfilter001.java | 22 +-- .../addThreadFilter/addthreadfilter002.java | 22 +-- .../addThreadFilter/addthreadfilter003.java | 22 +-- .../addThreadFilter/addthreadfilter005.java | 22 +-- .../jdi/VMDeathEvent/_itself_/vmdeath002.java | 21 +-- .../jdi/VMDeathEvent/_itself_/vmdeath003.java | 22 +-- .../allClasses/allclasses001.java | 22 +-- .../canAddMethod/canaddmethod001.java | 22 +-- .../canPopFrames/canpopframes001.java | 22 +-- .../canredefineclasses001.java | 22 +-- .../canreqvmdev001.java | 22 +-- .../curc001.java | 22 +-- .../canusefilters001.java | 22 +-- .../canwatchaccess001.java | 22 +-- .../canwatchmod001.java | 22 +-- .../redefineClasses/redefineclasses001.java | 26 +-- .../jdi/VoidType/_itself_/voidtype001.java | 22 +-- .../addClassExclusionFilter/filter003.java | 22 +-- .../addClassExclusionFilter/filter004.java | 22 +-- .../addClassFilter_rt/filter_rt003.java | 22 +-- .../addClassFilter_rt/filter_rt004.java | 22 +-- .../addClassFilter_s/filter_s003.java | 22 +-- .../addClassFilter_s/filter_s004.java | 22 +-- .../addInstanceFilter/instancefilter003.java | 22 +-- .../addInstanceFilter/instancefilter004.java | 22 +-- .../addInstanceFilter/instancefilter005.java | 22 +-- .../addInstanceFilter/instancefilter006.java | 22 +-- .../addThreadFilter/addthreadfilter003.java | 22 +-- .../addThreadFilter/addthreadfilter004.java | 22 +-- .../addThreadFilter/addthreadfilter005.java | 22 +-- .../addThreadFilter/addthreadfilter006.java | 22 +-- .../jdi/WatchpointRequest/field/field001.java | 22 +-- .../jdi/WatchpointRequest/field/field002.java | 22 +-- .../vmTestbase/nsk/share/jdi/Debugee.java | 14 ++ .../share/jdi/JDITestRuntimeException.java | 7 + 198 files changed, 314 insertions(+), 4134 deletions(-) create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDITestRuntimeException.java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java index 9bedcc54989..fc595162b34 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BooleanType/_itself_/booleantype001.java @@ -142,13 +142,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +285,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -347,20 +340,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java index cbc2b30f939..95f2bd2b4b2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -310,7 +304,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java index b7863ebe6e3..8dcabd16b16 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addInstanceFilter/instancefilter003.java @@ -150,12 +150,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -298,7 +292,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -386,20 +380,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java index 79ccc79dd38..a73e342938c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter002.java @@ -156,12 +156,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -304,7 +298,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -405,19 +399,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java index 6ea1964f821..9e73e2e750b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/addThreadFilter/threadfilter003.java @@ -156,12 +156,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -285,7 +279,7 @@ private void testRun() eventRManager = vm.eventRequestManager(); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); - cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD); + cpRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); cpRequest.addClassFilter(debuggeeName); cpRequest.enable(); @@ -297,21 +291,21 @@ private void testRun() debuggeeClass = event.referenceType(); if (!debuggeeClass.name().equals(debuggeeName)) - throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); + throw new JDITestRuntimeException("** Unexpected ClassName for ClassPrepareEvent **"); log2(" received: ClassPrepareEvent for debuggeeClass"); String bPointMethod = "methodForCommunication"; - String lineForComm = "lineForComm"; + String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, - debuggeeClass, - bPointMethod, lineForComm, "zero"); + debuggeeClass, + bPointMethod, lineForComm, "zero"); bpRequest.enable(); - //------------------------------------------------------ testing section + //------------------------------------------------------ testing section log1(" TESTING BEGINS"); @@ -319,8 +313,8 @@ private void testRun() EventRequest eventRequest2 = null; EventRequest eventRequest3 = null; - ThreadReference thread1 = null; - String thread1Name = "thread1"; + ThreadReference thread1 = null; + String thread1Name = "thread1"; String property1 = "BreakpointRequest1"; String property2 = "BreakpointRequest2"; @@ -337,7 +331,7 @@ private void testRun() breakpointForCommunication(); int instruction = ((IntegerValue) - (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); + (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); if (instruction == 0) { vm.resume(); @@ -350,63 +344,63 @@ private void testRun() switch (i) { - case 0: - testClassReference = + case 0: + testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); - thread1 = (ThreadReference) debuggeeClass.getValue( - debuggeeClass.fieldByName(thread1Name)); - - eventRequest1 = setting2BreakpointRequest (null, - testClassReference, methodName, bpLineName, - EventRequest.SUSPEND_NONE, property1); - - try { - log2("......eventRequest1.addThreadFilter(thread1);"); - log2(" no Exception expected"); - ((BreakpointRequest)eventRequest1).addThreadFilter(thread1); - log2(" no Exception"); - } catch ( Exception e ) { - log3("ERROR: Exception : " + e); - testExitCode = FAILED; - } - - break; - - case 1: - eventRequest2 = setting2BreakpointRequest (null, - testClassReference, methodName, bpLineName, - EventRequest.SUSPEND_NONE, property2); - - try { - log2("......eventRequest2.addThreadFilter(thread1);"); - log2(" no Exception expected"); - ((BreakpointRequest)eventRequest2).addThreadFilter(thread1); - log2(" no Exception"); - } catch ( Exception e ) { - log3("ERROR: Exception : " + e); - testExitCode = FAILED; - } - break; - - case 2: - eventRequest3 = setting2BreakpointRequest (null, - testClassReference, methodName, bpLineName, - EventRequest.SUSPEND_NONE, property3); - - try { - log2("......eventRequest3.addThreadFilter(thread1);"); - log2(" no Exception expected"); - ((BreakpointRequest)eventRequest3).addThreadFilter(thread1); - log2(" no Exception"); - } catch ( Exception e ) { - log3("ERROR: Exception : " + e); - testExitCode = FAILED; - } - break; - - default: - throw new JDITestRuntimeException("** default case 2 **"); + thread1 = (ThreadReference) debuggeeClass.getValue( + debuggeeClass.fieldByName(thread1Name)); + + eventRequest1 = setting2BreakpointRequest(null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property1); + + try { + log2("......eventRequest1.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((BreakpointRequest) eventRequest1).addThreadFilter(thread1); + log2(" no Exception"); + } catch (Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + + break; + + case 1: + eventRequest2 = setting2BreakpointRequest(null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property2); + + try { + log2("......eventRequest2.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((BreakpointRequest) eventRequest2).addThreadFilter(thread1); + log2(" no Exception"); + } catch (Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + case 2: + eventRequest3 = setting2BreakpointRequest(null, + testClassReference, methodName, bpLineName, + EventRequest.SUSPEND_NONE, property3); + + try { + log2("......eventRequest3.addThreadFilter(thread1);"); + log2(" no Exception expected"); + ((BreakpointRequest) eventRequest3).addThreadFilter(thread1); + log2(" no Exception"); + } catch (Exception e) { + log3("ERROR: Exception : " + e); + testExitCode = FAILED; + } + break; + + default: + throw new JDITestRuntimeException("** default case 2 **"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ } @@ -414,20 +408,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java index df1281910d3..bafe4d58b0c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BreakpointRequest/location/location001.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -377,20 +371,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java index d1a51c118c4..168b381cec8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ByteType/_itself_/bytetype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,19 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java index d3384264219..67304d1cb84 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/CharType/_itself_/chartype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,19 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java index bb7406294f8..522e623195d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/definedClasses/definedclasses001.java @@ -147,12 +147,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -296,7 +290,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -344,20 +338,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java index 9670dba51e5..f26063aad46 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassLoaderReference/visibleClasses/visibleclasses001.java @@ -160,12 +160,6 @@ private static void log3(String message) { "^short(\\[\\])+", "^long(\\[\\])+", "^float(\\[\\])+", "^double(\\[\\])+"}); - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -309,7 +303,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -390,21 +384,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java index 16537f75c98..7fee118f977 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassExclusionFilter/filter003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -388,20 +382,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java index 7faa656b6f3..26bd7702c59 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_rt/filter_rt002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -304,7 +298,7 @@ private void testRun() String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -395,20 +389,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java index 68864fc0e57..99ef62c4ebf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassPrepareRequest/addClassFilter_s/filter_s002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -304,7 +298,7 @@ private void testRun() String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -392,20 +386,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java index b96cfe74d68..b8cef0b3814 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod015.java @@ -350,19 +350,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java index 71917626d10..228dfc55253 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/DoubleType/_itself_/doubletype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,20 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java index dd484351ccf..e0fd2c82b7b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Event/request/request001.java @@ -168,12 +168,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - // Event #: // 0-6 : AccessWatchpoint, ModificationWatchpoint, Breakpoint, Exception, @@ -361,7 +355,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -632,20 +626,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java index d82d4037c56..b5b11c1da34 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventIterator/nextEvent/nextevent001.java @@ -168,12 +168,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - // Event #: // 0-6 : AccessWatchpoint, ModificationWatchpoint, Breakpoint, Exception, // MethodEntry, MethodExit, Step @@ -360,7 +354,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -620,20 +614,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java index 3b6a4f7f2e7..283268e7b19 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004.java @@ -145,12 +145,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -380,20 +374,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java index 64fad54af18..187a22a5795 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004.java @@ -140,12 +140,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -354,20 +348,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java index 7ae39143415..b328996820c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/addCountFilter/addcountfilter001.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -301,7 +295,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -349,7 +343,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -478,20 +472,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java index d14abb8477e..6b1a8b1e3a1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable001.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -343,7 +337,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -436,20 +430,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java index d407d9b45f4..5c2e62a328e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/disable/disable002.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -343,7 +337,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -434,20 +428,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java index 96c6ef3200c..737de0eed1a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable001.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -343,7 +337,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -432,20 +426,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java index fb70ef42655..9f71e51f117 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/enable/enable002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -346,7 +340,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -450,20 +444,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java index c2901199e37..175aecc7a1b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/getProperty/getproperty001.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -301,7 +295,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -349,7 +343,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -446,20 +440,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java index 9b033475cb2..5245ce003fb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/hashCode/hashcode001.java @@ -115,7 +115,7 @@ private static void execTest() { switch (i) { case 0: - ThreadReference thread = threadByName(methodName); + ThreadReference thread = debuggee.threadByNameOrThrow(methodName); display(".....setting up StepRequest"); eventRequest = eventRequestManager.createStepRequest @@ -224,18 +224,5 @@ private static Method methodByName(ReferenceType refType, String methodName) { return method; } - static private ThreadReference threadByName(String name) { - - List all = debuggee.VM().allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread IS NOT found : " + name); - } - } //--------------------------------------------------------- test specific classes diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java index d6dbbba2bec..9947e4e2f4b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/isEnabled/isenabled001.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -343,7 +337,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -440,20 +434,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java index 2f498c2e457..50b69647478 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/putProperty/putproperty001.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -301,7 +295,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -349,7 +343,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -451,20 +445,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java index 26571b466bc..f98935aa1bd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled001.java @@ -150,12 +150,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -298,7 +292,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -342,7 +336,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -439,20 +433,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java index f46aaa16f89..dd9e57d8838 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -346,7 +340,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -466,20 +460,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java index e20a786d1c9..802f90a39ba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -418,19 +412,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java index c95834f1f19..ef7c823339c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/setSuspendPolicy/setsuspendpolicy001.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -351,7 +345,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -482,20 +476,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java index 3a47f86d3e3..49d5e4a29c6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequest/suspendPolicy/suspendpolicy001.java @@ -150,12 +150,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -298,7 +292,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -346,7 +340,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest"); eventRequest1 = eventRManager.createStepRequest @@ -455,19 +449,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java index 6fe2265f99d..b47ba8671f2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/accessWatchpointRequests/accwtchpreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -431,19 +425,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java index e11bdfc6c94..03408b0b249 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/breakpointRequests/breakpreq002.java @@ -149,12 +149,6 @@ private static void log3(String message) { Location breakpLocation = null; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -424,20 +418,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java index b98603fc457..489a4224563 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classPrepareRequests/clsprepreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -424,20 +418,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java index 7ecc87b235e..2ac173491fb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/classUnloadRequests/clsunlreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java index 667958795e1..cca726ae16a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createAccessWatchpointRequest/craccwtchpreq003.java @@ -149,12 +149,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -381,20 +375,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java index 421eb141e56..89b741a8233 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createBreakpointRequest/crbreakpreq003.java @@ -149,12 +149,6 @@ private static void log3(String message) { Location breakpLocation = null; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -362,20 +356,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java index 6293bd2d897..36637f92ba2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassPrepareRequest/cpreg001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,19 +331,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java index a8a8d3eb9f9..4d2afde5363 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createClassUnloadRequest/cureg001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,20 +331,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java index b3a61e6a92e..86bf02f9e4f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq009.java @@ -147,12 +147,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -295,7 +289,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -361,20 +355,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java index baab21ecd73..9499f1da59a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createExceptionRequest/crexreq010.java @@ -148,12 +148,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -296,7 +290,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -352,20 +346,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java index ea0e995c3f9..b35521575dd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodEntryRequest/menreg001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,20 +331,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java index 1745d3c968f..6888a5a83be 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createMethodExitRequest/mexreg001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,19 +331,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java index 3a074620e87..96c7cd6df9e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createModificationWatchpointRequest/crmodwtchpreq003.java @@ -148,12 +148,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -296,7 +290,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -380,19 +374,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java index 2571289065d..e3a25488fd2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq002.java @@ -148,12 +148,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -296,7 +290,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -333,7 +327,7 @@ private void testRun() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part - thread = threadByName(threadName); + thread = debuggee.threadByNameOrThrow(threadName); if (StepRequest.STEP_MIN > StepRequest.STEP_LINE) { maxSize = StepRequest.STEP_MIN; @@ -448,20 +442,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java index 72ad344cad6..7ad725d5ab4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq003.java @@ -154,7 +154,7 @@ private int runThis(String argv[], PrintStream out) { //--------------------------------------------------------- mutable common methods private void execTest() { - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); /* BreakpointRequest bpRequest = setBreakpoint( mainThread, debuggeeClass, @@ -252,7 +252,7 @@ private void setAndCheckStepEvent ( BreakpointRequest bpRequest, exitCode = FAILED; } - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); StepRequest stepRequest = setStepRequest( thread, StepRequest.STEP_LINE, stepDepth, @@ -421,19 +421,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java index f2dba0bdd1c..d8e36c6e47d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq004.java @@ -155,7 +155,7 @@ private int runThis(String argv[], PrintStream out) { //--------------------------------------------------------- mutable common methods private void execTest() { - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = setBreakpoint( mainThread, debuggeeClass, @@ -247,7 +247,7 @@ private void setAndCheckStepEvent ( BreakpointRequest bpRequest, exitCode = FAILED; } - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); StepRequest stepRequest = setStepRequest( thread, StepRequest.STEP_LINE, stepDepth, @@ -418,19 +418,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java index c8dc5397924..24294f0c0b9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq005.java @@ -217,7 +217,7 @@ private StepRequest setStepRequest ( BreakpointRequest bpRequest, } display("Getting mirror of thread: " + threadName); - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); display("Getting ReferenceType of thread: " + threadName); ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); @@ -441,19 +441,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java index 2fdd39ab107..d7b0d1c0aff 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq006.java @@ -215,7 +215,7 @@ private StepRequest setStepRequest ( BreakpointRequest bpRequest, } display("Getting mirror of thread: " + threadName); - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); display("Getting ReferenceType of thread: " + threadName); ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); @@ -439,19 +439,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java index 7927dccddef..9706d1cb8b6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq007.java @@ -217,7 +217,7 @@ private StepRequest setStepRequest ( BreakpointRequest bpRequest, } display("Getting mirror of thread: " + threadName); - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); display("Getting ReferenceType of thread: " + threadName); ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); @@ -441,19 +441,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java index 317027a846d..22e492aa35d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq008.java @@ -217,7 +217,7 @@ private StepRequest setStepRequest ( BreakpointRequest bpRequest, } display("Getting mirror of thread: " + threadName); - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); display("Getting ReferenceType of thread: " + threadName); ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); @@ -441,19 +441,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java index fb89b818947..2f8e722dd5f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq009.java @@ -215,7 +215,7 @@ private StepRequest setStepRequest ( BreakpointRequest bpRequest, } display("Getting mirror of thread: " + threadName); - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); display("Getting ReferenceType of thread: " + threadName); ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); @@ -439,19 +439,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java index c615b430a2c..627f0f0a5bb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createStepRequest/crstepreq010.java @@ -219,7 +219,7 @@ private StepRequest setStepRequest ( BreakpointRequest bpRequest, } display("Getting mirror of thread: " + threadName); - ThreadReference thread = threadByName(threadName); + ThreadReference thread = debuggee.threadByNameOrThrow(threadName); display("Getting ReferenceType of thread: " + threadName); ReferenceType debuggeeThread = debuggee.classByName(debuggeeThreadName); @@ -443,19 +443,6 @@ private void getEventSet() { } } - - private ThreadReference threadByName(String name) throws Failure{ - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - while (li.hasNext()) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new Failure("Thread with searching for name is not found: " + name); - } - private ReferenceType waitForDebuggeeClassPrepared () { display("Creating request for ClassPrepareEvent for debuggee."); ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java index 4ce208821dc..2acb1847858 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadDeathRequest/tdreg001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,20 +331,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java index 8c081f2bb22..4da1bd4e926 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createThreadStartRequest/tsreg001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,20 +331,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java index 1885e595acb..cf0b159dfcd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/createVMDeathRequest/vmdreg001.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -349,20 +343,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java index 5c9275617d4..b381b0079c3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteAllBreakpoints/delallbreakp002.java @@ -148,12 +148,6 @@ private static void log3(String message) { Location breakpLocation = null; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -296,7 +290,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -348,20 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java index fdd49ac9c3b..1ed1c56a2e0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequest/delevtreq002.java @@ -154,12 +154,6 @@ private static void log3(String message) { Location breakpLocation = null; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -433,20 +427,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java index 43e423d399e..746e80c7710 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/deleteEventRequests/delevtreqs002.java @@ -152,12 +152,6 @@ private static void log3(String message) { Location breakpLocation = null; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -502,20 +496,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java index 6c357c19091..7c999c53ef0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/exceptionRequests/excreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -424,20 +418,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java index 35b1195ae56..1ba95aceb8f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodEntryRequests/methentreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java index e59abe10da3..62d7e8a97e7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/methodExitRequests/methexitreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java index 78e73d7afa9..952288b029b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/modificationWatchpointRequests/modwtchpreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -431,20 +425,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java index 1f8467aad73..2b57e4ab49e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/stepRequests/stepreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -426,20 +420,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java index de42ac78bb4..6f577993329 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java index 86edbcaee19..017c18292d4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadStartRequests/thrstartreq002.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java index b6fce04d6ac..b5be0dd7236 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/vmDeathRequests/vmdeathreq001.java @@ -146,12 +146,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java index a336bf093b9..089f2212e94 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator001.java @@ -144,12 +144,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods @@ -320,7 +314,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -367,20 +361,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java index 1a4c36be045..ca5dd54ba15 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator002.java @@ -150,12 +150,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -309,7 +303,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -431,20 +425,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java index 7dd013c5bb1..862b631773b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis(String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() throws JDITestRuntimeException, Exception { String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -392,19 +386,6 @@ private void testRun() throws JDITestRuntimeException, Exception { return; } - private ThreadReference threadByName(String name) throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext();) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java index ac9476da7c1..b9119773aa1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/eventIterator/eventiterator004.java @@ -138,12 +138,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - // Event #: // 0-6 : AccessWatchpoint, ModificationWatchpoint, Breakpoint, Exception, // MethodEntry, MethodExit, Step @@ -330,7 +324,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -363,20 +357,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java index 808c6a0c8c8..dea420743c4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume002.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -313,7 +307,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -510,20 +504,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java index 45e470f5359..422e2465f05 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume003.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -313,7 +307,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -511,20 +505,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java index 4ebfb3ff30f..394573d207e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume004.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -306,7 +300,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -504,20 +498,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java index 11b0ab2561b..b57abbf7d2c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume005.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -306,7 +300,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -504,20 +498,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java index 50df1acfedb..6e7f282453c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume006.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -306,7 +300,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -502,20 +496,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java index cc0a3e4b256..ce4ebbcb7fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume007.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -306,7 +300,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -501,20 +495,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java index 8e6aa77a4e5..973bc52ac61 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume010.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -306,7 +300,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -499,20 +493,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java index 4bbee554d30..12bf8340405 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume011.java @@ -142,12 +142,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -307,7 +301,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -344,20 +338,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java index 01aa01ccf23..fcb52349bc2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume012.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -308,7 +302,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -345,20 +339,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java index 502b9da8cf5..c1a9f385004 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/resume/resume013.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -308,7 +302,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -344,20 +338,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java index 0d075163fd1..fe02854a102 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy001.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -492,20 +486,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java index cdff2ce99db..2f3f9df0a5a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -312,7 +306,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -487,20 +481,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java index 6988f530043..a75cf23b44a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy003.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -318,7 +312,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -494,20 +488,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java index 56719aeac70..e91c8551ea3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy004.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -312,7 +306,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -489,20 +483,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java index 9009f7402ac..8331bb93bf6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy005.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -312,7 +306,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -489,20 +483,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java index 6d9a450317b..d4d483de7c1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy006.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -487,20 +481,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java index da114123eac..66b345dec97 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy007.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -486,20 +480,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java index 8c3788b4d3f..8fa8e8b6985 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy008.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -463,20 +457,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java index 878c35b9563..1b2c058213b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -463,20 +457,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java index ee733d43817..321653ff4e5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy010.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -310,7 +304,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -418,20 +412,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java index a6e48edc65a..34d59838441 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy011.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -319,7 +313,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -365,20 +359,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java index 18e34f6ece8..f79f84a0dcb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy012.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -319,7 +313,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -365,20 +359,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java index 33dfb24e9e4..cf13951176c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy013.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -319,7 +313,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -365,20 +359,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java index 716d3c21c0d..e36917567fe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy014.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -320,7 +314,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -368,20 +362,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java index e3cafdf6357..778c01aa644 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy015.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -320,7 +314,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -368,20 +362,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java index e8f7c03581a..6de316fc1e5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy016.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -320,7 +314,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -368,19 +362,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java index c2bf7bfae31..211527fea66 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy017.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - int policyToCheck = 0; //------------------------------------------------------ methods @@ -320,7 +314,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, bPointMethod, lineForComm, "zero"); @@ -370,20 +364,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java index 42f24fb625f..73671ae9afa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassExclusionFilter/filter002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -392,20 +386,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java index ad90bc53d25..9c8b6742293 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_rt/filter_rt002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -394,20 +388,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java index bf5a544fa43..1e0fd47ed46 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addClassFilter_s/filter_s002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -393,20 +387,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java index 2dc18e5cb47..d9f5f86c1a8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -310,7 +304,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -415,20 +409,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java index 66dd7161aa3..15b80dea916 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter003.java @@ -150,12 +150,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -298,7 +292,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -382,20 +376,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java index eb710144d51..383cb2a9a67 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter002.java @@ -157,12 +157,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -305,7 +299,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -402,20 +396,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java index 4f1e046660d..e661f7b292b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/addThreadFilter/threadfilter003.java @@ -157,12 +157,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -305,7 +299,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -407,20 +401,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java index 72a4e40d243..bed4712c333 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/exception/exception001.java @@ -149,12 +149,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -382,20 +376,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java index da7c5022533..c8d5b0b7e2c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyCaught/notifycaught001.java @@ -147,12 +147,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -295,7 +289,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -371,20 +365,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java index 8f02f3fa4dd..3e6cf1a1feb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ExceptionRequest/notifyUncaught/notifyuncaught001.java @@ -147,12 +147,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -295,7 +289,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -371,20 +365,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java index 61a10039052..ca1cfbbe939 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/FloatType/_itself_/floattype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,20 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java index 2b7d8255ab0..c2ab6e0fd91 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/IntegerType/_itself_/integertype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,20 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java index 79c2f06c072..b3b3cd0cc61 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocatableEvent/thread/thread001.java @@ -158,12 +158,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -307,7 +301,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -542,20 +536,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java index 871ace70912..d45dc04c964 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LongType/_itself_/longtype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,20 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java index d1946a1337b..171e075047a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassExclusionFilter/filter002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -389,20 +383,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java index 9cbb56bc192..6297fc7b8bf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_rt/filter_rt002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -394,20 +388,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java index 1d2225b0f3d..4173f206010 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addClassFilter_s/filter_s002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -389,20 +383,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java index 4a6f4893a1b..75e8c58f1a0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -310,7 +304,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -420,20 +414,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java index 0a6936b397b..ec40131c95e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addInstanceFilter/instancefilter003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -387,20 +381,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java index eafa4730ddf..c4b7efab8fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter002.java @@ -157,12 +157,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -305,7 +299,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -402,20 +396,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java index afb5cd8d24a..2915c989a7d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodEntryRequest/addThreadFilter/threadfilter003.java @@ -157,12 +157,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -305,7 +299,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -405,20 +399,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java index 2ce1141a70e..405bb9a7dd9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassExclusionFilter/filter002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -389,20 +383,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java index 2d66add566d..4d860872554 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -394,20 +388,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java index ca18acbdec8..7b5e471a8f4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_s/filter_s002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -389,20 +383,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java index 2701981c4fc..a2b87ad3f9e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -310,7 +304,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -420,20 +414,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java index 6c2ad1daf54..2c00a9e0ff7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addInstanceFilter/instancefilter003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -387,20 +381,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java index 42ed26ca153..c911fb0eb56 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter002.java @@ -156,12 +156,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -304,7 +298,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -402,20 +396,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java index 37b9c31a1eb..ebcb3c4a784 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/MethodExitRequest/addThreadFilter/threadfilter003.java @@ -156,12 +156,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -304,7 +298,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -408,20 +402,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java index 6afdcd14960..b3e0181047e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001.java @@ -150,12 +150,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -304,7 +298,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -379,20 +373,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java index 4818218c025..56f2999c70f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/disableCollection/disablecollection002.java @@ -167,12 +167,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -316,7 +310,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -383,20 +377,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java index 901b70a6300..325a67397bf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PathSearchingVirtualMachine/classPath/classpath001.java @@ -149,12 +149,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -376,20 +370,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java index 6954b2d390e..89959a84fa5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/PrimitiveType/_itself_/primitivetype001.java @@ -142,12 +142,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -291,7 +285,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -344,20 +338,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java index 8299aaf7eb9..5aab6d1e139 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classLoader/classloader001.java @@ -134,12 +134,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -284,7 +278,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -359,20 +353,6 @@ private void checkClassLoader (String testedClassName, boolean nullExpected) { } } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java index a8bbadaf602..70b3e9d0ddb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue001.java @@ -135,12 +135,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -285,7 +279,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -368,20 +362,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java index eb701855946..c0ac6f588b2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue002.java @@ -134,12 +134,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -284,7 +278,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -369,20 +363,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java index 1130fbc2f30..e05eea7a94d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValue/getvalue003.java @@ -134,12 +134,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -284,7 +278,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -369,20 +363,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java index 28d40c3d1f5..16e57b679db 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/getValues/getvalues001.java @@ -138,12 +138,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -288,7 +282,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -396,20 +390,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java index 7153e138fb4..cf7cfcc8270 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001.java @@ -122,12 +122,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -272,7 +266,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -445,20 +439,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java index f4a8ebbd44d..ac64893f8bb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -463,20 +457,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java index 16ce817ed5d..a2a0acb9191 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic002.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -374,20 +368,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java index bea80620850..831d3d982d5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes001.java @@ -128,12 +128,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -278,7 +272,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -384,20 +378,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java index 559fc020922..12db4ab322b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/nestedTypes/nestedtypes002.java @@ -128,12 +128,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -401,20 +395,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java index 6cdd5bd4455..47830a1b7ac 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ShortType/_itself_/shorttype001.java @@ -143,12 +143,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -348,20 +342,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java index 5e44ed731bf..231e44f7a3c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassExclusionFilter/filter002.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -301,7 +295,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -337,7 +331,7 @@ private void testRun() switch (i) { case 0: - ThreadReference thread1 = threadByName("main"); + ThreadReference thread1 = debuggee.threadByNameOrThrow("main"); eventRequest1 = setting23StepRequest(thread1, testedClassName1, EventRequest.SUSPEND_NONE, property1); @@ -388,20 +382,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java index 212abb2fbd5..a2f35183295 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_rt/filter_rt002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -348,7 +342,7 @@ private void testRun() testClassReference = (ReferenceType) vm.classesByName(testedClassName).get(0); - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); eventRequest1 = setting21StepRequest(thread1, testClassReference, EventRequest.SUSPEND_NONE, property1); @@ -399,20 +393,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java index 2b179b531f0..2eeb2852b4e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addClassFilter_s/filter_s002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -340,7 +334,7 @@ private void testRun() switch (i) { case 0: - ThreadReference thread1 = threadByName("thread1"); + ThreadReference thread1 = debuggee.threadByNameOrThrow("thread1"); eventRequest1 = setting23StepRequest(thread1, testedClassName1, EventRequest.SUSPEND_NONE, property1); @@ -391,20 +385,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java index e486da70739..c48d2c700b4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter002.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -310,7 +304,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -419,20 +413,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java index 0e4b3eb7b34..f12c5ae7ff3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/addInstanceFilter/instancefilter003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -386,20 +380,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java index 38eaf7aff0f..fbeb350ef96 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth001.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -339,7 +333,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest with depth StepRequest.STEP_INTO"); eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, @@ -366,20 +360,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java index 967e47982cb..adc2bd80c42 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth002.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -339,7 +333,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest with depth StepRequest.STEP_OVER"); eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, @@ -366,20 +360,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java index 6c47720eaa8..8d848790707 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/depth/depth003.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -339,7 +333,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest with depth StepRequest.STEP_OUT"); eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, @@ -366,20 +360,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java index 3485153b8f5..fc7e105367d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size001.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -339,7 +333,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest with size StepRequest.STEP_MIN"); eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_MIN, @@ -366,20 +360,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java index 72ea53da199..a8ed1a0ccd1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/size/size002.java @@ -151,12 +151,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -299,7 +293,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -339,7 +333,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest with size StepRequest.STEP_LINE"); eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_LINE, @@ -366,20 +360,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java index d70f1a748d8..f99cd7db856 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/StepRequest/thread/thread001.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -340,7 +334,7 @@ private void testRun() switch (i) { case 0: - thread1 = threadByName(threadName1); + thread1 = debuggee.threadByNameOrThrow(threadName1); log2("......setting up StepRequest with size StepRequest.STEP_MIN"); eventRequest1 = setting24StepRequest(thread1, StepRequest.STEP_MIN, @@ -367,20 +361,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java index 8b7557b30d6..72acf1999fc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter001.java @@ -148,12 +148,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -384,20 +378,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java index d86de05f35c..4e54e439d82 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter002.java @@ -145,12 +145,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -294,7 +288,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -380,20 +374,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java index 28550d18b21..811486a427e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter003.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -308,7 +302,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -399,20 +393,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java index ae742b7d7ec..67a47387eb2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadDeathRequest/addThreadFilter/addthreadfilter005.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -307,7 +301,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -411,20 +405,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java index f35bf61ae83..db5ef413aba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes001.java @@ -162,12 +162,6 @@ private static void log3(String message) { BreakpointRequest breakpointRequest; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -312,7 +306,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -360,7 +354,7 @@ private void testRun() } String thread2Name = "thread2"; - ThreadReference thread2Ref = threadByName(thread2Name); + ThreadReference thread2Ref = debuggee.threadByNameOrThrow(thread2Name); String poppedMethod = "poppedMethod"; @@ -369,7 +363,7 @@ private void testRun() log2("......setting breakpoint in poppedMethod"); try { - breakpointRequest = settingBreakpoint(threadByName(thread2Name), + breakpointRequest = settingBreakpoint(debuggee.threadByNameOrThrow(thread2Name), debuggeeClass, poppedMethod, breakpointLine, "one"); } catch ( Exception e ) { @@ -428,20 +422,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java index 026a8775ca9..7272e11631c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes002.java @@ -157,12 +157,6 @@ private static void log3(String message) { BreakpointRequest breakpointRequest3; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -313,7 +307,7 @@ private void testRun() String lineForComm = "lineForComm"; log2("......setting BreakpointRequest (bpRequest) in main thread"); - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); log2("bpRequest.enable();"); @@ -329,10 +323,10 @@ private void testRun() breakpointForCommunication(); String thread2Name = "thread2"; - ThreadReference thread2Ref = threadByName(thread2Name); + ThreadReference thread2Ref = debuggee.threadByNameOrThrow(thread2Name); String thread3Name = "thread3"; - ThreadReference thread3Ref = threadByName(thread3Name); + ThreadReference thread3Ref = debuggee.threadByNameOrThrow(thread3Name); String poppedMethod = "poppedMethod"; String breakpointLine = "breakpointLine"; @@ -407,20 +401,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java index a2a625daa81..eca4f172956 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes003.java @@ -158,12 +158,6 @@ private static void log3(String message) { MethodEntryRequest meRequest3; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -313,7 +307,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference threadMainRef = threadByName("main"); + ThreadReference threadMainRef = debuggee.threadByNameOrThrow("main"); try { bpRequest = settingBreakpoint(threadMainRef, debuggeeClass, @@ -344,10 +338,10 @@ private void testRun() String thread2Name = "thread2"; - ThreadReference thread2Ref = threadByName(thread2Name); + ThreadReference thread2Ref = debuggee.threadByNameOrThrow(thread2Name); String thread3Name = "thread3"; - ThreadReference thread3Ref = threadByName(thread3Name); + ThreadReference thread3Ref = debuggee.threadByNameOrThrow(thread3Name); String poppedMethod = "poppedMethod"; String breakpointLine = "breakpointLine"; @@ -478,21 +472,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java index 469a5a870aa..184c89b027e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes004.java @@ -154,12 +154,6 @@ private static void log3(String message) { BreakpointRequest breakpointRequest2; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -309,7 +303,7 @@ private void testRun() String lineForComm = "lineForComm"; log2("......setting BreakpointRequest (bpRequest) in main thread"); - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); log2("bpRequest.enable();"); @@ -325,7 +319,7 @@ private void testRun() breakpointForCommunication(); String thread2Name = "thread2"; - ThreadReference thread2Ref = threadByName(thread2Name); + ThreadReference thread2Ref = debuggee.threadByNameOrThrow(thread2Name); StackFrame stackFrame = null; int var; @@ -418,20 +412,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java index cfc0e68b1dc..d8f5f71271b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/popFrames/popframes005.java @@ -158,12 +158,6 @@ private static void log3(String message) { BreakpointRequest breakpointRequest2; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -313,7 +307,7 @@ private void testRun() String lineForComm = "lineForComm"; log2("......setting BreakpointRequest (bpRequest) in main thread"); - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); log2("bpRequest.enable();"); @@ -329,7 +323,7 @@ private void testRun() breakpointForCommunication(); String thread2Name = "thread2"; - ThreadReference thread2Ref = threadByName(thread2Name); + ThreadReference thread2Ref = debuggee.threadByNameOrThrow(thread2Name); StackFrame stackFrame0 = null; StackFrame stackFrame1 = null; @@ -400,20 +394,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java index c4d593fd63b..f0d9002a9ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter001.java @@ -148,12 +148,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -297,7 +291,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -383,20 +377,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java index 268ea7d01f8..be78eb12c06 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java @@ -145,12 +145,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -295,7 +289,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -382,20 +376,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java index dd0710a7c75..8796a1b3ddb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter003.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -308,7 +302,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -399,20 +393,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java index 2dc413b36f0..1b1d849c98d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter005.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -406,20 +400,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java index d23a86ee2a0..a12d345f92a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath002.java @@ -134,12 +134,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -291,7 +285,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -330,19 +324,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java index c6fb72983ff..690b9c93ae3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VMDeathEvent/_itself_/vmdeath003.java @@ -140,12 +140,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -296,7 +290,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -333,20 +327,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java index 136c537363f..e65ee66bd2b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/allClasses/allclasses001.java @@ -140,12 +140,6 @@ private static void log3(String message) { static final int returnCode0 = 0; static final int returnCode1 = 1; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -290,7 +284,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -448,20 +442,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java index 15b6167ceb7..2e3ae8008a1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canAddMethod/canaddmethod001.java @@ -130,12 +130,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -321,20 +315,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java index f198faa7846..da18818db07 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canPopFrames/canpopframes001.java @@ -130,12 +130,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -321,20 +315,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java index c1ecbd95cad..d12656c923d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRedefineClasses/canredefineclasses001.java @@ -130,12 +130,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -321,20 +315,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java index 961901a7857..29369343c06 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canRequestVMDeathEvent/canreqvmdev001.java @@ -130,12 +130,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -321,20 +315,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java index f8773004333..0775dd1f2d7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUnrestrictedlyRedefineClasses/curc001.java @@ -130,12 +130,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -321,20 +315,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java index 3e73b7f58bc..e2bc38ee317 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canUseInstanceFilters/canusefilters001.java @@ -130,12 +130,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -280,7 +274,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -321,20 +315,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java index 9ec3c9afc84..4c7cce74ba2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldAccess/canwatchaccess001.java @@ -141,12 +141,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -291,7 +285,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -332,20 +326,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java index d0d6fe245d9..6f8b41710dd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/canWatchFieldModification/canwatchmod001.java @@ -142,12 +142,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -292,7 +286,7 @@ private void testRun() BreakpointRequest bpRequest; try { - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); } catch ( Exception e ) { @@ -333,20 +327,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java index b389b18d4fa..70094bb5954 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses001.java @@ -164,12 +164,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -318,7 +312,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -359,7 +353,7 @@ private void testRun() case 0: List classes = vm.classesByName(bpClassName); bpClass = (ReferenceType) classes.get(0); - bpRequest2 = settingBreakpoint(threadByName("main"), + bpRequest2 = settingBreakpoint(debuggee.threadByNameOrThrow("main"), bpClass, bpMethodName, bpLineName, "one"); bpRequest2.enable(); @@ -384,7 +378,7 @@ private void testRun() case 1: - bpRequest3 = settingBreakpoint(threadByName("main"), + bpRequest3 = settingBreakpoint(debuggee.threadByNameOrThrow("main"), bpClass, bpMethodName, bpLineName, "one"); @@ -416,20 +410,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java index 4997fc38879..0e4f073f438 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/VoidType/_itself_/voidtype001.java @@ -142,12 +142,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -291,7 +285,7 @@ private void testRun() String lineForComm = "lineForComm"; BreakpointRequest bpRequest; - bpRequest = settingBreakpoint(threadByName("main"), + bpRequest = settingBreakpoint(debuggee.threadByNameOrThrow("main"), debuggeeClass, bPointMethod, lineForComm, "zero"); bpRequest.enable(); @@ -350,20 +344,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java index 27de4de00fd..2237832dff9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter003.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -397,20 +391,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java index c405dfbac72..2fb77ace017 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassExclusionFilter/filter004.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -397,20 +391,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java index 463bdc5768e..3b898363894 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt003.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -396,20 +390,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java index a633bd7a6ec..e69348f86dc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_rt/filter_rt004.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -396,20 +390,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java index cf64ce2b7c2..52bf38e1650 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s003.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -396,20 +390,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java index 24f96c2c323..30bae5092ae 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addClassFilter_s/filter_s004.java @@ -155,12 +155,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -303,7 +297,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -396,20 +390,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java index 79c7e8e54b5..94d2149344b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter003.java @@ -156,12 +156,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -423,20 +417,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java index 4bd8dbf2016..f10273db3dc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter004.java @@ -156,12 +156,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -311,7 +305,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -423,20 +417,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java index fda553215d7..0fb515b01d3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter005.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -390,20 +384,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java index 4343ca0abb8..83fa96600d7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addInstanceFilter/instancefilter006.java @@ -152,12 +152,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -300,7 +294,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -390,20 +384,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java index 3320fc6b274..237d52da575 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter003.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -314,7 +308,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -413,20 +407,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java index 61d8894fd5a..1a8c570f759 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter004.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -314,7 +308,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -413,20 +407,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java index 7f6ad0d47ef..ae80e88d5d5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter005.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -314,7 +308,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -416,20 +410,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java index 498a27dff33..7a8d8f62db0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/addThreadFilter/addthreadfilter006.java @@ -159,12 +159,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -314,7 +308,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -416,20 +410,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java index 3746a3b4eb3..c3c3a61a8f0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field001.java @@ -153,12 +153,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -301,7 +295,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -369,20 +363,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java index 1e09ff899b8..66a61dfe847 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointRequest/field/field002.java @@ -154,12 +154,6 @@ private static void log3(String message) { static int testExitCode = PASSED; - class JDITestRuntimeException extends RuntimeException { - JDITestRuntimeException(String str) { - super("JDITestRuntimeException : " + str); - } - } - //------------------------------------------------------ methods private int runThis (String argv[], PrintStream out) { @@ -302,7 +296,7 @@ private void testRun() String bPointMethod = "methodForCommunication"; String lineForComm = "lineForComm"; - ThreadReference mainThread = threadByName("main"); + ThreadReference mainThread = debuggee.threadByNameOrThrow("main"); BreakpointRequest bpRequest = settingBreakpoint(mainThread, debuggeeClass, @@ -370,20 +364,6 @@ private void testRun() return; } - private ThreadReference threadByName(String name) - throws JDITestRuntimeException { - - List all = vm.allThreads(); - ListIterator li = all.listIterator(); - - for (; li.hasNext(); ) { - ThreadReference thread = (ThreadReference) li.next(); - if (thread.name().equals(name)) - return thread; - } - throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); - } - /* * private BreakpointRequest settingBreakpoint(ThreadReference, ReferenceType, * String, String, String) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java index c7f82af2261..214b7f19fc4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java @@ -48,6 +48,7 @@ * @see DebugeeProcess */ abstract public class Debugee extends DebugeeProcess { + /** * Mirror of the debugee VM. This must be initialized by every * particular non-abstract class extending Debugee class. @@ -240,6 +241,19 @@ public ThreadReference threadByName (String name) { return threads[index]; } + + public ThreadReference threadByNameOrThrow(String name) throws JDITestRuntimeException { + + List all = vm.allThreads(); + ListIterator li = all.listIterator(); + for (; li.hasNext(); ) { + ThreadReference thread = (ThreadReference) li.next(); + if (thread.name().equals(name)) + return thread; + } + throw new JDITestRuntimeException("** Thread IS NOT found ** : " + name); + } + // --------------------------------------------------- // /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDITestRuntimeException.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDITestRuntimeException.java new file mode 100644 index 00000000000..e7b1e3d595b --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDITestRuntimeException.java @@ -0,0 +1,7 @@ +package nsk.share.jdi; + +public class JDITestRuntimeException extends RuntimeException { + public JDITestRuntimeException(String str) { + super("JDITestRuntimeException : " + str); + } +} From 5b155f05e75efb18444fcc990a73625c75be3183 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 4 Dec 2019 11:30:32 +0100 Subject: [PATCH 29/32] 8235324: Dying objects are published from users of CollectedHeap::object_iterate Reviewed-by: pliden, eosterlund, sjohanss, rkennke --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 4 ++++ src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 3 +++ src/hotspot/share/gc/shared/collectedHeap.hpp | 3 +++ src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp | 5 +++++ src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp | 3 +++ src/hotspot/share/gc/z/zBarrier.cpp | 8 -------- src/hotspot/share/gc/z/zBarrier.hpp | 1 + src/hotspot/share/gc/z/zBarrier.inline.hpp | 14 ++++++++++++++ src/hotspot/share/gc/z/zCollectedHeap.cpp | 4 ++++ src/hotspot/share/gc/z/zCollectedHeap.hpp | 2 ++ src/hotspot/share/gc/z/zHeap.cpp | 4 ++++ src/hotspot/share/gc/z/zHeap.hpp | 1 + src/hotspot/share/memory/heapInspection.cpp | 4 ++++ src/hotspot/share/prims/jvmtiTagMap.cpp | 5 +++++ 14 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index c4f5aa34eba..b0acd88bc59 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2348,6 +2348,10 @@ void G1CollectedHeap::object_iterate(ObjectClosure* cl) { heap_region_iterate(&blk); } +void G1CollectedHeap::keep_alive(oop obj) { + G1BarrierSet::enqueue(obj); +} + void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { _hrm->iterate(cl); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 25b72115624..62d38434f6c 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1170,6 +1170,9 @@ class G1CollectedHeap : public CollectedHeap { // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl); + // Keep alive an object that was loaded with AS_NO_KEEPALIVE. + virtual void keep_alive(oop obj); + // Iterate over heap regions, in address order, terminating the // iteration early if the "do_heap_region" method returns "true". void heap_region_iterate(HeapRegionClosure* blk) const; diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 36693e530c4..aa5dba60e0a 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -387,6 +387,9 @@ class CollectedHeap : public CHeapObj { // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl) = 0; + // Keep alive an object that was loaded with AS_NO_KEEPALIVE. + virtual void keep_alive(oop obj) {} + // Returns the longest time (in ms) that has elapsed since the last // time that any part of the heap was examined by a garbage collection. virtual jlong millis_since_last_gc() = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 9ffcd6b257b..4b7b58d7ef6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1327,6 +1327,11 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) { } } +// Keep alive an object that was loaded with AS_NO_KEEPALIVE. +void ShenandoahHeap::keep_alive(oop obj) { + ShenandoahBarrierSet::barrier_set()->enqueue(obj); +} + void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const { for (size_t i = 0; i < num_regions(); i++) { ShenandoahHeapRegion* current = get_region(i); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index ca962d1aa0a..7272d8d728a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -560,6 +560,9 @@ class ShenandoahHeap : public CollectedHeap { // Used for native heap walkers: heap dumpers, mostly void object_iterate(ObjectClosure* cl); + // Keep alive an object that was loaded with AS_NO_KEEPALIVE. + void keep_alive(oop obj); + // Used by RMI jlong millis_since_last_gc(); diff --git a/src/hotspot/share/gc/z/zBarrier.cpp b/src/hotspot/share/gc/z/zBarrier.cpp index 494828c8bf5..008cb59f233 100644 --- a/src/hotspot/share/gc/z/zBarrier.cpp +++ b/src/hotspot/share/gc/z/zBarrier.cpp @@ -31,14 +31,6 @@ #include "runtime/safepoint.hpp" #include "utilities/debug.hpp" -bool ZBarrier::during_mark() { - return ZGlobalPhase == ZPhaseMark; -} - -bool ZBarrier::during_relocate() { - return ZGlobalPhase == ZPhaseRelocate; -} - template bool ZBarrier::should_mark_through(uintptr_t addr) { // Finalizable marked oops can still exists on the heap after marking diff --git a/src/hotspot/share/gc/z/zBarrier.hpp b/src/hotspot/share/gc/z/zBarrier.hpp index 913ea6f9db4..b1387c00b7d 100644 --- a/src/hotspot/share/gc/z/zBarrier.hpp +++ b/src/hotspot/share/gc/z/zBarrier.hpp @@ -105,6 +105,7 @@ class ZBarrier : public AllStatic { static void keep_alive_barrier_on_weak_oop_field(volatile oop* p); static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p); static void keep_alive_barrier_on_phantom_root_oop_field(oop* p); + static void keep_alive_barrier_on_oop(oop o); // Mark barrier static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable); diff --git a/src/hotspot/share/gc/z/zBarrier.inline.hpp b/src/hotspot/share/gc/z/zBarrier.inline.hpp index 13459e234ea..283c1ef5246 100644 --- a/src/hotspot/share/gc/z/zBarrier.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp @@ -144,6 +144,14 @@ inline bool ZBarrier::is_weak_good_or_null_fast_path(uintptr_t addr) { return ZAddress::is_weak_good_or_null(addr); } +inline bool ZBarrier::during_mark() { + return ZGlobalPhase == ZPhaseMark; +} + +inline bool ZBarrier::during_relocate() { + return ZGlobalPhase == ZPhaseRelocate; +} + // // Load barrier // @@ -291,6 +299,12 @@ inline void ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(oop* p) { root_barrier(p, o); } +inline void ZBarrier::keep_alive_barrier_on_oop(oop o) { + if (during_mark()) { + barrier(NULL, o); + } +} + // // Mark barrier // diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 5652ff61d19..13fb90d191c 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -247,6 +247,10 @@ void ZCollectedHeap::object_iterate(ObjectClosure* cl) { _heap.object_iterate(cl, true /* visit_weaks */); } +void ZCollectedHeap::keep_alive(oop obj) { + _heap.keep_alive(obj); +} + void ZCollectedHeap::register_nmethod(nmethod* nm) { ZNMethod::register_nmethod(nm); } diff --git a/src/hotspot/share/gc/z/zCollectedHeap.hpp b/src/hotspot/share/gc/z/zCollectedHeap.hpp index 1910f03e1e5..1a96a0c11e4 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.hpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp @@ -99,6 +99,8 @@ class ZCollectedHeap : public CollectedHeap { virtual void object_iterate(ObjectClosure* cl); + virtual void keep_alive(oop obj); + virtual void register_nmethod(nmethod* nm); virtual void unregister_nmethod(nmethod* nm); virtual void flush_nmethod(nmethod* nm); diff --git a/src/hotspot/share/gc/z/zHeap.cpp b/src/hotspot/share/gc/z/zHeap.cpp index bb10f7066b4..8ed661478d2 100644 --- a/src/hotspot/share/gc/z/zHeap.cpp +++ b/src/hotspot/share/gc/z/zHeap.cpp @@ -322,6 +322,10 @@ bool ZHeap::mark_end() { return true; } +void ZHeap::keep_alive(oop obj) { + ZBarrier::keep_alive_barrier_on_oop(obj); +} + void ZHeap::set_soft_reference_policy(bool clear) { _reference_processor.set_soft_reference_policy(clear); } diff --git a/src/hotspot/share/gc/z/zHeap.hpp b/src/hotspot/share/gc/z/zHeap.hpp index b45f1ddc788..0b91ef7d9fa 100644 --- a/src/hotspot/share/gc/z/zHeap.hpp +++ b/src/hotspot/share/gc/z/zHeap.hpp @@ -137,6 +137,7 @@ class ZHeap { void mark(bool initial); void mark_flush_and_free(Thread* thread); bool mark_end(); + void keep_alive(oop obj); // Relocation set void select_relocation_set(); diff --git a/src/hotspot/share/memory/heapInspection.cpp b/src/hotspot/share/memory/heapInspection.cpp index 3d72ca98223..a192e0bedc5 100644 --- a/src/hotspot/share/memory/heapInspection.cpp +++ b/src/hotspot/share/memory/heapInspection.cpp @@ -778,6 +778,10 @@ class FindInstanceClosure : public ObjectClosure { void do_object(oop obj) { if (obj->is_a(_klass)) { + // obj was read with AS_NO_KEEPALIVE, or equivalent. + // The object needs to be kept alive when it is published. + Universe::heap()->keep_alive(obj); + _result->append(obj); } } diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index abd4f8e2e3c..48f9f8a149e 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -483,6 +483,11 @@ JvmtiTagMap::~JvmtiTagMap() { // is returned. Otherwise an new entry is allocated. JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) { assert(Thread::current()->is_VM_thread() || is_locked(), "checking"); + + // ref was read with AS_NO_KEEPALIVE, or equivalent. + // The object needs to be kept alive when it is published. + Universe::heap()->keep_alive(ref); + JvmtiTagHashmapEntry* entry; if (_free_entries == NULL) { entry = new JvmtiTagHashmapEntry(ref, tag); From c198b4da32389a398c5cbe4a5ef3493ac8ffddcd Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 9 Dec 2019 15:28:46 +0100 Subject: [PATCH 30/32] 8234508: VM_HeapWalkOperation::iterate_over_object reads non-strong fields with an on-strong load barrier Reviewed-by: pliden, eosterlund --- src/hotspot/share/prims/jvmtiTagMap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index 48f9f8a149e..cc5469857d5 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -2963,7 +2963,7 @@ inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { ClassFieldDescriptor* field = field_map->field_at(i); char type = field->field_type(); if (!is_primitive_field_type(type)) { - oop fld_o = o->obj_field(field->field_offset()); + oop fld_o = o->obj_field_access(field->field_offset()); // ignore any objects that aren't visible to profiler if (fld_o != NULL) { assert(Universe::heap()->is_in(fld_o), "unsafe code should not " From 9ac2f8b6543b99ff361501361bcbac55c7579485 Mon Sep 17 00:00:00 2001 From: Henry Jen Date: Tue, 10 Dec 2019 00:36:30 +0000 Subject: [PATCH 31/32] 8234542: code removal of Pack200 Tools and API Reviewed-by: alanb, mchung, erikj --- make/autoconf/compare.sh.in | 1 - make/common/Modules.gmk | 2 - make/launcher/Launcher-jdk.pack.gmk | 102 - make/lib/Lib-jdk.pack.gmk | 53 - make/nashorn/element-list | 1 - make/scripts/compare.sh | 25 - make/scripts/compare_exceptions.sh.incl | 2 - .../java/util/jar/pack/AdaptiveCoding.java | 298 - .../com/sun/java/util/jar/pack/Attribute.java | 1699 ------ .../sun/java/util/jar/pack/BandStructure.java | 2762 --------- .../sun/java/util/jar/pack/ClassReader.java | 619 -- .../sun/java/util/jar/pack/ClassWriter.java | 317 - .../com/sun/java/util/jar/pack/Code.java | 398 -- .../com/sun/java/util/jar/pack/Coding.java | 906 --- .../sun/java/util/jar/pack/CodingChooser.java | 1489 ----- .../sun/java/util/jar/pack/CodingMethod.java | 43 - .../sun/java/util/jar/pack/ConstantPool.java | 1658 ------ .../com/sun/java/util/jar/pack/Constants.java | 515 -- .../com/sun/java/util/jar/pack/Driver.java | 750 --- .../java/util/jar/pack/DriverResource.java | 136 - .../java/util/jar/pack/DriverResource_ja.java | 136 - .../util/jar/pack/DriverResource_zh_CN.java | 136 - .../com/sun/java/util/jar/pack/FixedList.java | 174 - .../com/sun/java/util/jar/pack/Fixups.java | 570 -- .../com/sun/java/util/jar/pack/Histogram.java | 818 --- .../sun/java/util/jar/pack/Instruction.java | 689 --- .../sun/java/util/jar/pack/NativeUnpack.java | 332 -- .../com/sun/java/util/jar/pack/Package.java | 1377 ----- .../sun/java/util/jar/pack/PackageReader.java | 2376 -------- .../sun/java/util/jar/pack/PackageWriter.java | 1743 ------ .../sun/java/util/jar/pack/PackerImpl.java | 611 -- .../java/util/jar/pack/PopulationCoding.java | 500 -- .../com/sun/java/util/jar/pack/PropMap.java | 332 -- .../com/sun/java/util/jar/pack/TLGlobals.java | 125 - .../sun/java/util/jar/pack/UnpackerImpl.java | 263 - .../com/sun/java/util/jar/pack/Utils.java | 320 - .../java/util/jar/pack/intrinsic.properties | 48 - .../sun/java/util/jar/pack/package-info.java | 101 - .../share/classes/java/util/jar/Pack200.java | 733 --- .../sun/tools/jar/GNUStyleOptions.java | 6 - .../share/classes/sun/tools/jar/Main.java | 33 +- .../sun/tools/jar/resources/jar.properties | 2 - src/jdk.pack/share/classes/module-info.java | 42 - src/jdk.pack/share/man/pack200.1 | 357 -- src/jdk.pack/share/man/unpack200.1 | 126 - .../share/native/common-unpack/bands.cpp | 486 -- .../share/native/common-unpack/bands.h | 481 -- .../share/native/common-unpack/bytes.cpp | 193 - .../share/native/common-unpack/bytes.h | 144 - .../share/native/common-unpack/coding.cpp | 989 ---- .../share/native/common-unpack/coding.h | 226 - .../share/native/common-unpack/constants.h | 497 -- .../share/native/common-unpack/defines.h | 178 - .../share/native/common-unpack/unpack.cpp | 5250 ----------------- .../share/native/common-unpack/unpack.h | 509 -- .../share/native/common-unpack/utils.cpp | 183 - .../share/native/common-unpack/utils.h | 67 - .../share/native/common-unpack/zip.cpp | 708 --- src/jdk.pack/share/native/common-unpack/zip.h | 118 - src/jdk.pack/share/native/libunpack/jni.cpp | 351 -- src/jdk.pack/share/native/unpack200/main.cpp | 469 -- .../unpack200/unpack200_proto.exe.manifest | 20 - .../nbproject/project.properties | 1 - test/jdk/ProblemList.txt | 9 - test/jdk/TEST.groups | 4 +- .../java/util/jar/Pack200/SecurityTest.java | 39 - test/jdk/tools/jar/DeprecateOptionN.java | 96 - test/jdk/tools/launcher/HelpFlagsTest.java | 2 - test/jdk/tools/launcher/VersionCheck.java | 7 +- test/jdk/tools/pack200/AttributeTests.java | 126 - test/jdk/tools/pack200/BandIntegrity.java | 62 - test/jdk/tools/pack200/CommandLineTests.java | 185 - test/jdk/tools/pack200/DeprecatePack200.java | 75 - test/jdk/tools/pack200/InstructionTests.java | 76 - test/jdk/tools/pack200/ModuleAttributes.java | 50 - test/jdk/tools/pack200/MultiRelease.java | 258 - test/jdk/tools/pack200/Pack200Props.java | 139 - test/jdk/tools/pack200/Pack200Test.java | 142 - test/jdk/tools/pack200/PackChecksum.java | 178 - test/jdk/tools/pack200/PackTestZip64.java | 160 - .../tools/pack200/PackTestZip64Manual.java | 33 - .../jdk/tools/pack200/PackageVersionTest.java | 156 - test/jdk/tools/pack200/RepackTest.java | 75 - test/jdk/tools/pack200/T7007157.java | 69 - test/jdk/tools/pack200/TestExceptions.java | 341 -- test/jdk/tools/pack200/TestNormal.java | 61 - test/jdk/tools/pack200/TimeStamp.java | 157 - .../jdk/tools/pack200/UnpackerMemoryTest.java | 87 - test/jdk/tools/pack200/Utils.java | 670 --- test/jdk/tools/pack200/badattr.jar | Bin 1493 -> 0 bytes .../pack200/pack200-verifier/data/README | 46 - .../pack200/pack200-verifier/data/golden.jar | Bin 448228 -> 0 bytes .../pack200/pack200-verifier/make/build.xml | 64 - .../sun/tools/pack/verify/ClassCompare.java | 160 - .../src/sun/tools/pack/verify/Globals.java | 309 - .../sun/tools/pack/verify/JarFileCompare.java | 199 - .../src/sun/tools/pack/verify/Main.java | 171 - .../sun/tools/pack/verify/VerifyTreeSet.java | 46 - .../src/xmlkit/ClassReader.java | 1911 ------ .../src/xmlkit/CommandLineParser.java | 282 - .../src/xmlkit/TokenList.java | 447 -- .../pack200-verifier/src/xmlkit/XMLKit.java | 4328 -------------- test/jdk/tools/pack200/typeannos/Lambda.java | 59 - test/jdk/tools/pack200/typeannos/Readme.txt | 11 - .../tools/pack200/typeannos/TargetTypes.java | 227 - .../typeannos/TestTypeAnnotations.java | 46 - .../pack200/typeannos/TypeUseTarget.java | 62 - 107 files changed, 4 insertions(+), 46217 deletions(-) delete mode 100644 make/launcher/Launcher-jdk.pack.gmk delete mode 100644 make/lib/Lib-jdk.pack.gmk delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Coding.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/FixedList.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Fixups.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Histogram.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Instruction.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/PackageWriter.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/TLGlobals.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/Utils.java delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties delete mode 100644 src/java.base/share/classes/com/sun/java/util/jar/pack/package-info.java delete mode 100644 src/java.base/share/classes/java/util/jar/Pack200.java delete mode 100644 src/jdk.pack/share/classes/module-info.java delete mode 100644 src/jdk.pack/share/man/pack200.1 delete mode 100644 src/jdk.pack/share/man/unpack200.1 delete mode 100644 src/jdk.pack/share/native/common-unpack/bands.cpp delete mode 100644 src/jdk.pack/share/native/common-unpack/bands.h delete mode 100644 src/jdk.pack/share/native/common-unpack/bytes.cpp delete mode 100644 src/jdk.pack/share/native/common-unpack/bytes.h delete mode 100644 src/jdk.pack/share/native/common-unpack/coding.cpp delete mode 100644 src/jdk.pack/share/native/common-unpack/coding.h delete mode 100644 src/jdk.pack/share/native/common-unpack/constants.h delete mode 100644 src/jdk.pack/share/native/common-unpack/defines.h delete mode 100644 src/jdk.pack/share/native/common-unpack/unpack.cpp delete mode 100644 src/jdk.pack/share/native/common-unpack/unpack.h delete mode 100644 src/jdk.pack/share/native/common-unpack/utils.cpp delete mode 100644 src/jdk.pack/share/native/common-unpack/utils.h delete mode 100644 src/jdk.pack/share/native/common-unpack/zip.cpp delete mode 100644 src/jdk.pack/share/native/common-unpack/zip.h delete mode 100644 src/jdk.pack/share/native/libunpack/jni.cpp delete mode 100644 src/jdk.pack/share/native/unpack200/main.cpp delete mode 100644 src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest delete mode 100644 test/jdk/java/util/jar/Pack200/SecurityTest.java delete mode 100644 test/jdk/tools/jar/DeprecateOptionN.java delete mode 100644 test/jdk/tools/pack200/AttributeTests.java delete mode 100644 test/jdk/tools/pack200/BandIntegrity.java delete mode 100644 test/jdk/tools/pack200/CommandLineTests.java delete mode 100644 test/jdk/tools/pack200/DeprecatePack200.java delete mode 100644 test/jdk/tools/pack200/InstructionTests.java delete mode 100644 test/jdk/tools/pack200/ModuleAttributes.java delete mode 100644 test/jdk/tools/pack200/MultiRelease.java delete mode 100644 test/jdk/tools/pack200/Pack200Props.java delete mode 100644 test/jdk/tools/pack200/Pack200Test.java delete mode 100644 test/jdk/tools/pack200/PackChecksum.java delete mode 100644 test/jdk/tools/pack200/PackTestZip64.java delete mode 100644 test/jdk/tools/pack200/PackTestZip64Manual.java delete mode 100644 test/jdk/tools/pack200/PackageVersionTest.java delete mode 100644 test/jdk/tools/pack200/RepackTest.java delete mode 100644 test/jdk/tools/pack200/T7007157.java delete mode 100644 test/jdk/tools/pack200/TestExceptions.java delete mode 100644 test/jdk/tools/pack200/TestNormal.java delete mode 100644 test/jdk/tools/pack200/TimeStamp.java delete mode 100644 test/jdk/tools/pack200/UnpackerMemoryTest.java delete mode 100644 test/jdk/tools/pack200/Utils.java delete mode 100644 test/jdk/tools/pack200/badattr.jar delete mode 100644 test/jdk/tools/pack200/pack200-verifier/data/README delete mode 100644 test/jdk/tools/pack200/pack200-verifier/data/golden.jar delete mode 100644 test/jdk/tools/pack200/pack200-verifier/make/build.xml delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/xmlkit/TokenList.java delete mode 100644 test/jdk/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java delete mode 100644 test/jdk/tools/pack200/typeannos/Lambda.java delete mode 100644 test/jdk/tools/pack200/typeannos/Readme.txt delete mode 100644 test/jdk/tools/pack200/typeannos/TargetTypes.java delete mode 100644 test/jdk/tools/pack200/typeannos/TestTypeAnnotations.java delete mode 100644 test/jdk/tools/pack200/typeannos/TypeUseTarget.java diff --git a/make/autoconf/compare.sh.in b/make/autoconf/compare.sh.in index 6a51c346369..7df7ef507c8 100644 --- a/make/autoconf/compare.sh.in +++ b/make/autoconf/compare.sh.in @@ -67,7 +67,6 @@ export STRIP="@STRIP@ @STRIPFLAGS@" export TAR="@TAR@" export TEE="@TEE@" export UNIQ="@UNIQ@" -export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200" export UNARCHIVE="@UNZIP@ -q -o" export TOPDIR="@TOPDIR@" diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index 5833b6c8233..55fc6efb668 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -129,7 +129,6 @@ endif JRE_TOOL_MODULES += \ jdk.jdwp.agent \ jdk.incubator.jpackage \ - jdk.pack \ jdk.scripting.nashorn.shell \ # @@ -170,7 +169,6 @@ DOCS_MODULES += \ jdk.naming.dns \ jdk.naming.rmi \ jdk.net \ - jdk.pack \ jdk.rmic \ jdk.scripting.nashorn \ jdk.sctp \ diff --git a/make/launcher/Launcher-jdk.pack.gmk b/make/launcher/Launcher-jdk.pack.gmk deleted file mode 100644 index fd025064701..00000000000 --- a/make/launcher/Launcher-jdk.pack.gmk +++ /dev/null @@ -1,102 +0,0 @@ -# -# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -include LauncherCommon.gmk - -$(eval $(call SetupBuildLauncher, pack200, \ - MAIN_MODULE := java.base, \ - MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \ -)) - -################################################################################ -# The order of the object files on the link command line affects the size of the resulting -# binary (at least on linux) which causes the size to differ between old and new build. - -# Tell the compiler not to export any functions unless declared so in -# the source code. On Windows, this is the default and cannot be changed. -# On Mac, we have always exported all symbols, probably due to oversight -# and/or misunderstanding. To emulate this, don't hide any symbols -# by default. -# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063) -# Also provide an override for non-conformant libraries. -ifeq ($(TOOLCHAIN_TYPE), gcc) - CXXFLAGS_JDKEXE += -fvisibility=hidden - LDFLAGS_JDKEXE += -Wl,--exclude-libs,ALL -else ifeq ($(TOOLCHAIN_TYPE), clang) - ifeq ($(call isTargetOs, macosx), false) - CXXFLAGS_JDKEXE += -fvisibility=hidden - endif -else ifeq ($(TOOLCHAIN_TYPE), solstudio) - CXXFLAGS_JDKEXE += -xldscope=hidden -endif - -UNPACKEXE_SRC := $(TOPDIR)/src/jdk.pack/share/native/common-unpack \ - $(TOPDIR)/src/jdk.pack/share/native/unpack200 -UNPACKEXE_CFLAGS := -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava - -ifeq ($(USE_EXTERNAL_LIBZ), true) - UNPACKEXE_CFLAGS += -DSYSTEM_ZLIB - UNPACKEXE_LIBS := -lz -else - UNPACKEXE_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/libzip/zlib - UNPACKEXE_ZIPOBJS := $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zcrc32$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/deflate$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/trees$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zadler32$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/compress$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/zutil$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inflate$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/infback$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inftrees$(OBJ_SUFFIX) \ - $(SUPPORT_OUTPUTDIR)/native/java.base/libzip/inffast$(OBJ_SUFFIX) - -endif - -$(eval $(call SetupJdkExecutable, BUILD_UNPACKEXE, \ - NAME := unpack200, \ - SRC := $(UNPACKEXE_SRC), \ - TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ - OPTIMIZATION := LOW, \ - CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \ - CFLAGS_release := -DPRODUCT, \ - CFLAGS_linux := -fPIC, \ - CFLAGS_solaris := -KPIC, \ - CFLAGS_macosx := -fPIC, \ - DISABLED_WARNINGS_clang := format-nonliteral, \ - DISABLED_WARNINGS_solstudio := wunreachable, \ - LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe, \ - MANIFEST := $(TOPDIR)/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest, \ - MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \ - EXTRA_OBJECT_FILES := $(UNPACKEXE_ZIPOBJS) \ -)) - -TARGETS += $(BUILD_UNPACKEXE) - -################################################################################ diff --git a/make/lib/Lib-jdk.pack.gmk b/make/lib/Lib-jdk.pack.gmk deleted file mode 100644 index bc537fc9d2c..00000000000 --- a/make/lib/Lib-jdk.pack.gmk +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -include LibCommon.gmk - -################################################################################ - -$(eval $(call SetupJdkLibrary, BUILD_LIBUNPACK, \ - NAME := unpack, \ - EXTRA_SRC := common-unpack, \ - TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ - OPTIMIZATION := LOW, \ - CFLAGS := $(CXXFLAGS_JDKLIB) \ - -DNO_ZLIB -DUNPACK_JNI -DFULL, \ - CFLAGS_release := -DPRODUCT, \ - EXTRA_HEADER_DIRS := $(call GetJavaHeaderDir, java.base), \ - DISABLED_WARNINGS_gcc := implicit-fallthrough, \ - DISABLED_WARNINGS_clang := format-nonliteral, \ - DISABLED_WARNINGS_solstudio := wunreachable, \ - LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_windows := -map:$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpack.map -debug, \ - LIBS_unix := -ljvm $(LIBCXX) -ljava, \ - LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \ -)) - -$(BUILD_LIBUNPACK): $(call FindLib, java.base, java) - -TARGETS += $(BUILD_LIBUNPACK) - -################################################################################ diff --git a/make/nashorn/element-list b/make/nashorn/element-list index 4cfabf8fdf8..4405748b41e 100644 --- a/make/nashorn/element-list +++ b/make/nashorn/element-list @@ -260,7 +260,6 @@ module:jdk.naming.rmi module:jdk.net jdk.net jdk.nio -module:jdk.pack module:jdk.rmic module:jdk.scripting.nashorn jdk.nashorn.api.scripting diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index e20220d03ef..57c3489ceca 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -529,31 +529,6 @@ compare_zip_file() { (cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP) fi - # Find all archives inside and unzip them as well to compare the contents rather than - # the archives. pie.jar.pack.gz i app3.war is corrupt, skip it. - EXCEPTIONS="pie.jar.pack.gz jdk.pack" - for pack in $($FIND $THIS_UNZIPDIR \( -name "*.pack" -o -name "*.pack.gz" \) -a \ - ! -name pie.jar.pack.gz -a ! -name jdk.pack); do - ($UNPACK200 $pack $pack.jar) - # Filter out the unzipped archives from the diff below. - EXCEPTIONS="$EXCEPTIONS $pack $pack.jar" - done - for pack in $($FIND $OTHER_UNZIPDIR \( -name "*.pack" -o -name "*.pack.gz" \) -a \ - ! -name pie.jar.pack.gz -a ! -name jdk.pack); do - ($UNPACK200 $pack $pack.jar) - EXCEPTIONS="$EXCEPTIONS $pack $pack.jar" - done - for zip in $($FIND $THIS_UNZIPDIR -name "*.jar" -o -name "*.zip"); do - $MKDIR $zip.unzip - (cd $zip.unzip && $UNARCHIVE $zip) - EXCEPTIONS="$EXCEPTIONS $zip" - done - for zip in $($FIND $OTHER_UNZIPDIR -name "*.jar" -o -name "*.zip"); do - $MKDIR $zip.unzip - (cd $zip.unzip && $UNARCHIVE $zip) - EXCEPTIONS="$EXCEPTIONS $zip" - done - CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff # On solaris, there is no -q option. if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then diff --git a/make/scripts/compare_exceptions.sh.incl b/make/scripts/compare_exceptions.sh.incl index a2001056c3c..bcfeef34f4e 100644 --- a/make/scripts/compare_exceptions.sh.incl +++ b/make/scripts/compare_exceptions.sh.incl @@ -50,9 +50,7 @@ elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then SORT_SYMBOLS=" ./lib/libfontmanager.so ./lib/libjimage.so - ./lib/libunpack.so ./lib/server/libjvm.so - ./bin/unpack200 ./hotspot/gtest/server/libjvm.so " KNOWN_DIS_DIFF=" diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java deleted file mode 100644 index 776a170ec44..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/AdaptiveCoding.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Adaptive coding. - * See the section "Adaptive Encodings" in the Pack200 spec. - * @author John Rose - */ -class AdaptiveCoding implements CodingMethod { - CodingMethod headCoding; - int headLength; - CodingMethod tailCoding; - - public AdaptiveCoding(int headLength, CodingMethod headCoding, CodingMethod tailCoding) { - assert(isCodableLength(headLength)); - this.headLength = headLength; - this.headCoding = headCoding; - this.tailCoding = tailCoding; - } - - public void setHeadCoding(CodingMethod headCoding) { - this.headCoding = headCoding; - } - public void setHeadLength(int headLength) { - assert(isCodableLength(headLength)); - this.headLength = headLength; - } - public void setTailCoding(CodingMethod tailCoding) { - this.tailCoding = tailCoding; - } - - public boolean isTrivial() { - return headCoding == tailCoding; - } - - // CodingMethod methods. - public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException { - writeArray(this, out, a, start, end); - } - // writeArrayTo must be coded iteratively, not recursively: - private static void writeArray(AdaptiveCoding run, OutputStream out, int[] a, int start, int end) throws IOException { - for (;;) { - int mid = start+run.headLength; - assert(mid <= end); - run.headCoding.writeArrayTo(out, a, start, mid); - start = mid; - if (run.tailCoding instanceof AdaptiveCoding) { - run = (AdaptiveCoding) run.tailCoding; - continue; - } - break; - } - run.tailCoding.writeArrayTo(out, a, start, end); - } - - public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException { - readArray(this, in, a, start, end); - } - private static void readArray(AdaptiveCoding run, InputStream in, int[] a, int start, int end) throws IOException { - for (;;) { - int mid = start+run.headLength; - assert(mid <= end); - run.headCoding.readArrayFrom(in, a, start, mid); - start = mid; - if (run.tailCoding instanceof AdaptiveCoding) { - run = (AdaptiveCoding) run.tailCoding; - continue; - } - break; - } - run.tailCoding.readArrayFrom(in, a, start, end); - } - - public static final int KX_MIN = 0; - public static final int KX_MAX = 3; - public static final int KX_LG2BASE = 4; - public static final int KX_BASE = 16; - - public static final int KB_MIN = 0x00; - public static final int KB_MAX = 0xFF; - public static final int KB_OFFSET = 1; - public static final int KB_DEFAULT = 3; - - static int getKXOf(int K) { - for (int KX = KX_MIN; KX <= KX_MAX; KX++) { - if (((K - KB_OFFSET) & ~KB_MAX) == 0) - return KX; - K >>>= KX_LG2BASE; - } - return -1; - } - - static int getKBOf(int K) { - int KX = getKXOf(K); - if (KX < 0) return -1; - K >>>= (KX * KX_LG2BASE); - return K-1; - } - - static int decodeK(int KX, int KB) { - assert(KX_MIN <= KX && KX <= KX_MAX); - assert(KB_MIN <= KB && KB <= KB_MAX); - return (KB+KB_OFFSET) << (KX * KX_LG2BASE); - } - - static int getNextK(int K) { - if (K <= 0) return 1; // 1st K value - int KX = getKXOf(K); - if (KX < 0) return Integer.MAX_VALUE; - // This is the increment we expect to apply: - int unit = 1 << (KX * KX_LG2BASE); - int mask = KB_MAX << (KX * KX_LG2BASE); - int K1 = K + unit; - K1 &= ~(unit-1); // cut off stray low-order bits - if (((K1 - unit) & ~mask) == 0) { - assert(getKXOf(K1) == KX); - return K1; - } - if (KX == KX_MAX) return Integer.MAX_VALUE; - KX += 1; - int mask2 = KB_MAX << (KX * KX_LG2BASE); - K1 |= (mask & ~mask2); - K1 += unit; - assert(getKXOf(K1) == KX); - return K1; - } - - // Is K of the form ((KB:[0..255])+1) * 16^(KX:{0..3])? - public static boolean isCodableLength(int K) { - int KX = getKXOf(K); - if (KX < 0) return false; - int unit = 1 << (KX * KX_LG2BASE); - int mask = KB_MAX << (KX * KX_LG2BASE); - return ((K - unit) & ~mask) == 0; - } - - public byte[] getMetaCoding(Coding dflt) { - //assert(!isTrivial()); // can happen - // See the isCodableLength restriction in CodingChooser. - ByteArrayOutputStream bytes = new ByteArrayOutputStream(10); - try { - makeMetaCoding(this, dflt, bytes); - } catch (IOException ee) { - throw new RuntimeException(ee); - } - return bytes.toByteArray(); - } - private static void makeMetaCoding(AdaptiveCoding run, Coding dflt, - ByteArrayOutputStream bytes) - throws IOException { - for (;;) { - CodingMethod headCoding = run.headCoding; - int headLength = run.headLength; - CodingMethod tailCoding = run.tailCoding; - int K = headLength; - assert(isCodableLength(K)); - int ADef = (headCoding == dflt)?1:0; - int BDef = (tailCoding == dflt)?1:0; - if (ADef+BDef > 1) BDef = 0; // arbitrary choice - int ABDef = 1*ADef + 2*BDef; - assert(ABDef < 3); - int KX = getKXOf(K); - int KB = getKBOf(K); - assert(decodeK(KX, KB) == K); - int KBFlag = (KB != KB_DEFAULT)?1:0; - bytes.write(_meta_run + KX + 4*KBFlag + 8*ABDef); - if (KBFlag != 0) bytes.write(KB); - if (ADef == 0) bytes.write(headCoding.getMetaCoding(dflt)); - if (tailCoding instanceof AdaptiveCoding) { - run = (AdaptiveCoding) tailCoding; - continue; // tail call, to avoid deep stack recursion - } - if (BDef == 0) bytes.write(tailCoding.getMetaCoding(dflt)); - break; - } - } - public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod res[]) { - int op = bytes[pos++] & 0xFF; - if (op < _meta_run || op >= _meta_pop) return pos-1; // backup - AdaptiveCoding prevc = null; - for (boolean keepGoing = true; keepGoing; ) { - keepGoing = false; - assert(op >= _meta_run); - op -= _meta_run; - int KX = op % 4; - int KBFlag = (op / 4) % 2; - int ABDef = (op / 8); - assert(ABDef < 3); - int ADef = (ABDef & 1); - int BDef = (ABDef & 2); - CodingMethod[] ACode = {dflt}, BCode = {dflt}; - int KB = KB_DEFAULT; - if (KBFlag != 0) - KB = bytes[pos++] & 0xFF; - if (ADef == 0) { - pos = BandStructure.parseMetaCoding(bytes, pos, dflt, ACode); - } - if (BDef == 0 && - ((op = bytes[pos] & 0xFF) >= _meta_run) && op < _meta_pop) { - pos++; - keepGoing = true; - } else if (BDef == 0) { - pos = BandStructure.parseMetaCoding(bytes, pos, dflt, BCode); - } - AdaptiveCoding newc = new AdaptiveCoding(decodeK(KX, KB), - ACode[0], BCode[0]); - if (prevc == null) { - res[0] = newc; - } else { - prevc.tailCoding = newc; - } - prevc = newc; - } - return pos; - } - - private String keyString(CodingMethod m) { - if (m instanceof Coding) - return ((Coding)m).keyString(); - return m.toString(); - } - public String toString() { - StringBuilder res = new StringBuilder(20); - AdaptiveCoding run = this; - res.append("run("); - for (;;) { - res.append(run.headLength).append("*"); - res.append(keyString(run.headCoding)); - if (run.tailCoding instanceof AdaptiveCoding) { - run = (AdaptiveCoding) run.tailCoding; - res.append(" "); - continue; - } - break; - } - res.append(" **").append(keyString(run.tailCoding)); - res.append(")"); - return res.toString(); - } - -/* - public static void main(String av[]) { - int[][] samples = { - {1,2,3,4,5}, - {254,255,256,256+1*16,256+2*16}, - {0xfd,0xfe,0xff,0x100,0x110,0x120,0x130}, - {0xfd0,0xfe0,0xff0,0x1000,0x1100,0x1200,0x1300}, - {0xfd00,0xfe00,0xff00,0x10000,0x11000,0x12000,0x13000}, - {0xfd000,0xfe000,0xff000,0x100000} - }; - for (int i = 0; i < samples.length; i++) { - for (int j = 0; j < samples[i].length; j++) { - int K = samples[i][j]; - int KX = getKXOf(K); - int KB = getKBOf(K); - System.out.println("K="+Integer.toHexString(K)+ - " KX="+KX+" KB="+KB); - assert(isCodableLength(K)); - assert(K == decodeK(KX, KB)); - if (j == 0) continue; - int K1 = samples[i][j-1]; - assert(K == getNextK(K1)); - } - } - } -//*/ - -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java deleted file mode 100644 index a686b080fca..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Attribute.java +++ /dev/null @@ -1,1699 +0,0 @@ -/* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import com.sun.java.util.jar.pack.ConstantPool.Index; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Represents an attribute in a class-file. - * Takes care to remember where constant pool indexes occur. - * Implements the "little language" of Pack200 for describing - * attribute layouts. - * @author John Rose - */ -class Attribute implements Comparable { - // Attribute instance fields. - - Layout def; // the name and format of this attr - byte[] bytes; // the actual bytes - Object fixups; // reference relocations, if any are required - - public String name() { return def.name(); } - public Layout layout() { return def; } - public byte[] bytes() { return bytes; } - public int size() { return bytes.length; } - public Entry getNameRef() { return def.getNameRef(); } - - private Attribute(Attribute old) { - this.def = old.def; - this.bytes = old.bytes; - this.fixups = old.fixups; - } - - public Attribute(Layout def, byte[] bytes, Object fixups) { - this.def = def; - this.bytes = bytes; - this.fixups = fixups; - Fixups.setBytes(fixups, bytes); - } - public Attribute(Layout def, byte[] bytes) { - this(def, bytes, null); - } - - public Attribute addContent(byte[] bytes, Object fixups) { - assert(isCanonical()); - if (bytes.length == 0 && fixups == null) - return this; - Attribute res = new Attribute(this); - res.bytes = bytes; - res.fixups = fixups; - Fixups.setBytes(fixups, bytes); - return res; - } - public Attribute addContent(byte[] bytes) { - return addContent(bytes, null); - } - - public void finishRefs(Index ix) { - if (fixups != null) { - Fixups.finishRefs(fixups, bytes, ix); - fixups = null; - } - } - - public boolean isCanonical() { - return this == def.canon; - } - - @Override - public int compareTo(Attribute that) { - return this.def.compareTo(that.def); - } - - private static final Map, List> canonLists = new HashMap<>(); - private static final Map attributes = new HashMap<>(); - private static final Map standardDefs = new HashMap<>(); - - // Canonicalized lists of trivial attrs (Deprecated, etc.) - // are used by trimToSize, in order to reduce footprint - // of some common cases. (Note that Code attributes are - // always zero size.) - public static List getCanonList(List al) { - synchronized (canonLists) { - List cl = canonLists.get(al); - if (cl == null) { - cl = new ArrayList<>(al.size()); - cl.addAll(al); - cl = Collections.unmodifiableList(cl); - canonLists.put(al, cl); - } - return cl; - } - } - - // Find the canonical empty attribute with the given ctype, name, layout. - public static Attribute find(int ctype, String name, String layout) { - Layout key = Layout.makeKey(ctype, name, layout); - synchronized (attributes) { - Attribute a = attributes.get(key); - if (a == null) { - a = new Layout(ctype, name, layout).canonicalInstance(); - attributes.put(key, a); - } - return a; - } - } - - public static Layout keyForLookup(int ctype, String name) { - return Layout.makeKey(ctype, name); - } - - // Find canonical empty attribute with given ctype and name, - // and with the standard layout. - public static Attribute lookup(Map defs, int ctype, - String name) { - if (defs == null) { - defs = standardDefs; - } - return defs.get(Layout.makeKey(ctype, name)); - } - - public static Attribute define(Map defs, int ctype, - String name, String layout) { - Attribute a = find(ctype, name, layout); - defs.put(Layout.makeKey(ctype, name), a); - return a; - } - - static { - Map sd = standardDefs; - define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH"); - define(sd, ATTR_CONTEXT_CLASS, "Synthetic", ""); - define(sd, ATTR_CONTEXT_CLASS, "Deprecated", ""); - define(sd, ATTR_CONTEXT_CLASS, "SourceFile", "RUH"); - define(sd, ATTR_CONTEXT_CLASS, "EnclosingMethod", "RCHRDNH"); - define(sd, ATTR_CONTEXT_CLASS, "InnerClasses", "NH[RCHRCNHRUNHFH]"); - define(sd, ATTR_CONTEXT_CLASS, "BootstrapMethods", "NH[RMHNH[KLH]]"); - - define(sd, ATTR_CONTEXT_FIELD, "Signature", "RSH"); - define(sd, ATTR_CONTEXT_FIELD, "Synthetic", ""); - define(sd, ATTR_CONTEXT_FIELD, "Deprecated", ""); - define(sd, ATTR_CONTEXT_FIELD, "ConstantValue", "KQH"); - - define(sd, ATTR_CONTEXT_METHOD, "Signature", "RSH"); - define(sd, ATTR_CONTEXT_METHOD, "Synthetic", ""); - define(sd, ATTR_CONTEXT_METHOD, "Deprecated", ""); - define(sd, ATTR_CONTEXT_METHOD, "Exceptions", "NH[RCH]"); - define(sd, ATTR_CONTEXT_METHOD, "MethodParameters", "NB[RUNHFH]"); - //define(sd, ATTR_CONTEXT_METHOD, "Code", "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]"); - - define(sd, ATTR_CONTEXT_CODE, "StackMapTable", - ("[NH[(1)]]" + - "[TB" + - "(64-127)[(2)]" + - "(247)[(1)(2)]" + - "(248-251)[(1)]" + - "(252)[(1)(2)]" + - "(253)[(1)(2)(2)]" + - "(254)[(1)(2)(2)(2)]" + - "(255)[(1)NH[(2)]NH[(2)]]" + - "()[]" + - "]" + - "[H]" + - "[TB(7)[RCH](8)[PH]()[]]")); - - define(sd, ATTR_CONTEXT_CODE, "LineNumberTable", "NH[PHH]"); - define(sd, ATTR_CONTEXT_CODE, "LocalVariableTable", "NH[PHOHRUHRSHH]"); - define(sd, ATTR_CONTEXT_CODE, "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); - //define(sd, ATTR_CONTEXT_CODE, "CharacterRangeTable", "NH[PHPOHIIH]"); - //define(sd, ATTR_CONTEXT_CODE, "CoverageTable", "NH[PHHII]"); - - // Note: Code and InnerClasses are special-cased elsewhere. - // Their layout specs. are given here for completeness. - // The Code spec is incomplete, in that it does not distinguish - // bytecode bytes or locate CP references. - // The BootstrapMethods attribute is also special-cased - // elsewhere as an appendix to the local constant pool. - } - - // Metadata. - // - // We define metadata using similar layouts - // for all five kinds of metadata attributes and 2 type metadata attributes - // - // Regular annotations are a counted list of [RSHNH[RUH(1)]][...] - // pack.method.attribute.RuntimeVisibleAnnotations=[NH[(1)]][RSHNH[RUH(1)]][TB...] - // - // Parameter annotations are a counted list of regular annotations. - // pack.method.attribute.RuntimeVisibleParameterAnnotations=[NB[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...] - // - // RuntimeInvisible annotations are defined similarly... - // Non-method annotations are defined similarly... - // - // Annotation are a simple tagged value [TB...] - // pack.attribute.method.AnnotationDefault=[TB...] - - static { - String mdLayouts[] = { - Attribute.normalizeLayoutString - ("" - +"\n # parameter_annotations :=" - +"\n [ NB[(1)] ] # forward call to annotations" - ), - Attribute.normalizeLayoutString - ("" - +"\n # annotations :=" - +"\n [ NH[(1)] ] # forward call to annotation" - +"\n " - ), - Attribute.normalizeLayoutString - ("" - +"\n # annotation :=" - +"\n [RSH" - +"\n NH[RUH (1)] # forward call to value" - +"\n ]" - ), - Attribute.normalizeLayoutString - ("" - +"\n # value :=" - +"\n [TB # Callable 2 encodes one tagged value." - +"\n (\\B,\\C,\\I,\\S,\\Z)[KIH]" - +"\n (\\D)[KDH]" - +"\n (\\F)[KFH]" - +"\n (\\J)[KJH]" - +"\n (\\c)[RSH]" - +"\n (\\e)[RSH RUH]" - +"\n (\\s)[RUH]" - +"\n (\\[)[NH[(0)]] # backward self-call to value" - +"\n (\\@)[RSH NH[RUH (0)]] # backward self-call to value" - +"\n ()[] ]" - ) - }; - /* - * RuntimeVisibleTypeAnnotation and RuntimeInvisibleTypeAnnotatation are - * similar to RuntimeVisibleAnnotation and RuntimeInvisibleAnnotation, - * a type-annotation union and a type-path structure precedes the - * annotation structure - */ - String typeLayouts[] = { - Attribute.normalizeLayoutString - ("" - +"\n # type-annotations :=" - +"\n [ NH[(1)(2)(3)] ] # forward call to type-annotations" - ), - Attribute.normalizeLayoutString - ( "" - +"\n # type-annotation :=" - +"\n [TB" - +"\n (0-1) [B] # {CLASS, METHOD}_TYPE_PARAMETER" - +"\n (16) [FH] # CLASS_EXTENDS" - +"\n (17-18) [BB] # {CLASS, METHOD}_TYPE_PARAMETER_BOUND" - +"\n (19-21) [] # FIELD, METHOD_RETURN, METHOD_RECEIVER" - +"\n (22) [B] # METHOD_FORMAL_PARAMETER" - +"\n (23) [H] # THROWS" - +"\n (64-65) [NH[PHOHH]] # LOCAL_VARIABLE, RESOURCE_VARIABLE" - +"\n (66) [H] # EXCEPTION_PARAMETER" - +"\n (67-70) [PH] # INSTANCEOF, NEW, {CONSTRUCTOR, METHOD}_REFERENCE_RECEIVER" - +"\n (71-75) [PHB] # CAST, {CONSTRUCTOR,METHOD}_INVOCATION_TYPE_ARGUMENT, {CONSTRUCTOR, METHOD}_REFERENCE_TYPE_ARGUMENT" - +"\n ()[] ]" - ), - Attribute.normalizeLayoutString - ("" - +"\n # type-path" - +"\n [ NB[BB] ]" - ) - }; - Map sd = standardDefs; - String defaultLayout = mdLayouts[3]; - String annotationsLayout = mdLayouts[1] + mdLayouts[2] + mdLayouts[3]; - String paramsLayout = mdLayouts[0] + annotationsLayout; - String typesLayout = typeLayouts[0] + typeLayouts[1] + - typeLayouts[2] + mdLayouts[2] + mdLayouts[3]; - - for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { - if (ctype != ATTR_CONTEXT_CODE) { - define(sd, ctype, - "RuntimeVisibleAnnotations", annotationsLayout); - define(sd, ctype, - "RuntimeInvisibleAnnotations", annotationsLayout); - - if (ctype == ATTR_CONTEXT_METHOD) { - define(sd, ctype, - "RuntimeVisibleParameterAnnotations", paramsLayout); - define(sd, ctype, - "RuntimeInvisibleParameterAnnotations", paramsLayout); - define(sd, ctype, - "AnnotationDefault", defaultLayout); - } - } - define(sd, ctype, - "RuntimeVisibleTypeAnnotations", typesLayout); - define(sd, ctype, - "RuntimeInvisibleTypeAnnotations", typesLayout); - } - } - - public static String contextName(int ctype) { - switch (ctype) { - case ATTR_CONTEXT_CLASS: return "class"; - case ATTR_CONTEXT_FIELD: return "field"; - case ATTR_CONTEXT_METHOD: return "method"; - case ATTR_CONTEXT_CODE: return "code"; - } - return null; - } - - /** Base class for any attributed object (Class, Field, Method, Code). - * Flags are included because they are used to help transmit the - * presence of attributes. That is, flags are a mix of modifier - * bits and attribute indicators. - */ - public abstract static - class Holder { - - // We need this abstract method to interpret embedded CP refs. - protected abstract Entry[] getCPMap(); - - protected int flags; // defined here for convenience - protected List attributes; - - public int attributeSize() { - return (attributes == null) ? 0 : attributes.size(); - } - - public void trimToSize() { - if (attributes == null) { - return; - } - if (attributes.isEmpty()) { - attributes = null; - return; - } - if (attributes instanceof ArrayList) { - ArrayList al = (ArrayList)attributes; - al.trimToSize(); - boolean allCanon = true; - for (Attribute a : al) { - if (!a.isCanonical()) { - allCanon = false; - } - if (a.fixups != null) { - assert(!a.isCanonical()); - a.fixups = Fixups.trimToSize(a.fixups); - } - } - if (allCanon) { - // Replace private writable attribute list - // with only trivial entries by public unique - // immutable attribute list with the same entries. - attributes = getCanonList(al); - } - } - } - - public void addAttribute(Attribute a) { - if (attributes == null) - attributes = new ArrayList<>(3); - else if (!(attributes instanceof ArrayList)) - attributes = new ArrayList<>(attributes); // unfreeze it - attributes.add(a); - } - - public Attribute removeAttribute(Attribute a) { - if (attributes == null) return null; - if (!attributes.contains(a)) return null; - if (!(attributes instanceof ArrayList)) - attributes = new ArrayList<>(attributes); // unfreeze it - attributes.remove(a); - return a; - } - - public Attribute getAttribute(int n) { - return attributes.get(n); - } - - protected void visitRefs(int mode, Collection refs) { - if (attributes == null) return; - for (Attribute a : attributes) { - a.visitRefs(this, mode, refs); - } - } - - static final List noAttributes = Arrays.asList(new Attribute[0]); - - public List getAttributes() { - if (attributes == null) - return noAttributes; - return attributes; - } - - public void setAttributes(List attrList) { - if (attrList.isEmpty()) - attributes = null; - else - attributes = attrList; - } - - public Attribute getAttribute(String attrName) { - if (attributes == null) return null; - for (Attribute a : attributes) { - if (a.name().equals(attrName)) - return a; - } - return null; - } - - public Attribute getAttribute(Layout attrDef) { - if (attributes == null) return null; - for (Attribute a : attributes) { - if (a.layout() == attrDef) - return a; - } - return null; - } - - public Attribute removeAttribute(String attrName) { - return removeAttribute(getAttribute(attrName)); - } - - public Attribute removeAttribute(Layout attrDef) { - return removeAttribute(getAttribute(attrDef)); - } - - public void strip(String attrName) { - removeAttribute(getAttribute(attrName)); - } - } - - // Lightweight interface to hide details of band structure. - // Also used for testing. - public abstract static - class ValueStream { - public int getInt(int bandIndex) { throw undef(); } - public void putInt(int bandIndex, int value) { throw undef(); } - public Entry getRef(int bandIndex) { throw undef(); } - public void putRef(int bandIndex, Entry ref) { throw undef(); } - // Note: decodeBCI goes w/ getInt/Ref; encodeBCI goes w/ putInt/Ref - public int decodeBCI(int bciCode) { throw undef(); } - public int encodeBCI(int bci) { throw undef(); } - public void noteBackCall(int whichCallable) { /* ignore by default */ } - private RuntimeException undef() { - return new UnsupportedOperationException("ValueStream method"); - } - } - - // Element kinds: - static final byte EK_INT = 1; // B H I SH etc. - static final byte EK_BCI = 2; // PH POH etc. - static final byte EK_BCO = 3; // OH etc. - static final byte EK_FLAG = 4; // FH etc. - static final byte EK_REPL = 5; // NH[...] etc. - static final byte EK_REF = 6; // RUH, RUNH, KQH, etc. - static final byte EK_UN = 7; // TB(...)[...] etc. - static final byte EK_CASE = 8; // (...)[...] etc. - static final byte EK_CALL = 9; // (0), (1), etc. - static final byte EK_CBLE = 10; // [...][...] etc. - static final byte EF_SIGN = 1<<0; // INT is signed - static final byte EF_DELTA = 1<<1; // BCI/BCI value is diff'ed w/ previous - static final byte EF_NULL = 1<<2; // null REF is expected/allowed - static final byte EF_BACK = 1<<3; // call, callable, case is backward - static final int NO_BAND_INDEX = -1; - - /** A "class" of attributes, characterized by a context-type, name - * and format. The formats are specified in a "little language". - */ - public static - class Layout implements Comparable { - int ctype; // attribute context type, e.g., ATTR_CONTEXT_CODE - String name; // name of attribute - boolean hasRefs; // this kind of attr contains CP refs? - String layout; // layout specification - int bandCount; // total number of elems - Element[] elems; // tokenization of layout - Attribute canon; // canonical instance of this layout - - public int ctype() { return ctype; } - public String name() { return name; } - public String layout() { return layout; } - public Attribute canonicalInstance() { return canon; } - - public Entry getNameRef() { - return ConstantPool.getUtf8Entry(name()); - } - - public boolean isEmpty() { - return layout.isEmpty(); - } - - public Layout(int ctype, String name, String layout) { - this.ctype = ctype; - this.name = name.intern(); - this.layout = layout.intern(); - assert(ctype < ATTR_CONTEXT_LIMIT); - boolean hasCallables = layout.startsWith("["); - try { - if (!hasCallables) { - this.elems = tokenizeLayout(this, -1, layout); - } else { - String[] bodies = splitBodies(layout); - // Make the callables now, so they can be linked immediately. - Element[] lelems = new Element[bodies.length]; - this.elems = lelems; - for (int i = 0; i < lelems.length; i++) { - Element ce = this.new Element(); - ce.kind = EK_CBLE; - ce.removeBand(); - ce.bandIndex = NO_BAND_INDEX; - ce.layout = bodies[i]; - lelems[i] = ce; - } - // Next fill them in. - for (int i = 0; i < lelems.length; i++) { - Element ce = lelems[i]; - ce.body = tokenizeLayout(this, i, bodies[i]); - } - //System.out.println(Arrays.asList(elems)); - } - } catch (StringIndexOutOfBoundsException ee) { - // simplest way to catch syntax errors... - throw new RuntimeException("Bad attribute layout: "+layout, ee); - } - // Some uses do not make a fresh one for each occurrence. - // For example, if layout == "", we only need one attr to share. - canon = new Attribute(this, noBytes); - } - private Layout() {} - static Layout makeKey(int ctype, String name, String layout) { - Layout def = new Layout(); - def.ctype = ctype; - def.name = name.intern(); - def.layout = layout.intern(); - assert(ctype < ATTR_CONTEXT_LIMIT); - return def; - } - static Layout makeKey(int ctype, String name) { - return makeKey(ctype, name, ""); - } - - public Attribute addContent(byte[] bytes, Object fixups) { - return canon.addContent(bytes, fixups); - } - public Attribute addContent(byte[] bytes) { - return canon.addContent(bytes, null); - } - - @Override - public boolean equals(Object x) { - return ( x != null) && ( x.getClass() == Layout.class ) && - equals((Layout)x); - } - public boolean equals(Layout that) { - return this.name.equals(that.name) - && this.layout.equals(that.layout) - && this.ctype == that.ctype; - } - @Override - public int hashCode() { - return (((17 + name.hashCode()) - * 37 + layout.hashCode()) - * 37 + ctype); - } - @Override - public int compareTo(Layout that) { - int r; - r = this.name.compareTo(that.name); - if (r != 0) return r; - r = this.layout.compareTo(that.layout); - if (r != 0) return r; - return this.ctype - that.ctype; - } - @Override - public String toString() { - String str = contextName(ctype)+"."+name+"["+layout+"]"; - // If -ea, print out more informative strings! - assert((str = stringForDebug()) != null); - return str; - } - private String stringForDebug() { - return contextName(ctype)+"."+name+Arrays.asList(elems); - } - - public - class Element { - String layout; // spelling in the little language - byte flags; // EF_SIGN, etc. - byte kind; // EK_UINT, etc. - byte len; // scalar length of element - byte refKind; // CONSTANT_String, etc. - int bandIndex; // which band does this element govern? - int value; // extra parameter - Element[] body; // extra data (for replications, unions, calls) - - boolean flagTest(byte mask) { return (flags & mask) != 0; } - - Element() { - bandIndex = bandCount++; - } - - void removeBand() { - --bandCount; - assert(bandIndex == bandCount); - bandIndex = NO_BAND_INDEX; - } - - public boolean hasBand() { - return bandIndex >= 0; - } - public String toString() { - String str = layout; - // If -ea, print out more informative strings! - assert((str = stringForDebug()) != null); - return str; - } - private String stringForDebug() { - Element[] lbody = this.body; - switch (kind) { - case EK_CALL: - lbody = null; - break; - case EK_CASE: - if (flagTest(EF_BACK)) - lbody = null; - break; - } - return layout - + (!hasBand()?"":"#"+bandIndex) - + "<"+ (flags==0?"":""+flags)+kind+len - + (refKind==0?"":""+refKind) + ">" - + (value==0?"":"("+value+")") - + (lbody==null?"": ""+Arrays.asList(lbody)); - } - } - - public boolean hasCallables() { - return (elems.length > 0 && elems[0].kind == EK_CBLE); - } - private static final Element[] noElems = {}; - public Element[] getCallables() { - if (hasCallables()) { - Element[] nelems = Arrays.copyOf(elems, elems.length); - return nelems; - } else - return noElems; // no callables at all - } - public Element[] getEntryPoint() { - if (hasCallables()) - return elems[0].body; // body of first callable - else { - Element[] nelems = Arrays.copyOf(elems, elems.length); - return nelems; // no callables; whole body - } - } - - /** Return a sequence of tokens from the given attribute bytes. - * Sequence elements will be 1-1 correspondent with my layout tokens. - */ - public void parse(Holder holder, - byte[] bytes, int pos, int len, ValueStream out) { - int end = parseUsing(getEntryPoint(), - holder, bytes, pos, len, out); - if (end != pos + len) - throw new InternalError("layout parsed "+(end-pos)+" out of "+len+" bytes"); - } - /** Given a sequence of tokens, return the attribute bytes. - * Sequence elements must be 1-1 correspondent with my layout tokens. - * The returned object is a cookie for Fixups.finishRefs, which - * must be used to harden any references into integer indexes. - */ - public Object unparse(ValueStream in, ByteArrayOutputStream out) { - Object[] fixups = { null }; - unparseUsing(getEntryPoint(), fixups, in, out); - return fixups[0]; // return ref-bearing cookie, if any - } - - public String layoutForClassVersion(Package.Version vers) { - if (vers.lessThan(JAVA6_MAX_CLASS_VERSION)) { - // Disallow layout syntax in the oldest protocol version. - return expandCaseDashNotation(layout); - } - return layout; - } - } - - public static - class FormatException extends IOException { - @java.io.Serial - private static final long serialVersionUID = -2542243830788066513L; - - private int ctype; - private String name; - String layout; - public FormatException(String message, - int ctype, String name, String layout) { - super(ATTR_CONTEXT_NAME[ctype]+ " attribute \"" + name + "\"" + - (message == null? "" : (": " + message))); - this.ctype = ctype; - this.name = name; - this.layout = layout; - } - public FormatException(String message, - int ctype, String name) { - this(message, ctype, name, null); - } - } - - void visitRefs(Holder holder, int mode, final Collection refs) { - if (mode == VRM_CLASSIC) { - refs.add(getNameRef()); - } - // else the name is owned by the layout, and is processed elsewhere - if (bytes.length == 0) return; // quick exit - if (!def.hasRefs) return; // quick exit - if (fixups != null) { - Fixups.visitRefs(fixups, refs); - return; - } - // References (to a local cpMap) are embedded in the bytes. - def.parse(holder, bytes, 0, bytes.length, - new ValueStream() { - @Override - public void putInt(int bandIndex, int value) { - } - @Override - public void putRef(int bandIndex, Entry ref) { - refs.add(ref); - } - @Override - public int encodeBCI(int bci) { - return bci; - } - }); - } - - public void parse(Holder holder, byte[] bytes, int pos, int len, ValueStream out) { - def.parse(holder, bytes, pos, len, out); - } - public Object unparse(ValueStream in, ByteArrayOutputStream out) { - return def.unparse(in, out); - } - - @Override - public String toString() { - return def - +"{"+(bytes == null ? -1 : size())+"}" - +(fixups == null? "": fixups.toString()); - } - - /** Remove any informal "pretty printing" from the layout string. - * Removes blanks and control chars. - * Removes '#' comments (to end of line). - * Replaces '\c' by the decimal code of the character c. - * Replaces '0xNNN' by the decimal code of the hex number NNN. - */ - public static - String normalizeLayoutString(String layout) { - StringBuilder buf = new StringBuilder(); - for (int i = 0, len = layout.length(); i < len; ) { - char ch = layout.charAt(i++); - if (ch <= ' ') { - // Skip whitespace and control chars - continue; - } else if (ch == '#') { - // Skip to end of line. - int end1 = layout.indexOf('\n', i); - int end2 = layout.indexOf('\r', i); - if (end1 < 0) end1 = len; - if (end2 < 0) end2 = len; - i = Math.min(end1, end2); - } else if (ch == '\\') { - // Map a character reference to its decimal code. - buf.append((int) layout.charAt(i++)); - } else if (ch == '0' && layout.startsWith("0x", i-1)) { - // Map a hex numeral to its decimal code. - int start = i-1; - int end = start+2; - while (end < len) { - int dig = layout.charAt(end); - if ((dig >= '0' && dig <= '9') || - (dig >= 'a' && dig <= 'f')) - ++end; - else - break; - } - if (end > start) { - String num = layout.substring(start, end); - buf.append(Integer.decode(num)); - i = end; - } else { - buf.append(ch); - } - } else { - buf.append(ch); - } - } - String result = buf.toString(); - if (false && !result.equals(layout)) { - Utils.log.info("Normalizing layout string"); - Utils.log.info(" From: "+layout); - Utils.log.info(" To: "+result); - } - return result; - } - - /// Subroutines for parsing and unparsing: - - /** Parse the attribute layout language. -

-  attribute_layout:
-        ( layout_element )* | ( callable )+
-  layout_element:
-        ( integral | replication | union | call | reference )
-
-  callable:
-        '[' body ']'
-  body:
-        ( layout_element )+
-
-  integral:
-        ( unsigned_int | signed_int | bc_index | bc_offset | flag )
-  unsigned_int:
-        uint_type
-  signed_int:
-        'S' uint_type
-  any_int:
-        ( unsigned_int | signed_int )
-  bc_index:
-        ( 'P' uint_type | 'PO' uint_type )
-  bc_offset:
-        'O' any_int
-  flag:
-        'F' uint_type
-  uint_type:
-        ( 'B' | 'H' | 'I' | 'V' )
-
-  replication:
-        'N' uint_type '[' body ']'
-
-  union:
-        'T' any_int (union_case)* '(' ')' '[' (body)? ']'
-  union_case:
-        '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
-  union_case_tag:
-        ( numeral | numeral '-' numeral )
-  call:
-        '(' numeral ')'
-
-  reference:
-        reference_type ( 'N' )? uint_type
-  reference_type:
-        ( constant_ref | schema_ref | utf8_ref | untyped_ref )
-  constant_ref:
-        ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' )
-  schema_ref:
-        ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' )
-  utf8_ref:
-        'RU'
-  untyped_ref:
-        'RQ'
-
-  numeral:
-        '(' ('-')? (digit)+ ')'
-  digit:
-        ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
- 
- */ - static //private - Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) { - List col = new ArrayList<>(layout.length()); - tokenizeLayout(self, curCble, layout, col); - Layout.Element[] res = new Layout.Element[col.size()]; - col.toArray(res); - return res; - } - static //private - void tokenizeLayout(Layout self, int curCble, String layout, List col) { - boolean prevBCI = false; - for (int len = layout.length(), i = 0; i < len; ) { - int start = i; - int body; - Layout.Element e = self.new Element(); - byte kind; - //System.out.println("at "+i+": ..."+layout.substring(i)); - // strip a prefix - switch (layout.charAt(i++)) { - /// layout_element: integral - case 'B': case 'H': case 'I': case 'V': // unsigned_int - kind = EK_INT; - --i; // reparse - i = tokenizeUInt(e, layout, i); - break; - case 'S': // signed_int - kind = EK_INT; - --i; // reparse - i = tokenizeSInt(e, layout, i); - break; - case 'P': // bc_index - kind = EK_BCI; - if (layout.charAt(i++) == 'O') { - // bc_index: 'PO' tokenizeUInt - e.flags |= EF_DELTA; - // must follow P or PO: - if (!prevBCI) - { i = -i; continue; } // fail - i++; // move forward - } - --i; // reparse - i = tokenizeUInt(e, layout, i); - break; - case 'O': // bc_offset - kind = EK_BCO; - e.flags |= EF_DELTA; - // must follow P or PO: - if (!prevBCI) - { i = -i; continue; } // fail - i = tokenizeSInt(e, layout, i); - break; - case 'F': // flag - kind = EK_FLAG; - i = tokenizeUInt(e, layout, i); - break; - case 'N': // replication: 'N' uint '[' elem ... ']' - kind = EK_REPL; - i = tokenizeUInt(e, layout, i); - if (layout.charAt(i++) != '[') - { i = -i; continue; } // fail - i = skipBody(layout, body = i); - e.body = tokenizeLayout(self, curCble, - layout.substring(body, i++)); - break; - case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']' - kind = EK_UN; - i = tokenizeSInt(e, layout, i); - List cases = new ArrayList<>(); - for (;;) { - // Keep parsing cases until we hit the default case. - if (layout.charAt(i++) != '(') - { i = -i; break; } // fail - int beg = i; - i = layout.indexOf(')', i); - String cstr = layout.substring(beg, i++); - int cstrlen = cstr.length(); - if (layout.charAt(i++) != '[') - { i = -i; break; } // fail - // Check for duplication. - if (layout.charAt(i) == ']') - body = i; // missing body, which is legal here - else - i = skipBody(layout, body = i); - Layout.Element[] cbody - = tokenizeLayout(self, curCble, - layout.substring(body, i++)); - if (cstrlen == 0) { - Layout.Element ce = self.new Element(); - ce.body = cbody; - ce.kind = EK_CASE; - ce.removeBand(); - cases.add(ce); - break; // done with the whole union - } else { - // Parse a case string. - boolean firstCaseNum = true; - for (int cp = 0, endp;; cp = endp+1) { - // Look for multiple case tags: - endp = cstr.indexOf(',', cp); - if (endp < 0) endp = cstrlen; - String cstr1 = cstr.substring(cp, endp); - if (cstr1.isEmpty()) - cstr1 = "empty"; // will fail parse - int value0, value1; - // Check for a case range (new in 1.6). - int dash = findCaseDash(cstr1, 0); - if (dash >= 0) { - value0 = parseIntBefore(cstr1, dash); - value1 = parseIntAfter(cstr1, dash); - if (value0 >= value1) - { i = -i; break; } // fail - } else { - value0 = value1 = Integer.parseInt(cstr1); - } - // Add a case for each value in value0..value1 - for (;; value0++) { - Layout.Element ce = self.new Element(); - ce.body = cbody; // all cases share one body - ce.kind = EK_CASE; - ce.removeBand(); - if (!firstCaseNum) - // "backward case" repeats a body - ce.flags |= EF_BACK; - firstCaseNum = false; - ce.value = value0; - cases.add(ce); - if (value0 == value1) break; - } - if (endp == cstrlen) { - break; // done with this case - } - } - } - } - e.body = new Layout.Element[cases.size()]; - cases.toArray(e.body); - e.kind = kind; - for (int j = 0; j < e.body.length-1; j++) { - Layout.Element ce = e.body[j]; - if (matchCase(e, ce.value) != ce) { - // Duplicate tag. - { i = -i; break; } // fail - } - } - break; - case '(': // call: '(' '-'? digit+ ')' - kind = EK_CALL; - e.removeBand(); - i = layout.indexOf(')', i); - String cstr = layout.substring(start+1, i++); - int offset = Integer.parseInt(cstr); - int target = curCble + offset; - if (!(offset+"").equals(cstr) || - self.elems == null || - target < 0 || - target >= self.elems.length) - { i = -i; continue; } // fail - Layout.Element ce = self.elems[target]; - assert(ce.kind == EK_CBLE); - e.value = target; - e.body = new Layout.Element[]{ ce }; - // Is it a (recursive) backward call? - if (offset <= 0) { - // Yes. Mark both caller and callee backward. - e.flags |= EF_BACK; - ce.flags |= EF_BACK; - } - break; - case 'K': // reference_type: constant_ref - kind = EK_REF; - switch (layout.charAt(i++)) { - case 'I': e.refKind = CONSTANT_Integer; break; - case 'J': e.refKind = CONSTANT_Long; break; - case 'F': e.refKind = CONSTANT_Float; break; - case 'D': e.refKind = CONSTANT_Double; break; - case 'S': e.refKind = CONSTANT_String; break; - case 'Q': e.refKind = CONSTANT_FieldSpecific; break; - - // new in 1.7: - case 'M': e.refKind = CONSTANT_MethodHandle; break; - case 'T': e.refKind = CONSTANT_MethodType; break; - case 'L': e.refKind = CONSTANT_LoadableValue; break; - default: { i = -i; continue; } // fail - } - break; - case 'R': // schema_ref - kind = EK_REF; - switch (layout.charAt(i++)) { - case 'C': e.refKind = CONSTANT_Class; break; - case 'S': e.refKind = CONSTANT_Signature; break; - case 'D': e.refKind = CONSTANT_NameandType; break; - case 'F': e.refKind = CONSTANT_Fieldref; break; - case 'M': e.refKind = CONSTANT_Methodref; break; - case 'I': e.refKind = CONSTANT_InterfaceMethodref; break; - - case 'U': e.refKind = CONSTANT_Utf8; break; //utf8_ref - case 'Q': e.refKind = CONSTANT_All; break; //untyped_ref - - // new in 1.7: - case 'Y': e.refKind = CONSTANT_InvokeDynamic; break; - case 'B': e.refKind = CONSTANT_BootstrapMethod; break; - case 'N': e.refKind = CONSTANT_AnyMember; break; - - default: { i = -i; continue; } // fail - } - break; - default: { i = -i; continue; } // fail - } - - // further parsing of refs - if (kind == EK_REF) { - // reference: reference_type -><- ( 'N' )? tokenizeUInt - if (layout.charAt(i++) == 'N') { - e.flags |= EF_NULL; - i++; // move forward - } - --i; // reparse - i = tokenizeUInt(e, layout, i); - self.hasRefs = true; - } - - prevBCI = (kind == EK_BCI); - - // store the new element - e.kind = kind; - e.layout = layout.substring(start, i); - col.add(e); - } - } - static //private - String[] splitBodies(String layout) { - List bodies = new ArrayList<>(); - // Parse several independent layout bodies: "[foo][bar]...[baz]" - for (int i = 0; i < layout.length(); i++) { - if (layout.charAt(i++) != '[') - layout.charAt(-i); // throw error - int body; - i = skipBody(layout, body = i); - bodies.add(layout.substring(body, i)); - } - String[] res = new String[bodies.size()]; - bodies.toArray(res); - return res; - } - private static - int skipBody(String layout, int i) { - assert(layout.charAt(i-1) == '['); - if (layout.charAt(i) == ']') - // No empty bodies, please. - return -i; - // skip balanced [...[...]...] - for (int depth = 1; depth > 0; ) { - switch (layout.charAt(i++)) { - case '[': depth++; break; - case ']': depth--; break; - } - } - --i; // get before bracket - assert(layout.charAt(i) == ']'); - return i; // return closing bracket - } - private static - int tokenizeUInt(Layout.Element e, String layout, int i) { - switch (layout.charAt(i++)) { - case 'V': e.len = 0; break; - case 'B': e.len = 1; break; - case 'H': e.len = 2; break; - case 'I': e.len = 4; break; - default: return -i; - } - return i; - } - private static - int tokenizeSInt(Layout.Element e, String layout, int i) { - if (layout.charAt(i) == 'S') { - e.flags |= EF_SIGN; - ++i; - } - return tokenizeUInt(e, layout, i); - } - - private static - boolean isDigit(char c) { - return c >= '0' && c <= '9'; - } - - /** Find an occurrence of hyphen '-' between two numerals. */ - static //private - int findCaseDash(String layout, int fromIndex) { - if (fromIndex <= 0) fromIndex = 1; // minimum dash pos - int lastDash = layout.length() - 2; // maximum dash pos - for (;;) { - int dash = layout.indexOf('-', fromIndex); - if (dash < 0 || dash > lastDash) return -1; - if (isDigit(layout.charAt(dash-1))) { - char afterDash = layout.charAt(dash+1); - if (afterDash == '-' && dash+2 < layout.length()) - afterDash = layout.charAt(dash+2); - if (isDigit(afterDash)) { - // matched /[0-9]--?[0-9]/; return position of dash - return dash; - } - } - fromIndex = dash+1; - } - } - static - int parseIntBefore(String layout, int dash) { - int end = dash; - int beg = end; - while (beg > 0 && isDigit(layout.charAt(beg-1))) { - --beg; - } - if (beg == end) return Integer.parseInt("empty"); - // skip backward over a sign - if (beg >= 1 && layout.charAt(beg-1) == '-') --beg; - assert(beg == 0 || !isDigit(layout.charAt(beg-1))); - return Integer.parseInt(layout.substring(beg, end)); - } - static - int parseIntAfter(String layout, int dash) { - int beg = dash+1; - int end = beg; - int limit = layout.length(); - if (end < limit && layout.charAt(end) == '-') ++end; - while (end < limit && isDigit(layout.charAt(end))) { - ++end; - } - if (beg == end) return Integer.parseInt("empty"); - return Integer.parseInt(layout.substring(beg, end)); - } - /** For compatibility with 1.5 pack, expand 1-5 into 1,2,3,4,5. */ - static - String expandCaseDashNotation(String layout) { - int dash = findCaseDash(layout, 0); - if (dash < 0) return layout; // no dashes (the common case) - StringBuilder result = new StringBuilder(layout.length() * 3); - int sofar = 0; // how far have we processed the layout? - for (;;) { - // for each dash, collect everything up to the dash - result.append(layout, sofar, dash); - sofar = dash+1; // skip the dash - // then collect intermediate values - int value0 = parseIntBefore(layout, dash); - int value1 = parseIntAfter(layout, dash); - assert(value0 < value1); - result.append(","); // close off value0 numeral - for (int i = value0+1; i < value1; i++) { - result.append(i); - result.append(","); // close off i numeral - } - dash = findCaseDash(layout, sofar); - if (dash < 0) break; - } - result.append(layout, sofar, layout.length()); // collect the rest - return result.toString(); - } - static { - assert(expandCaseDashNotation("1-5").equals("1,2,3,4,5")); - assert(expandCaseDashNotation("-2--1").equals("-2,-1")); - assert(expandCaseDashNotation("-2-1").equals("-2,-1,0,1")); - assert(expandCaseDashNotation("-1-0").equals("-1,0")); - } - - // Parse attribute bytes, putting values into bands. Returns new pos. - // Used when reading a class file (local refs resolved with local cpMap). - // Also used for ad hoc scanning. - static - int parseUsing(Layout.Element[] elems, Holder holder, - byte[] bytes, int pos, int len, ValueStream out) { - int prevBCI = 0; - int prevRBCI = 0; - int end = pos + len; - int[] buf = { 0 }; // for calls to parseInt, holds 2nd result - for (int i = 0; i < elems.length; i++) { - Layout.Element e = elems[i]; - int bandIndex = e.bandIndex; - int value; - int BCI, RBCI; - switch (e.kind) { - case EK_INT: - pos = parseInt(e, bytes, pos, buf); - value = buf[0]; - out.putInt(bandIndex, value); - break; - case EK_BCI: // PH, POH - pos = parseInt(e, bytes, pos, buf); - BCI = buf[0]; - RBCI = out.encodeBCI(BCI); - if (!e.flagTest(EF_DELTA)) { - // PH: transmit R(bci), store bci - value = RBCI; - } else { - // POH: transmit D(R(bci)), store bci - value = RBCI - prevRBCI; - } - prevBCI = BCI; - prevRBCI = RBCI; - out.putInt(bandIndex, value); - break; - case EK_BCO: // OH - assert(e.flagTest(EF_DELTA)); - // OH: transmit D(R(bci)), store D(bci) - pos = parseInt(e, bytes, pos, buf); - BCI = prevBCI + buf[0]; - RBCI = out.encodeBCI(BCI); - value = RBCI - prevRBCI; - prevBCI = BCI; - prevRBCI = RBCI; - out.putInt(bandIndex, value); - break; - case EK_FLAG: - pos = parseInt(e, bytes, pos, buf); - value = buf[0]; - out.putInt(bandIndex, value); - break; - case EK_REPL: - pos = parseInt(e, bytes, pos, buf); - value = buf[0]; - out.putInt(bandIndex, value); - for (int j = 0; j < value; j++) { - pos = parseUsing(e.body, holder, bytes, pos, end-pos, out); - } - break; // already transmitted the scalar value - case EK_UN: - pos = parseInt(e, bytes, pos, buf); - value = buf[0]; - out.putInt(bandIndex, value); - Layout.Element ce = matchCase(e, value); - pos = parseUsing(ce.body, holder, bytes, pos, end-pos, out); - - break; // already transmitted the scalar value - case EK_CALL: - // Adjust band offset if it is a backward call. - assert(e.body.length == 1); - assert(e.body[0].kind == EK_CBLE); - if (e.flagTest(EF_BACK)) - out.noteBackCall(e.value); - pos = parseUsing(e.body[0].body, holder, bytes, pos, end-pos, out); - break; // no additional scalar value to transmit - case EK_REF: - pos = parseInt(e, bytes, pos, buf); - int localRef = buf[0]; - Entry globalRef; - if (localRef == 0) { - globalRef = null; // N.B. global null reference is -1 - } else { - Entry[] cpMap = holder.getCPMap(); - globalRef = (localRef >= 0 && localRef < cpMap.length - ? cpMap[localRef] - : null); - byte tag = e.refKind; - if (globalRef != null && tag == CONSTANT_Signature - && globalRef.getTag() == CONSTANT_Utf8) { - // Cf. ClassReader.readSignatureRef. - String typeName = globalRef.stringValue(); - globalRef = ConstantPool.getSignatureEntry(typeName); - } - String got = (globalRef == null - ? "invalid CP index" - : "type=" + ConstantPool.tagName(globalRef.tag)); - if (globalRef == null || !globalRef.tagMatches(tag)) { - throw new IllegalArgumentException( - "Bad constant, expected type=" + - ConstantPool.tagName(tag) + " got " + got); - } - } - out.putRef(bandIndex, globalRef); - break; - default: assert(false); - } - } - return pos; - } - - static - Layout.Element matchCase(Layout.Element e, int value) { - assert(e.kind == EK_UN); - int lastj = e.body.length-1; - for (int j = 0; j < lastj; j++) { - Layout.Element ce = e.body[j]; - assert(ce.kind == EK_CASE); - if (value == ce.value) - return ce; - } - return e.body[lastj]; - } - - private static - int parseInt(Layout.Element e, byte[] bytes, int pos, int[] buf) { - int value = 0; - int loBits = e.len * 8; - // Read in big-endian order: - for (int bitPos = loBits; (bitPos -= 8) >= 0; ) { - value += (bytes[pos++] & 0xFF) << bitPos; - } - if (loBits < 32 && e.flagTest(EF_SIGN)) { - // sign-extend subword value - int hiBits = 32 - loBits; - value = (value << hiBits) >> hiBits; - } - buf[0] = value; - return pos; - } - - // Format attribute bytes, drawing values from bands. - // Used when emptying attribute bands into a package model. - // (At that point CP refs. are not yet assigned indexes.) - static - void unparseUsing(Layout.Element[] elems, Object[] fixups, - ValueStream in, ByteArrayOutputStream out) { - int prevBCI = 0; - int prevRBCI = 0; - for (int i = 0; i < elems.length; i++) { - Layout.Element e = elems[i]; - int bandIndex = e.bandIndex; - int value; - int BCI, RBCI; // "RBCI" is R(BCI), BCI's coded representation - switch (e.kind) { - case EK_INT: - value = in.getInt(bandIndex); - unparseInt(e, value, out); - break; - case EK_BCI: // PH, POH - value = in.getInt(bandIndex); - if (!e.flagTest(EF_DELTA)) { - // PH: transmit R(bci), store bci - RBCI = value; - } else { - // POH: transmit D(R(bci)), store bci - RBCI = prevRBCI + value; - } - assert(prevBCI == in.decodeBCI(prevRBCI)); - BCI = in.decodeBCI(RBCI); - unparseInt(e, BCI, out); - prevBCI = BCI; - prevRBCI = RBCI; - break; - case EK_BCO: // OH - value = in.getInt(bandIndex); - assert(e.flagTest(EF_DELTA)); - // OH: transmit D(R(bci)), store D(bci) - assert(prevBCI == in.decodeBCI(prevRBCI)); - RBCI = prevRBCI + value; - BCI = in.decodeBCI(RBCI); - unparseInt(e, BCI - prevBCI, out); - prevBCI = BCI; - prevRBCI = RBCI; - break; - case EK_FLAG: - value = in.getInt(bandIndex); - unparseInt(e, value, out); - break; - case EK_REPL: - value = in.getInt(bandIndex); - unparseInt(e, value, out); - for (int j = 0; j < value; j++) { - unparseUsing(e.body, fixups, in, out); - } - break; - case EK_UN: - value = in.getInt(bandIndex); - unparseInt(e, value, out); - Layout.Element ce = matchCase(e, value); - unparseUsing(ce.body, fixups, in, out); - break; - case EK_CALL: - assert(e.body.length == 1); - assert(e.body[0].kind == EK_CBLE); - unparseUsing(e.body[0].body, fixups, in, out); - break; - case EK_REF: - Entry globalRef = in.getRef(bandIndex); - int localRef; - if (globalRef != null) { - // It's a one-element array, really an lvalue. - fixups[0] = Fixups.addRefWithLoc(fixups[0], out.size(), globalRef); - localRef = 0; // placeholder for fixups - } else { - localRef = 0; // fixed null value - } - unparseInt(e, localRef, out); - break; - default: assert(false); continue; - } - } - } - - private static - void unparseInt(Layout.Element e, int value, ByteArrayOutputStream out) { - int loBits = e.len * 8; - if (loBits == 0) { - // It is not stored at all ('V' layout). - return; - } - if (loBits < 32) { - int hiBits = 32 - loBits; - int codedValue; - if (e.flagTest(EF_SIGN)) - codedValue = (value << hiBits) >> hiBits; - else - codedValue = (value << hiBits) >>> hiBits; - if (codedValue != value) - throw new InternalError("cannot code in "+e.len+" bytes: "+value); - } - // Write in big-endian order: - for (int bitPos = loBits; (bitPos -= 8) >= 0; ) { - out.write((byte)(value >>> bitPos)); - } - } - -/* - /// Testing. - public static void main(String av[]) { - int maxVal = 12; - int iters = 0; - boolean verbose; - int ap = 0; - while (ap < av.length) { - if (!av[ap].startsWith("-")) break; - if (av[ap].startsWith("-m")) - maxVal = Integer.parseInt(av[ap].substring(2)); - else if (av[ap].startsWith("-i")) - iters = Integer.parseInt(av[ap].substring(2)); - else - throw new RuntimeException("Bad option: "+av[ap]); - ap++; - } - verbose = (iters == 0); - if (iters <= 0) iters = 1; - if (ap == av.length) { - av = new String[] { - "HH", // ClassFile.version - "RUH", // SourceFile - "RCHRDNH", // EnclosingMethod - "KQH", // ConstantValue - "NH[RCH]", // Exceptions - "NH[PHH]", // LineNumberTable - "NH[PHOHRUHRSHH]", // LocalVariableTable - "NH[PHPOHIIH]", // CharacterRangeTable - "NH[PHHII]", // CoverageTable - "NH[RCHRCNHRUNHFH]", // InnerClasses - "NH[RMHNH[KLH]]", // BootstrapMethods - "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]", // Code - "=AnnotationDefault", - // Like metadata, but with a compact tag set: - "[NH[(1)]]" - +"[NH[(1)]]" - +"[RSHNH[RUH(1)]]" - +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(-1)](6)[NH[(0)]]()[]]", - "" - }; - ap = 0; - } - Utils.currentInstance.set(new PackerImpl()); - final int[][] counts = new int[2][3]; // int bci ref - final Entry[] cpMap = new Entry[maxVal+1]; - for (int i = 0; i < cpMap.length; i++) { - if (i == 0) continue; // 0 => null - cpMap[i] = ConstantPool.getLiteralEntry(new Integer(i)); - } - Package.Class cls = new Package().new Class(""); - cls.cpMap = cpMap; - class TestValueStream extends ValueStream { - java.util.Random rand = new java.util.Random(0); - ArrayList history = new ArrayList(); - int ckidx = 0; - int maxVal; - boolean verbose; - void reset() { history.clear(); ckidx = 0; } - public int getInt(int bandIndex) { - counts[0][0]++; - int value = rand.nextInt(maxVal+1); - history.add(new Integer(bandIndex)); - history.add(new Integer(value)); - return value; - } - public void putInt(int bandIndex, int token) { - counts[1][0]++; - if (verbose) - System.out.print(" "+bandIndex+":"+token); - // Make sure this put parallels a previous get: - int check0 = ((Integer)history.get(ckidx+0)).intValue(); - int check1 = ((Integer)history.get(ckidx+1)).intValue(); - if (check0 != bandIndex || check1 != token) { - if (!verbose) - System.out.println(history.subList(0, ckidx)); - System.out.println(" *** Should be "+check0+":"+check1); - throw new RuntimeException("Failed test!"); - } - ckidx += 2; - } - public Entry getRef(int bandIndex) { - counts[0][2]++; - int value = getInt(bandIndex); - if (value < 0 || value > maxVal) { - System.out.println(" *** Unexpected ref code "+value); - return ConstantPool.getLiteralEntry(new Integer(value)); - } - return cpMap[value]; - } - public void putRef(int bandIndex, Entry ref) { - counts[1][2]++; - if (ref == null) { - putInt(bandIndex, 0); - return; - } - Number refValue = null; - if (ref instanceof ConstantPool.NumberEntry) - refValue = ((ConstantPool.NumberEntry)ref).numberValue(); - int value; - if (!(refValue instanceof Integer)) { - System.out.println(" *** Unexpected ref "+ref); - value = -1; - } else { - value = ((Integer)refValue).intValue(); - } - putInt(bandIndex, value); - } - public int encodeBCI(int bci) { - counts[1][1]++; - // move LSB to MSB of low byte - int code = (bci >> 8) << 8; // keep high bits - code += (bci & 0xFE) >> 1; - code += (bci & 0x01) << 7; - return code ^ (8<<8); // mark it clearly as coded - } - public int decodeBCI(int bciCode) { - counts[0][1]++; - bciCode ^= (8<<8); // remove extra mark - int bci = (bciCode >> 8) << 8; // keep high bits - bci += (bciCode & 0x7F) << 1; - bci += (bciCode & 0x80) >> 7; - return bci; - } - } - TestValueStream tts = new TestValueStream(); - tts.maxVal = maxVal; - tts.verbose = verbose; - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - for (int i = 0; i < (1 << 30); i = (i + 1) * 5) { - int ei = tts.encodeBCI(i); - int di = tts.decodeBCI(ei); - if (di != i) System.out.println("i="+Integer.toHexString(i)+ - " ei="+Integer.toHexString(ei)+ - " di="+Integer.toHexString(di)); - } - while (iters-- > 0) { - for (int i = ap; i < av.length; i++) { - String layout = av[i]; - if (layout.startsWith("=")) { - String name = layout.substring(1); - for (Attribute a : standardDefs.values()) { - if (a.name().equals(name)) { - layout = a.layout().layout(); - break; - } - } - if (layout.startsWith("=")) { - System.out.println("Could not find "+name+" in "+standardDefs.values()); - } - } - Layout self = new Layout(0, "Foo", layout); - if (verbose) { - System.out.print("/"+layout+"/ => "); - System.out.println(Arrays.asList(self.elems)); - } - buf.reset(); - tts.reset(); - Object fixups = self.unparse(tts, buf); - byte[] bytes = buf.toByteArray(); - // Attach the references to the byte array. - Fixups.setBytes(fixups, bytes); - // Patch the references to their frozen values. - Fixups.finishRefs(fixups, bytes, new Index("test", cpMap)); - if (verbose) { - System.out.print(" bytes: {"); - for (int j = 0; j < bytes.length; j++) { - System.out.print(" "+bytes[j]); - } - System.out.println("}"); - } - if (verbose) { - System.out.print(" parse: {"); - } - self.parse(cls, bytes, 0, bytes.length, tts); - if (verbose) { - System.out.println("}"); - } - } - } - for (int j = 0; j <= 1; j++) { - System.out.print("values "+(j==0?"read":"written")+": {"); - for (int k = 0; k < counts[j].length; k++) { - System.out.print(" "+counts[j][k]); - } - System.out.println(" }"); - } - } -//*/ -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java deleted file mode 100644 index 4e453d84cba..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ /dev/null @@ -1,2762 +0,0 @@ -/* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import com.sun.java.util.jar.pack.ConstantPool.Index; -import com.sun.java.util.jar.pack.Package.Class.Field; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FilterInputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.jar.Pack200; -import static com.sun.java.util.jar.pack.Constants.*; -import java.util.LinkedList; - -/** - * Define the structure and ordering of "bands" in a packed file. - * @author John Rose - */ -@SuppressWarnings({"removal"}) -abstract -class BandStructure { - static final int MAX_EFFORT = 9; - static final int MIN_EFFORT = 1; - static final int DEFAULT_EFFORT = 5; - - // Inherit options from Pack200: - PropMap p200 = Utils.currentPropMap(); - - int verbose = p200.getInteger(Utils.DEBUG_VERBOSE); - int effort = p200.getInteger(Pack200.Packer.EFFORT); - { if (effort == 0) effort = DEFAULT_EFFORT; } - boolean optDumpBands = p200.getBoolean(Utils.COM_PREFIX+"dump.bands"); - boolean optDebugBands = p200.getBoolean(Utils.COM_PREFIX+"debug.bands"); - - // Various heuristic options. - boolean optVaryCodings = !p200.getBoolean(Utils.COM_PREFIX+"no.vary.codings"); - boolean optBigStrings = !p200.getBoolean(Utils.COM_PREFIX+"no.big.strings"); - - protected abstract Index getCPIndex(byte tag); - - // Local copy of highest class version. - private Package.Version highestClassVersion = null; - - /** Call this exactly once, early, to specify the archive major version. */ - public void initHighestClassVersion(Package.Version highestClassVersion) throws IOException { - if (this.highestClassVersion != null) { - throw new IOException( - "Highest class major version is already initialized to " + - this.highestClassVersion + "; new setting is " + highestClassVersion); - } - this.highestClassVersion = highestClassVersion; - adjustToClassVersion(); - } - - public Package.Version getHighestClassVersion() { - return highestClassVersion; - } - - private final boolean isReader = this instanceof PackageReader; - - protected BandStructure() {} - - static final Coding BYTE1 = Coding.of(1,256); - - static final Coding CHAR3 = Coding.of(3,128); - // Note: Tried sharper (3,16) with no post-zip benefit. - - // This is best used with BCI values: - static final Coding BCI5 = Coding.of(5,4); // mostly 1-byte offsets - static final Coding BRANCH5 = Coding.of(5,4,2); // mostly forward branches - - static final Coding UNSIGNED5 = Coding.of(5,64); - static final Coding UDELTA5 = UNSIGNED5.getDeltaCoding(); - // "sharp" (5,64) zips 0.4% better than "medium" (5,128) - // It zips 1.1% better than "flat" (5,192) - - static final Coding SIGNED5 = Coding.of(5,64,1); //sharp - static final Coding DELTA5 = SIGNED5.getDeltaCoding(); - // Note: Tried (5,128,2) and (5,192,2) with no benefit. - - static final Coding MDELTA5 = Coding.of(5,64,2).getDeltaCoding(); - - private static final Coding[] basicCodings = { - // Table of "Canonical BHSD Codings" from Pack200 spec. - null, // _meta_default - - // Fixed-length codings: - Coding.of(1,256,0), - Coding.of(1,256,1), - Coding.of(1,256,0).getDeltaCoding(), - Coding.of(1,256,1).getDeltaCoding(), - Coding.of(2,256,0), - Coding.of(2,256,1), - Coding.of(2,256,0).getDeltaCoding(), - Coding.of(2,256,1).getDeltaCoding(), - Coding.of(3,256,0), - Coding.of(3,256,1), - Coding.of(3,256,0).getDeltaCoding(), - Coding.of(3,256,1).getDeltaCoding(), - Coding.of(4,256,0), - Coding.of(4,256,1), - Coding.of(4,256,0).getDeltaCoding(), - Coding.of(4,256,1).getDeltaCoding(), - - // Full-range variable-length codings: - Coding.of(5, 4,0), - Coding.of(5, 4,1), - Coding.of(5, 4,2), - Coding.of(5, 16,0), - Coding.of(5, 16,1), - Coding.of(5, 16,2), - Coding.of(5, 32,0), - Coding.of(5, 32,1), - Coding.of(5, 32,2), - Coding.of(5, 64,0), - Coding.of(5, 64,1), - Coding.of(5, 64,2), - Coding.of(5,128,0), - Coding.of(5,128,1), - Coding.of(5,128,2), - - Coding.of(5, 4,0).getDeltaCoding(), - Coding.of(5, 4,1).getDeltaCoding(), - Coding.of(5, 4,2).getDeltaCoding(), - Coding.of(5, 16,0).getDeltaCoding(), - Coding.of(5, 16,1).getDeltaCoding(), - Coding.of(5, 16,2).getDeltaCoding(), - Coding.of(5, 32,0).getDeltaCoding(), - Coding.of(5, 32,1).getDeltaCoding(), - Coding.of(5, 32,2).getDeltaCoding(), - Coding.of(5, 64,0).getDeltaCoding(), - Coding.of(5, 64,1).getDeltaCoding(), - Coding.of(5, 64,2).getDeltaCoding(), - Coding.of(5,128,0).getDeltaCoding(), - Coding.of(5,128,1).getDeltaCoding(), - Coding.of(5,128,2).getDeltaCoding(), - - // Variable length subrange codings: - Coding.of(2,192,0), - Coding.of(2,224,0), - Coding.of(2,240,0), - Coding.of(2,248,0), - Coding.of(2,252,0), - - Coding.of(2, 8,0).getDeltaCoding(), - Coding.of(2, 8,1).getDeltaCoding(), - Coding.of(2, 16,0).getDeltaCoding(), - Coding.of(2, 16,1).getDeltaCoding(), - Coding.of(2, 32,0).getDeltaCoding(), - Coding.of(2, 32,1).getDeltaCoding(), - Coding.of(2, 64,0).getDeltaCoding(), - Coding.of(2, 64,1).getDeltaCoding(), - Coding.of(2,128,0).getDeltaCoding(), - Coding.of(2,128,1).getDeltaCoding(), - Coding.of(2,192,0).getDeltaCoding(), - Coding.of(2,192,1).getDeltaCoding(), - Coding.of(2,224,0).getDeltaCoding(), - Coding.of(2,224,1).getDeltaCoding(), - Coding.of(2,240,0).getDeltaCoding(), - Coding.of(2,240,1).getDeltaCoding(), - Coding.of(2,248,0).getDeltaCoding(), - Coding.of(2,248,1).getDeltaCoding(), - - Coding.of(3,192,0), - Coding.of(3,224,0), - Coding.of(3,240,0), - Coding.of(3,248,0), - Coding.of(3,252,0), - - Coding.of(3, 8,0).getDeltaCoding(), - Coding.of(3, 8,1).getDeltaCoding(), - Coding.of(3, 16,0).getDeltaCoding(), - Coding.of(3, 16,1).getDeltaCoding(), - Coding.of(3, 32,0).getDeltaCoding(), - Coding.of(3, 32,1).getDeltaCoding(), - Coding.of(3, 64,0).getDeltaCoding(), - Coding.of(3, 64,1).getDeltaCoding(), - Coding.of(3,128,0).getDeltaCoding(), - Coding.of(3,128,1).getDeltaCoding(), - Coding.of(3,192,0).getDeltaCoding(), - Coding.of(3,192,1).getDeltaCoding(), - Coding.of(3,224,0).getDeltaCoding(), - Coding.of(3,224,1).getDeltaCoding(), - Coding.of(3,240,0).getDeltaCoding(), - Coding.of(3,240,1).getDeltaCoding(), - Coding.of(3,248,0).getDeltaCoding(), - Coding.of(3,248,1).getDeltaCoding(), - - Coding.of(4,192,0), - Coding.of(4,224,0), - Coding.of(4,240,0), - Coding.of(4,248,0), - Coding.of(4,252,0), - - Coding.of(4, 8,0).getDeltaCoding(), - Coding.of(4, 8,1).getDeltaCoding(), - Coding.of(4, 16,0).getDeltaCoding(), - Coding.of(4, 16,1).getDeltaCoding(), - Coding.of(4, 32,0).getDeltaCoding(), - Coding.of(4, 32,1).getDeltaCoding(), - Coding.of(4, 64,0).getDeltaCoding(), - Coding.of(4, 64,1).getDeltaCoding(), - Coding.of(4,128,0).getDeltaCoding(), - Coding.of(4,128,1).getDeltaCoding(), - Coding.of(4,192,0).getDeltaCoding(), - Coding.of(4,192,1).getDeltaCoding(), - Coding.of(4,224,0).getDeltaCoding(), - Coding.of(4,224,1).getDeltaCoding(), - Coding.of(4,240,0).getDeltaCoding(), - Coding.of(4,240,1).getDeltaCoding(), - Coding.of(4,248,0).getDeltaCoding(), - Coding.of(4,248,1).getDeltaCoding(), - - null - }; - private static final Map basicCodingIndexes; - static { - assert(basicCodings[_meta_default] == null); - assert(basicCodings[_meta_canon_min] != null); - assert(basicCodings[_meta_canon_max] != null); - Map map = new HashMap<>(); - for (int i = 0; i < basicCodings.length; i++) { - Coding c = basicCodings[i]; - if (c == null) continue; - assert(i >= _meta_canon_min); - assert(i <= _meta_canon_max); - map.put(c, i); - } - basicCodingIndexes = map; - } - public static Coding codingForIndex(int i) { - return i < basicCodings.length ? basicCodings[i] : null; - } - public static int indexOf(Coding c) { - Integer i = basicCodingIndexes.get(c); - if (i == null) return 0; - return i.intValue(); - } - public static Coding[] getBasicCodings() { - return basicCodings.clone(); - } - - protected byte[] bandHeaderBytes; // used for input only - protected int bandHeaderBytePos; // BHB read pointer, for input only - protected int bandHeaderBytePos0; // for debug - - protected CodingMethod getBandHeader(int XB, Coding regularCoding) { - CodingMethod[] res = {null}; - // push back XB onto the band header bytes - bandHeaderBytes[--bandHeaderBytePos] = (byte) XB; - bandHeaderBytePos0 = bandHeaderBytePos; - // scan forward through XB and any additional band header bytes - bandHeaderBytePos = parseMetaCoding(bandHeaderBytes, - bandHeaderBytePos, - regularCoding, - res); - return res[0]; - } - - public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod[] res) { - if ((bytes[pos] & 0xFF) == _meta_default) { - res[0] = dflt; - return pos+1; - } - int pos2; - pos2 = Coding.parseMetaCoding(bytes, pos, dflt, res); - if (pos2 > pos) return pos2; - pos2 = PopulationCoding.parseMetaCoding(bytes, pos, dflt, res); - if (pos2 > pos) return pos2; - pos2 = AdaptiveCoding.parseMetaCoding(bytes, pos, dflt, res); - if (pos2 > pos) return pos2; - throw new RuntimeException("Bad meta-coding op "+(bytes[pos]&0xFF)); - } - - static final int SHORT_BAND_HEURISTIC = 100; - - public static final int NO_PHASE = 0; - - // package writing phases: - public static final int COLLECT_PHASE = 1; // collect data before write - public static final int FROZEN_PHASE = 3; // no longer collecting - public static final int WRITE_PHASE = 5; // ready to write bytes - - // package reading phases: - public static final int EXPECT_PHASE = 2; // gather expected counts - public static final int READ_PHASE = 4; // ready to read bytes - public static final int DISBURSE_PHASE = 6; // pass out data after read - - public static final int DONE_PHASE = 8; // done writing or reading - - static boolean phaseIsRead(int p) { - return (p % 2) == 0; - } - static int phaseCmp(int p0, int p1) { - assert((p0 % 2) == (p1 % 2) || (p0 % 8) == 0 || (p1 % 8) == 0); - return p0 - p1; - } - - /** The packed file is divided up into a number of segments. - * Most segments are typed as ValueBand, strongly-typed sequences - * of integer values, all interpreted in a single way. - * A few segments are ByteBands, which hetergeneous sequences - * of bytes. - * - * The two phases for writing a packed file are COLLECT and WRITE. - * 1. When writing a packed file, each band collects - * data in an ad-hoc order. - * 2. At the end, each band is assigned a coding scheme, - * and then all the bands are written in their global order. - * - * The three phases for reading a packed file are EXPECT, READ, - * and DISBURSE. - * 1. For each band, the expected number of integers is determined. - * 2. The data is actually read from the file into the band. - * 3. The band pays out its values as requested, in an ad hoc order. - * - * When the last phase of a band is done, it is marked so (DONE). - * Clearly, these phases must be properly ordered WRT each other. - */ - abstract class Band { - private int phase = NO_PHASE; - private final String name; - - private int valuesExpected; - - protected long outputSize = -1; // cache - - public final Coding regularCoding; - - public final int seqForDebug; - public int elementCountForDebug; - - - protected Band(String name, Coding regularCoding) { - this.name = name; - this.regularCoding = regularCoding; - this.seqForDebug = ++nextSeqForDebug; - if (verbose > 2) - Utils.log.fine("Band "+seqForDebug+" is "+name); - // caller must call init - } - - public Band init() { - // Cannot due this from the constructor, because constructor - // may wish to initialize some subclass variables. - // Set initial phase for reading or writing: - if (isReader) - readyToExpect(); - else - readyToCollect(); - return this; - } - - // common operations - boolean isReader() { return isReader; } - int phase() { return phase; } - String name() { return name; } - - /** Return -1 if data buffer not allocated, else max length. */ - public abstract int capacity(); - - /** Allocate data buffer to specified length. */ - protected abstract void setCapacity(int cap); - - /** Return current number of values in buffer, which must exist. */ - public abstract int length(); - - protected abstract int valuesRemainingForDebug(); - - public final int valuesExpected() { - return valuesExpected; - } - - /** Write out bytes, encoding the values. */ - public final void writeTo(OutputStream out) throws IOException { - assert(assertReadyToWriteTo(this, out)); - setPhase(WRITE_PHASE); - // subclasses continue by writing their contents to output - writeDataTo(out); - doneWriting(); - } - - abstract void chooseBandCodings() throws IOException; - - public final long outputSize() { - if (outputSize >= 0) { - long size = outputSize; - assert(size == computeOutputSize()); - return size; - } - return computeOutputSize(); - } - - protected abstract long computeOutputSize(); - - protected abstract void writeDataTo(OutputStream out) throws IOException; - - /** Expect a certain number of values. */ - void expectLength(int l) { - assert(assertPhase(this, EXPECT_PHASE)); - assert(valuesExpected == 0); // all at once - assert(l >= 0); - valuesExpected = l; - } - /** Expect more values. (Multiple calls accumulate.) */ - void expectMoreLength(int l) { - assert(assertPhase(this, EXPECT_PHASE)); - valuesExpected += l; - } - - - /// Phase change markers. - - private void readyToCollect() { // called implicitly by constructor - setCapacity(1); - setPhase(COLLECT_PHASE); - } - protected void doneWriting() { - assert(assertPhase(this, WRITE_PHASE)); - setPhase(DONE_PHASE); - } - private void readyToExpect() { // called implicitly by constructor - setPhase(EXPECT_PHASE); - } - /** Read in bytes, decoding the values. */ - public final void readFrom(InputStream in) throws IOException { - assert(assertReadyToReadFrom(this, in)); - setCapacity(valuesExpected()); - setPhase(READ_PHASE); - // subclasses continue by reading their contents from input: - readDataFrom(in); - readyToDisburse(); - } - protected abstract void readDataFrom(InputStream in) throws IOException; - protected void readyToDisburse() { - if (verbose > 1) Utils.log.fine("readyToDisburse "+this); - setPhase(DISBURSE_PHASE); - } - public void doneDisbursing() { - assert(assertPhase(this, DISBURSE_PHASE)); - setPhase(DONE_PHASE); - } - public final void doneWithUnusedBand() { - if (isReader) { - assert(assertPhase(this, EXPECT_PHASE)); - assert(valuesExpected() == 0); - // Fast forward: - setPhase(READ_PHASE); - setPhase(DISBURSE_PHASE); - setPhase(DONE_PHASE); - } else { - setPhase(FROZEN_PHASE); - } - } - - protected void setPhase(int newPhase) { - assert(assertPhaseChangeOK(this, phase, newPhase)); - this.phase = newPhase; - } - - protected int lengthForDebug = -1; // DEBUG ONLY - @Override - public String toString() { // DEBUG ONLY - int length = (lengthForDebug != -1 ? lengthForDebug : length()); - String str = name; - if (length != 0) - str += "[" + length + "]"; - if (elementCountForDebug != 0) - str += "(" + elementCountForDebug + ")"; - return str; - } - } - - class ValueBand extends Band { - private int[] values; // must be null in EXPECT phase - private int length; - private int valuesDisbursed; - - private CodingMethod bandCoding; - private byte[] metaCoding; - - protected ValueBand(String name, Coding regularCoding) { - super(name, regularCoding); - } - - @Override - public int capacity() { - return values == null ? -1 : values.length; - } - - /** Declare predicted or needed capacity. */ - @Override - protected void setCapacity(int cap) { - assert(length <= cap); - if (cap == -1) { values = null; return; } - values = realloc(values, cap); - } - - @Override - public int length() { - return length; - } - @Override - protected int valuesRemainingForDebug() { - return length - valuesDisbursed; - } - protected int valueAtForDebug(int i) { - return values[i]; - } - - void patchValue(int i, int value) { - // Only one use for this. - assert(this == archive_header_S); - assert(i == AH_ARCHIVE_SIZE_HI || i == AH_ARCHIVE_SIZE_LO); - assert(i < length); // must have already output a dummy - values[i] = value; - outputSize = -1; // decache - } - - protected void initializeValues(int[] values) { - assert(assertCanChangeLength(this)); - assert(length == 0); - this.values = values; - this.length = values.length; - } - - /** Collect one value, or store one decoded value. */ - protected void addValue(int x) { - assert(assertCanChangeLength(this)); - if (length == values.length) - setCapacity(length < 1000 ? length * 10 : length * 2); - values[length++] = x; - } - - private boolean canVaryCoding() { - if (!optVaryCodings) return false; - if (length == 0) return false; - // Can't read band_headers w/o the archive header: - if (this == archive_header_0) return false; - if (this == archive_header_S) return false; - if (this == archive_header_1) return false; - // BYTE1 bands can't vary codings, but the others can. - // All that's needed for the initial escape is at least - // 256 negative values or more than 256 non-negative values - return (regularCoding.min() <= -256 || regularCoding.max() >= 256); - } - - private boolean shouldVaryCoding() { - assert(canVaryCoding()); - if (effort < MAX_EFFORT && length < SHORT_BAND_HEURISTIC) - return false; - return true; - } - - @Override - protected void chooseBandCodings() throws IOException { - boolean canVary = canVaryCoding(); - if (!canVary || !shouldVaryCoding()) { - if (regularCoding.canRepresent(values, 0, length)) { - bandCoding = regularCoding; - } else { - assert(canVary); - if (verbose > 1) - Utils.log.fine("regular coding fails in band "+name()); - bandCoding = UNSIGNED5; - } - outputSize = -1; - } else { - int[] sizes = {0,0}; - bandCoding = chooseCoding(values, 0, length, - regularCoding, name(), - sizes); - outputSize = sizes[CodingChooser.BYTE_SIZE]; - if (outputSize == 0) // CodingChooser failed to size it. - outputSize = -1; - } - - // Compute and save the meta-coding bytes also. - if (bandCoding != regularCoding) { - metaCoding = bandCoding.getMetaCoding(regularCoding); - if (verbose > 1) { - Utils.log.fine("alternate coding "+this+" "+bandCoding); - } - } else if (canVary && - decodeEscapeValue(values[0], regularCoding) >= 0) { - // Need an explicit default. - metaCoding = defaultMetaCoding; - } else { - // Common case: Zero bytes of meta coding. - metaCoding = noMetaCoding; - } - if (metaCoding.length > 0 - && (verbose > 2 || verbose > 1 && metaCoding.length > 1)) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < metaCoding.length; i++) { - if (i == 1) sb.append(" /"); - sb.append(" ").append(metaCoding[i] & 0xFF); - } - Utils.log.fine(" meta-coding "+sb); - } - - assert((outputSize < 0) || - !(bandCoding instanceof Coding) || - (outputSize == ((Coding)bandCoding) - .getLength(values, 0, length))) - : (bandCoding+" : "+ - outputSize+" != "+ - ((Coding)bandCoding).getLength(values, 0, length) - +" ?= "+getCodingChooser().computeByteSize(bandCoding,values,0,length) - ); - - // Compute outputSize of the escape value X, if any. - if (metaCoding.length > 0) { - // First byte XB of meta-coding is treated specially, - // but any other bytes go into the band headers band. - // This must be done before any other output happens. - if (outputSize >= 0) - outputSize += computeEscapeSize(); // good cache - // Other bytes go into band_headers. - for (int i = 1; i < metaCoding.length; i++) { - band_headers.putByte(metaCoding[i] & 0xFF); - } - } - } - - @Override - protected long computeOutputSize() { - outputSize = getCodingChooser().computeByteSize(bandCoding, - values, 0, length); - assert(outputSize < Integer.MAX_VALUE); - outputSize += computeEscapeSize(); - return outputSize; - } - - protected int computeEscapeSize() { - if (metaCoding.length == 0) return 0; - int XB = metaCoding[0] & 0xFF; - int X = encodeEscapeValue(XB, regularCoding); - return regularCoding.setD(0).getLength(X); - } - - @Override - protected void writeDataTo(OutputStream out) throws IOException { - if (length == 0) return; // nothing to write - long len0 = 0; - if (out == outputCounter) { - len0 = outputCounter.getCount(); - } - if (metaCoding.length > 0) { - int XB = metaCoding[0] & 0xFF; - // We need an explicit band header, either because - // there is a non-default coding method, or because - // the first value would be parsed as an escape value. - int X = encodeEscapeValue(XB, regularCoding); - //System.out.println("X="+X+" XB="+XB+" in "+this); - regularCoding.setD(0).writeTo(out, X); - } - bandCoding.writeArrayTo(out, values, 0, length); - if (out == outputCounter) { - assert(outputSize == outputCounter.getCount() - len0) - : (outputSize+" != "+outputCounter.getCount()+"-"+len0); - } - if (optDumpBands) dumpBand(); - } - - @Override - protected void readDataFrom(InputStream in) throws IOException { - length = valuesExpected(); - if (length == 0) return; // nothing to read - if (verbose > 1) - Utils.log.fine("Reading band "+this); - if (!canVaryCoding()) { - bandCoding = regularCoding; - metaCoding = noMetaCoding; - } else { - assert(in.markSupported()); // input must be buffered - in.mark(Coding.B_MAX); - int X = regularCoding.setD(0).readFrom(in); - int XB = decodeEscapeValue(X, regularCoding); - if (XB < 0) { - // Do not consume this value. No alternate coding. - in.reset(); - bandCoding = regularCoding; - metaCoding = noMetaCoding; - } else if (XB == _meta_default) { - bandCoding = regularCoding; - metaCoding = defaultMetaCoding; - } else { - if (verbose > 2) - Utils.log.fine("found X="+X+" => XB="+XB); - bandCoding = getBandHeader(XB, regularCoding); - // This is really used only by dumpBands. - int p0 = bandHeaderBytePos0; - int p1 = bandHeaderBytePos; - metaCoding = new byte[p1-p0]; - System.arraycopy(bandHeaderBytes, p0, - metaCoding, 0, metaCoding.length); - } - } - if (bandCoding != regularCoding) { - if (verbose > 1) - Utils.log.fine(name()+": irregular coding "+bandCoding); - } - bandCoding.readArrayFrom(in, values, 0, length); - if (optDumpBands) dumpBand(); - } - - @Override - public void doneDisbursing() { - super.doneDisbursing(); - values = null; // for GC - } - - private void dumpBand() throws IOException { - assert(optDumpBands); - try (PrintStream ps = new PrintStream(getDumpStream(this, ".txt"))) { - String irr = (bandCoding == regularCoding) ? "" : " irregular"; - ps.print("# length="+length+ - " size="+outputSize()+ - irr+" coding="+bandCoding); - if (metaCoding != noMetaCoding) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < metaCoding.length; i++) { - if (i == 1) sb.append(" /"); - sb.append(" ").append(metaCoding[i] & 0xFF); - } - ps.print(" //header: "+sb); - } - printArrayTo(ps, values, 0, length); - } - try (OutputStream ds = getDumpStream(this, ".bnd")) { - bandCoding.writeArrayTo(ds, values, 0, length); - } - } - - /** Disburse one value. */ - protected int getValue() { - assert(phase() == DISBURSE_PHASE); - // when debugging return a zero if lengths are zero - if (optDebugBands && length == 0 && valuesDisbursed == length) - return 0; - assert(valuesDisbursed <= length); - return values[valuesDisbursed++]; - } - - /** Reset for another pass over the same value set. */ - public void resetForSecondPass() { - assert(phase() == DISBURSE_PHASE); - assert(valuesDisbursed == length()); // 1st pass is complete - valuesDisbursed = 0; - } - } - - class ByteBand extends Band { - private ByteArrayOutputStream bytes; // input buffer - private ByteArrayOutputStream bytesForDump; - private InputStream in; - - public ByteBand(String name) { - super(name, BYTE1); - } - - @Override - public int capacity() { - return bytes == null ? -1 : Integer.MAX_VALUE; - } - @Override - protected void setCapacity(int cap) { - assert(bytes == null); // do this just once - bytes = new ByteArrayOutputStream(cap); - } - public void destroy() { - lengthForDebug = length(); - bytes = null; - } - - @Override - public int length() { - return bytes == null ? -1 : bytes.size(); - } - public void reset() { - bytes.reset(); - } - @Override - protected int valuesRemainingForDebug() { - return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available(); - } - - @Override - protected void chooseBandCodings() throws IOException { - // No-op. - assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0); - assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0); - } - - @Override - protected long computeOutputSize() { - // do not cache - return bytes.size(); - } - - @Override - public void writeDataTo(OutputStream out) throws IOException { - if (length() == 0) return; - bytes.writeTo(out); - if (optDumpBands) dumpBand(); - destroy(); // done with the bits! - } - - private void dumpBand() throws IOException { - assert(optDumpBands); - try (OutputStream ds = getDumpStream(this, ".bnd")) { - if (bytesForDump != null) - bytesForDump.writeTo(ds); - else - bytes.writeTo(ds); - } - } - - @Override - public void readDataFrom(InputStream in) throws IOException { - int vex = valuesExpected(); - if (vex == 0) return; - if (verbose > 1) { - lengthForDebug = vex; - Utils.log.fine("Reading band "+this); - lengthForDebug = -1; - } - byte[] buf = new byte[Math.min(vex, 1<<14)]; - while (vex > 0) { - int nr = in.read(buf, 0, Math.min(vex, buf.length)); - if (nr < 0) throw new EOFException(); - bytes.write(buf, 0, nr); - vex -= nr; - } - if (optDumpBands) dumpBand(); - } - - @Override - public void readyToDisburse() { - in = new ByteArrayInputStream(bytes.toByteArray()); - super.readyToDisburse(); - } - - @Override - public void doneDisbursing() { - super.doneDisbursing(); - if (optDumpBands - && bytesForDump != null && bytesForDump.size() > 0) { - try { - dumpBand(); - } catch (IOException ee) { - throw new RuntimeException(ee); - } - } - in = null; // GC - bytes = null; // GC - bytesForDump = null; // GC - } - - // alternative to readFrom: - public void setInputStreamFrom(InputStream in) throws IOException { - assert(bytes == null); - assert(assertReadyToReadFrom(this, in)); - setPhase(READ_PHASE); - this.in = in; - if (optDumpBands) { - // Tap the stream. - bytesForDump = new ByteArrayOutputStream(); - this.in = new FilterInputStream(in) { - @Override - public int read() throws IOException { - int ch = in.read(); - if (ch >= 0) bytesForDump.write(ch); - return ch; - } - @Override - public int read(byte b[], int off, int len) throws IOException { - int nr = in.read(b, off, len); - if (nr >= 0) bytesForDump.write(b, off, nr); - return nr; - } - }; - } - super.readyToDisburse(); - } - - public OutputStream collectorStream() { - assert(phase() == COLLECT_PHASE); - assert(bytes != null); - return bytes; - } - - public InputStream getInputStream() { - assert(phase() == DISBURSE_PHASE); - assert(in != null); - return in; - } - public int getByte() throws IOException { - int b = getInputStream().read(); - if (b < 0) throw new EOFException(); - return b; - } - public void putByte(int b) throws IOException { - assert(b == (b & 0xFF)); - collectorStream().write(b); - } - @Override - public String toString() { - return "byte "+super.toString(); - } - } - - class IntBand extends ValueBand { - // The usual coding for bands is 7bit/5byte/delta. - public IntBand(String name, Coding regularCoding) { - super(name, regularCoding); - } - - public void putInt(int x) { - assert(phase() == COLLECT_PHASE); - addValue(x); - } - - public int getInt() { - return getValue(); - } - /** Return the sum of all values in this band. */ - public int getIntTotal() { - assert(phase() == DISBURSE_PHASE); - // assert that this is the whole pass; no other reads allowed - assert(valuesRemainingForDebug() == length()); - int total = 0; - for (int k = length(); k > 0; k--) { - total += getInt(); - } - resetForSecondPass(); - return total; - } - /** Return the occurrence count of a specific value in this band. */ - public int getIntCount(int value) { - assert(phase() == DISBURSE_PHASE); - // assert that this is the whole pass; no other reads allowed - assert(valuesRemainingForDebug() == length()); - int total = 0; - for (int k = length(); k > 0; k--) { - if (getInt() == value) { - total += 1; - } - } - resetForSecondPass(); - return total; - } - } - - static int getIntTotal(int[] values) { - int total = 0; - for (int i = 0; i < values.length; i++) { - total += values[i]; - } - return total; - } - - class CPRefBand extends ValueBand { - Index index; - boolean nullOK; - - public CPRefBand(String name, Coding regularCoding, byte cpTag, boolean nullOK) { - super(name, regularCoding); - this.nullOK = nullOK; - if (cpTag != CONSTANT_None) - setBandIndex(this, cpTag); - } - public CPRefBand(String name, Coding regularCoding, byte cpTag) { - this(name, regularCoding, cpTag, false); - } - public CPRefBand(String name, Coding regularCoding, Object undef) { - this(name, regularCoding, CONSTANT_None, false); - } - - public void setIndex(Index index) { - this.index = index; - } - - protected void readDataFrom(InputStream in) throws IOException { - super.readDataFrom(in); - assert(assertValidCPRefs(this)); - } - - /** Write a constant pool reference. */ - public void putRef(Entry e) { - addValue(encodeRefOrNull(e, index)); - } - public void putRef(Entry e, Index index) { - assert(this.index == null); - addValue(encodeRefOrNull(e, index)); - } - public void putRef(Entry e, byte cptag) { - putRef(e, getCPIndex(cptag)); - } - - public Entry getRef() { - if (index == null) Utils.log.warning("No index for "+this); - assert(index != null); - return decodeRefOrNull(getValue(), index); - } - public Entry getRef(Index index) { - assert(this.index == null); - return decodeRefOrNull(getValue(), index); - } - public Entry getRef(byte cptag) { - return getRef(getCPIndex(cptag)); - } - - private int encodeRefOrNull(Entry e, Index index) { - int nonNullCode; // NNC is the coding which assumes nulls are rare - if (e == null) { - nonNullCode = -1; // negative values are rare - } else { - nonNullCode = encodeRef(e, index); - } - // If nulls are expected, increment, to make -1 code turn to 0. - return (nullOK ? 1 : 0) + nonNullCode; - } - private Entry decodeRefOrNull(int code, Index index) { - // Inverse to encodeRefOrNull... - int nonNullCode = code - (nullOK ? 1 : 0); - if (nonNullCode == -1) { - return null; - } else { - return decodeRef(nonNullCode, index); - } - } - } - - // Bootstrap support for CPRefBands. These are needed to record - // intended CP indexes, before the CP has been created. - private final List allKQBands = new ArrayList<>(); - private List needPredefIndex = new ArrayList<>(); - - - int encodeRef(Entry e, Index ix) { - if (ix == null) - throw new RuntimeException("null index for " + e.stringValue()); - int coding = ix.indexOf(e); - if (verbose > 2) - Utils.log.fine("putRef "+coding+" => "+e); - return coding; - } - - Entry decodeRef(int n, Index ix) { - if (n < 0 || n >= ix.size()) - Utils.log.warning("decoding bad ref "+n+" in "+ix); - Entry e = ix.getEntry(n); - if (verbose > 2) - Utils.log.fine("getRef "+n+" => "+e); - return e; - } - - private CodingChooser codingChooser; - protected CodingChooser getCodingChooser() { - if (codingChooser == null) { - codingChooser = new CodingChooser(effort, basicCodings); - if (codingChooser.stress != null - && this instanceof PackageWriter) { - // Twist the random state based on my first file. - // This sends each segment off in a different direction. - List classes = ((PackageWriter)this).pkg.classes; - if (!classes.isEmpty()) { - Package.Class cls = classes.get(0); - codingChooser.addStressSeed(cls.getName().hashCode()); - } - } - } - return codingChooser; - } - - public CodingMethod chooseCoding(int[] values, int start, int end, - Coding regular, String bandName, - int[] sizes) { - assert(optVaryCodings); - if (effort <= MIN_EFFORT) { - return regular; - } - CodingChooser cc = getCodingChooser(); - if (verbose > 1 || cc.verbose > 1) { - Utils.log.fine("--- chooseCoding "+bandName); - } - return cc.choose(values, start, end, regular, sizes); - } - - static final byte[] defaultMetaCoding = { _meta_default }; - static final byte[] noMetaCoding = {}; - - // The first value in a band is always coded with the default coding D. - // If this first value X is an escape value, it actually represents the - // first (and perhaps only) byte of a meta-coding. - // - // If D.S != 0 and D includes the range [-256..-1], - // the escape values are in that range, - // and the first byte XB is -1-X. - // - // If D.S == 0 and D includes the range [(D.L)..(D.L)+255], - // the escape values are in that range, - // and XB is X-(D.L). - // - // This representation is designed so that a band header is unlikely - // to be confused with the initial value of a headerless band, - // and yet so that a band header is likely to occupy only a byte or two. - // - // Result is in [0..255] if XB was successfully extracted, else -1. - // See section "Coding Specifier Meta-Encoding" in the JSR 200 spec. - protected static int decodeEscapeValue(int X, Coding regularCoding) { - // The first value in a band is always coded with the default coding D. - // If this first value X is an escape value, it actually represents the - // first (and perhaps only) byte of a meta-coding. - // Result is in [0..255] if XB was successfully extracted, else -1. - if (regularCoding.B() == 1 || regularCoding.L() == 0) - return -1; // degenerate regular coding (BYTE1) - if (regularCoding.S() != 0) { - if (-256 <= X && X <= -1 && regularCoding.min() <= -256) { - int XB = -1-X; - assert(XB >= 0 && XB < 256); - return XB; - } - } else { - int L = regularCoding.L(); - if (L <= X && X <= L+255 && regularCoding.max() >= L+255) { - int XB = X-L; - assert(XB >= 0 && XB < 256); - return XB; - } - } - return -1; // negative value for failure - } - // Inverse to decodeEscapeValue(). - protected static int encodeEscapeValue(int XB, Coding regularCoding) { - assert(XB >= 0 && XB < 256); - assert(regularCoding.B() > 1 && regularCoding.L() > 0); - int X; - if (regularCoding.S() != 0) { - assert(regularCoding.min() <= -256); - X = -1-XB; - } else { - int L = regularCoding.L(); - assert(regularCoding.max() >= L+255); - X = XB+L; - } - assert(decodeEscapeValue(X, regularCoding) == XB) - : (regularCoding+" XB="+XB+" X="+X); - return X; - } - - static { - boolean checkXB = false; - assert(checkXB = true); - if (checkXB) { - for (int i = 0; i < basicCodings.length; i++) { - Coding D = basicCodings[i]; - if (D == null) continue; - if (D.B() == 1) continue; - if (D.L() == 0) continue; - for (int XB = 0; XB <= 255; XB++) { - // The following exercises decodeEscapeValue also: - encodeEscapeValue(XB, D); - } - } - } - } - - class MultiBand extends Band { - MultiBand(String name, Coding regularCoding) { - super(name, regularCoding); - } - - @Override - public Band init() { - super.init(); - // This is all just to keep the asserts happy: - setCapacity(0); - if (phase() == EXPECT_PHASE) { - // Fast forward: - setPhase(READ_PHASE); - setPhase(DISBURSE_PHASE); - } - return this; - } - - Band[] bands = new Band[10]; - int bandCount = 0; - - int size() { - return bandCount; - } - Band get(int i) { - assert(i < bandCount); - return bands[i]; - } - Band[] toArray() { - return (Band[]) realloc(bands, bandCount); - } - - void add(Band b) { - assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1])); - if (bandCount == bands.length) { - bands = (Band[]) realloc(bands); - } - bands[bandCount++] = b; - } - - ByteBand newByteBand(String name) { - ByteBand b = new ByteBand(name); - b.init(); add(b); - return b; - } - IntBand newIntBand(String name) { - IntBand b = new IntBand(name, regularCoding); - b.init(); add(b); - return b; - } - IntBand newIntBand(String name, Coding regularCoding) { - IntBand b = new IntBand(name, regularCoding); - b.init(); add(b); - return b; - } - MultiBand newMultiBand(String name, Coding regularCoding) { - MultiBand b = new MultiBand(name, regularCoding); - b.init(); add(b); - return b; - } - CPRefBand newCPRefBand(String name, byte cpTag) { - CPRefBand b = new CPRefBand(name, regularCoding, cpTag); - b.init(); add(b); - return b; - } - CPRefBand newCPRefBand(String name, Coding regularCoding, - byte cpTag) { - CPRefBand b = new CPRefBand(name, regularCoding, cpTag); - b.init(); add(b); - return b; - } - CPRefBand newCPRefBand(String name, Coding regularCoding, - byte cpTag, boolean nullOK) { - CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK); - b.init(); add(b); - return b; - } - - int bandCount() { return bandCount; } - - private int cap = -1; - @Override - public int capacity() { return cap; } - @Override - public void setCapacity(int cap) { this.cap = cap; } - - @Override - public int length() { return 0; } - @Override - public int valuesRemainingForDebug() { return 0; } - - @Override - protected void chooseBandCodings() throws IOException { - // coding decision pass - for (int i = 0; i < bandCount; i++) { - Band b = bands[i]; - b.chooseBandCodings(); - } - } - - @Override - protected long computeOutputSize() { - // coding decision pass - long sum = 0; - for (int i = 0; i < bandCount; i++) { - Band b = bands[i]; - long bsize = b.outputSize(); - assert(bsize >= 0) : b; - sum += bsize; - } - // do not cache - return sum; - } - - @Override - protected void writeDataTo(OutputStream out) throws IOException { - long preCount = 0; - if (outputCounter != null) preCount = outputCounter.getCount(); - for (int i = 0; i < bandCount; i++) { - Band b = bands[i]; - b.writeTo(out); - if (outputCounter != null) { - long postCount = outputCounter.getCount(); - long len = postCount - preCount; - preCount = postCount; - if ((verbose > 0 && len > 0) || verbose > 1) { - Utils.log.info(" ...wrote "+len+" bytes from "+b); - } - } - } - } - - @Override - protected void readDataFrom(InputStream in) throws IOException { - assert(false); // not called? - for (int i = 0; i < bandCount; i++) { - Band b = bands[i]; - b.readFrom(in); - if ((verbose > 0 && b.length() > 0) || verbose > 1) { - Utils.log.info(" ...read "+b); - } - } - } - - @Override - public String toString() { - return "{"+bandCount()+" bands: "+super.toString()+"}"; - } - } - - /** - * An output stream which counts the number of bytes written. - */ - private static - class ByteCounter extends FilterOutputStream { - // (should go public under the name CountingOutputStream?) - - private long count; - - public ByteCounter(OutputStream out) { - super(out); - } - - public long getCount() { return count; } - public void setCount(long c) { count = c; } - - @Override - public void write(int b) throws IOException { - count++; - if (out != null) out.write(b); - } - @Override - public void write(byte b[], int off, int len) throws IOException { - count += len; - if (out != null) out.write(b, off, len); - } - @Override - public String toString() { - return String.valueOf(getCount()); - } - } - ByteCounter outputCounter; - - void writeAllBandsTo(OutputStream out) throws IOException { - // Wrap a byte-counter around the output stream. - outputCounter = new ByteCounter(out); - out = outputCounter; - all_bands.writeTo(out); - if (verbose > 0) { - long nbytes = outputCounter.getCount(); - Utils.log.info("Wrote total of "+nbytes+" bytes."); - assert(nbytes == archiveSize0+archiveSize1); - } - outputCounter = null; - } - - // random AO_XXX bits, decoded from the archive header - protected int archiveOptions; - - // archiveSize1 sizes most of the archive [archive_options..file_bits). - protected long archiveSize0; // size through archive_size_lo - protected long archiveSize1; // size reported in archive_header - protected int archiveNextCount; // reported in archive_header - - static final int AH_LENGTH_0 = 3; // archive_header_0 = {minver, majver, options} - static final int AH_LENGTH_MIN = 15; // observed in spec {header_0[3], cp_counts[8], class_counts[4]} - // Length contributions from optional archive size fields: - static final int AH_LENGTH_S = 2; // archive_header_S = optional {size_hi, size_lo} - static final int AH_ARCHIVE_SIZE_HI = 0; // offset in archive_header_S - static final int AH_ARCHIVE_SIZE_LO = 1; // offset in archive_header_S - // Length contributions from optional header fields: - static final int AH_FILE_HEADER_LEN = 5; // file_counts = {{size_hi, size_lo}, next, modtime, files} - static final int AH_SPECIAL_FORMAT_LEN = 2; // special_counts = {layouts, band_headers} - static final int AH_CP_NUMBER_LEN = 4; // cp_number_counts = {int, float, long, double} - static final int AH_CP_EXTRA_LEN = 4; // cp_attr_counts = {MH, MT, InDy, BSM} - - // Common structure of attribute band groups: - static final int AB_FLAGS_HI = 0; - static final int AB_FLAGS_LO = 1; - static final int AB_ATTR_COUNT = 2; - static final int AB_ATTR_INDEXES = 3; - static final int AB_ATTR_CALLS = 4; - - static IntBand getAttrBand(MultiBand xxx_attr_bands, int which) { - IntBand b = (IntBand) xxx_attr_bands.get(which); - switch (which) { - case AB_FLAGS_HI: - assert(b.name().endsWith("_flags_hi")); break; - case AB_FLAGS_LO: - assert(b.name().endsWith("_flags_lo")); break; - case AB_ATTR_COUNT: - assert(b.name().endsWith("_attr_count")); break; - case AB_ATTR_INDEXES: - assert(b.name().endsWith("_attr_indexes")); break; - case AB_ATTR_CALLS: - assert(b.name().endsWith("_attr_calls")); break; - default: - assert(false); break; - } - return b; - } - - private static final boolean NULL_IS_OK = true; - - MultiBand all_bands = (MultiBand) new MultiBand("(package)", UNSIGNED5).init(); - - // file header (various random bytes) - ByteBand archive_magic = all_bands.newByteBand("archive_magic"); - IntBand archive_header_0 = all_bands.newIntBand("archive_header_0", UNSIGNED5); - IntBand archive_header_S = all_bands.newIntBand("archive_header_S", UNSIGNED5); - IntBand archive_header_1 = all_bands.newIntBand("archive_header_1", UNSIGNED5); - ByteBand band_headers = all_bands.newByteBand("band_headers"); - - // constant pool contents - MultiBand cp_bands = all_bands.newMultiBand("(constant_pool)", DELTA5); - IntBand cp_Utf8_prefix = cp_bands.newIntBand("cp_Utf8_prefix"); - IntBand cp_Utf8_suffix = cp_bands.newIntBand("cp_Utf8_suffix", UNSIGNED5); - IntBand cp_Utf8_chars = cp_bands.newIntBand("cp_Utf8_chars", CHAR3); - IntBand cp_Utf8_big_suffix = cp_bands.newIntBand("cp_Utf8_big_suffix"); - MultiBand cp_Utf8_big_chars = cp_bands.newMultiBand("(cp_Utf8_big_chars)", DELTA5); - IntBand cp_Int = cp_bands.newIntBand("cp_Int", UDELTA5); - IntBand cp_Float = cp_bands.newIntBand("cp_Float", UDELTA5); - IntBand cp_Long_hi = cp_bands.newIntBand("cp_Long_hi", UDELTA5); - IntBand cp_Long_lo = cp_bands.newIntBand("cp_Long_lo"); - IntBand cp_Double_hi = cp_bands.newIntBand("cp_Double_hi", UDELTA5); - IntBand cp_Double_lo = cp_bands.newIntBand("cp_Double_lo"); - CPRefBand cp_String = cp_bands.newCPRefBand("cp_String", UDELTA5, CONSTANT_Utf8); - CPRefBand cp_Class = cp_bands.newCPRefBand("cp_Class", UDELTA5, CONSTANT_Utf8); - CPRefBand cp_Signature_form = cp_bands.newCPRefBand("cp_Signature_form", CONSTANT_Utf8); - CPRefBand cp_Signature_classes = cp_bands.newCPRefBand("cp_Signature_classes", UDELTA5, CONSTANT_Class); - CPRefBand cp_Descr_name = cp_bands.newCPRefBand("cp_Descr_name", CONSTANT_Utf8); - CPRefBand cp_Descr_type = cp_bands.newCPRefBand("cp_Descr_type", UDELTA5, CONSTANT_Signature); - CPRefBand cp_Field_class = cp_bands.newCPRefBand("cp_Field_class", CONSTANT_Class); - CPRefBand cp_Field_desc = cp_bands.newCPRefBand("cp_Field_desc", UDELTA5, CONSTANT_NameandType); - CPRefBand cp_Method_class = cp_bands.newCPRefBand("cp_Method_class", CONSTANT_Class); - CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType); - CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class); - CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType); - IntBand cp_MethodHandle_refkind = cp_bands.newIntBand("cp_MethodHandle_refkind", DELTA5); - CPRefBand cp_MethodHandle_member = cp_bands.newCPRefBand("cp_MethodHandle_member", UDELTA5, CONSTANT_AnyMember); - CPRefBand cp_MethodType = cp_bands.newCPRefBand("cp_MethodType", UDELTA5, CONSTANT_Signature); - CPRefBand cp_BootstrapMethod_ref = cp_bands.newCPRefBand("cp_BootstrapMethod_ref", DELTA5, CONSTANT_MethodHandle); - IntBand cp_BootstrapMethod_arg_count = cp_bands.newIntBand("cp_BootstrapMethod_arg_count", UDELTA5); - CPRefBand cp_BootstrapMethod_arg = cp_bands.newCPRefBand("cp_BootstrapMethod_arg", DELTA5, CONSTANT_LoadableValue); - CPRefBand cp_InvokeDynamic_spec = cp_bands.newCPRefBand("cp_InvokeDynamic_spec", DELTA5, CONSTANT_BootstrapMethod); - CPRefBand cp_InvokeDynamic_desc = cp_bands.newCPRefBand("cp_InvokeDynamic_desc", UDELTA5, CONSTANT_NameandType); - - // bands for carrying attribute definitions: - MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5); - ByteBand attr_definition_headers = attr_definition_bands.newByteBand("attr_definition_headers"); - CPRefBand attr_definition_name = attr_definition_bands.newCPRefBand("attr_definition_name", CONSTANT_Utf8); - CPRefBand attr_definition_layout = attr_definition_bands.newCPRefBand("attr_definition_layout", CONSTANT_Utf8); - - // bands for hardwired InnerClasses attribute (shared across the package) - MultiBand ic_bands = all_bands.newMultiBand("(ic_bands)", DELTA5); - CPRefBand ic_this_class = ic_bands.newCPRefBand("ic_this_class", UDELTA5, CONSTANT_Class); - IntBand ic_flags = ic_bands.newIntBand("ic_flags", UNSIGNED5); - // These bands contain data only where flags sets ACC_IC_LONG_FORM: - CPRefBand ic_outer_class = ic_bands.newCPRefBand("ic_outer_class", DELTA5, CONSTANT_Class, NULL_IS_OK); - CPRefBand ic_name = ic_bands.newCPRefBand("ic_name", DELTA5, CONSTANT_Utf8, NULL_IS_OK); - - // bands for carrying class schema information: - MultiBand class_bands = all_bands.newMultiBand("(class_bands)", DELTA5); - CPRefBand class_this = class_bands.newCPRefBand("class_this", CONSTANT_Class); - CPRefBand class_super = class_bands.newCPRefBand("class_super", CONSTANT_Class); - IntBand class_interface_count = class_bands.newIntBand("class_interface_count"); - CPRefBand class_interface = class_bands.newCPRefBand("class_interface", CONSTANT_Class); - - // bands for class members - IntBand class_field_count = class_bands.newIntBand("class_field_count"); - IntBand class_method_count = class_bands.newIntBand("class_method_count"); - - CPRefBand field_descr = class_bands.newCPRefBand("field_descr", CONSTANT_NameandType); - MultiBand field_attr_bands = class_bands.newMultiBand("(field_attr_bands)", UNSIGNED5); - IntBand field_flags_hi = field_attr_bands.newIntBand("field_flags_hi"); - IntBand field_flags_lo = field_attr_bands.newIntBand("field_flags_lo"); - IntBand field_attr_count = field_attr_bands.newIntBand("field_attr_count"); - IntBand field_attr_indexes = field_attr_bands.newIntBand("field_attr_indexes"); - IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls"); - - // bands for predefined field attributes - CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific); - CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature); - MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5); - MultiBand field_type_metadata_bands = field_attr_bands.newMultiBand("(field_type_metadata_bands)", UNSIGNED5); - - CPRefBand method_descr = class_bands.newCPRefBand("method_descr", MDELTA5, CONSTANT_NameandType); - MultiBand method_attr_bands = class_bands.newMultiBand("(method_attr_bands)", UNSIGNED5); - IntBand method_flags_hi = method_attr_bands.newIntBand("method_flags_hi"); - IntBand method_flags_lo = method_attr_bands.newIntBand("method_flags_lo"); - IntBand method_attr_count = method_attr_bands.newIntBand("method_attr_count"); - IntBand method_attr_indexes = method_attr_bands.newIntBand("method_attr_indexes"); - IntBand method_attr_calls = method_attr_bands.newIntBand("method_attr_calls"); - // band for predefined method attributes - IntBand method_Exceptions_N = method_attr_bands.newIntBand("method_Exceptions_N"); - CPRefBand method_Exceptions_RC = method_attr_bands.newCPRefBand("method_Exceptions_RC", CONSTANT_Class); - CPRefBand method_Signature_RS = method_attr_bands.newCPRefBand("method_Signature_RS", CONSTANT_Signature); - MultiBand method_metadata_bands = method_attr_bands.newMultiBand("(method_metadata_bands)", UNSIGNED5); - // band for predefine method parameters - IntBand method_MethodParameters_NB = method_attr_bands.newIntBand("method_MethodParameters_NB", BYTE1); - CPRefBand method_MethodParameters_name_RUN = method_attr_bands.newCPRefBand("method_MethodParameters_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); - IntBand method_MethodParameters_flag_FH = method_attr_bands.newIntBand("method_MethodParameters_flag_FH"); - MultiBand method_type_metadata_bands = method_attr_bands.newMultiBand("(method_type_metadata_bands)", UNSIGNED5); - - MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5); - IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi"); - IntBand class_flags_lo = class_attr_bands.newIntBand("class_flags_lo"); - IntBand class_attr_count = class_attr_bands.newIntBand("class_attr_count"); - IntBand class_attr_indexes = class_attr_bands.newIntBand("class_attr_indexes"); - IntBand class_attr_calls = class_attr_bands.newIntBand("class_attr_calls"); - // band for predefined SourceFile and other class attributes - CPRefBand class_SourceFile_RUN = class_attr_bands.newCPRefBand("class_SourceFile_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); - CPRefBand class_EnclosingMethod_RC = class_attr_bands.newCPRefBand("class_EnclosingMethod_RC", CONSTANT_Class); - CPRefBand class_EnclosingMethod_RDN = class_attr_bands.newCPRefBand("class_EnclosingMethod_RDN", UNSIGNED5, CONSTANT_NameandType, NULL_IS_OK); - CPRefBand class_Signature_RS = class_attr_bands.newCPRefBand("class_Signature_RS", CONSTANT_Signature); - MultiBand class_metadata_bands = class_attr_bands.newMultiBand("(class_metadata_bands)", UNSIGNED5); - IntBand class_InnerClasses_N = class_attr_bands.newIntBand("class_InnerClasses_N"); - CPRefBand class_InnerClasses_RC = class_attr_bands.newCPRefBand("class_InnerClasses_RC", CONSTANT_Class); - IntBand class_InnerClasses_F = class_attr_bands.newIntBand("class_InnerClasses_F"); - CPRefBand class_InnerClasses_outer_RCN = class_attr_bands.newCPRefBand("class_InnerClasses_outer_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); - CPRefBand class_InnerClasses_name_RUN = class_attr_bands.newCPRefBand("class_InnerClasses_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK); - IntBand class_ClassFile_version_minor_H = class_attr_bands.newIntBand("class_ClassFile_version_minor_H"); - IntBand class_ClassFile_version_major_H = class_attr_bands.newIntBand("class_ClassFile_version_major_H"); - MultiBand class_type_metadata_bands = class_attr_bands.newMultiBand("(class_type_metadata_bands)", UNSIGNED5); - - MultiBand code_bands = class_bands.newMultiBand("(code_bands)", UNSIGNED5); - ByteBand code_headers = code_bands.newByteBand("code_headers"); //BYTE1 - IntBand code_max_stack = code_bands.newIntBand("code_max_stack", UNSIGNED5); - IntBand code_max_na_locals = code_bands.newIntBand("code_max_na_locals", UNSIGNED5); - IntBand code_handler_count = code_bands.newIntBand("code_handler_count", UNSIGNED5); - IntBand code_handler_start_P = code_bands.newIntBand("code_handler_start_P", BCI5); - IntBand code_handler_end_PO = code_bands.newIntBand("code_handler_end_PO", BRANCH5); - IntBand code_handler_catch_PO = code_bands.newIntBand("code_handler_catch_PO", BRANCH5); - CPRefBand code_handler_class_RCN = code_bands.newCPRefBand("code_handler_class_RCN", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); - - MultiBand code_attr_bands = class_bands.newMultiBand("(code_attr_bands)", UNSIGNED5); - IntBand code_flags_hi = code_attr_bands.newIntBand("code_flags_hi"); - IntBand code_flags_lo = code_attr_bands.newIntBand("code_flags_lo"); - IntBand code_attr_count = code_attr_bands.newIntBand("code_attr_count"); - IntBand code_attr_indexes = code_attr_bands.newIntBand("code_attr_indexes"); - IntBand code_attr_calls = code_attr_bands.newIntBand("code_attr_calls"); - - MultiBand stackmap_bands = code_attr_bands.newMultiBand("(StackMapTable_bands)", UNSIGNED5); - IntBand code_StackMapTable_N = stackmap_bands.newIntBand("code_StackMapTable_N"); - IntBand code_StackMapTable_frame_T = stackmap_bands.newIntBand("code_StackMapTable_frame_T",BYTE1); - IntBand code_StackMapTable_local_N = stackmap_bands.newIntBand("code_StackMapTable_local_N"); - IntBand code_StackMapTable_stack_N = stackmap_bands.newIntBand("code_StackMapTable_stack_N"); - IntBand code_StackMapTable_offset = stackmap_bands.newIntBand("code_StackMapTable_offset", UNSIGNED5); - IntBand code_StackMapTable_T = stackmap_bands.newIntBand("code_StackMapTable_T", BYTE1); - CPRefBand code_StackMapTable_RC = stackmap_bands.newCPRefBand("code_StackMapTable_RC", CONSTANT_Class); - IntBand code_StackMapTable_P = stackmap_bands.newIntBand("code_StackMapTable_P", BCI5); - - // bands for predefined LineNumberTable attribute - IntBand code_LineNumberTable_N = code_attr_bands.newIntBand("code_LineNumberTable_N"); - IntBand code_LineNumberTable_bci_P = code_attr_bands.newIntBand("code_LineNumberTable_bci_P", BCI5); - IntBand code_LineNumberTable_line = code_attr_bands.newIntBand("code_LineNumberTable_line"); - - // bands for predefined LocalVariable{Type}Table attributes - IntBand code_LocalVariableTable_N = code_attr_bands.newIntBand("code_LocalVariableTable_N"); - IntBand code_LocalVariableTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTable_bci_P", BCI5); - IntBand code_LocalVariableTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTable_span_O", BRANCH5); - CPRefBand code_LocalVariableTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTable_name_RU", CONSTANT_Utf8); - CPRefBand code_LocalVariableTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTable_type_RS", CONSTANT_Signature); - IntBand code_LocalVariableTable_slot = code_attr_bands.newIntBand("code_LocalVariableTable_slot"); - IntBand code_LocalVariableTypeTable_N = code_attr_bands.newIntBand("code_LocalVariableTypeTable_N"); - IntBand code_LocalVariableTypeTable_bci_P = code_attr_bands.newIntBand("code_LocalVariableTypeTable_bci_P", BCI5); - IntBand code_LocalVariableTypeTable_span_O = code_attr_bands.newIntBand("code_LocalVariableTypeTable_span_O", BRANCH5); - CPRefBand code_LocalVariableTypeTable_name_RU = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_name_RU", CONSTANT_Utf8); - CPRefBand code_LocalVariableTypeTable_type_RS = code_attr_bands.newCPRefBand("code_LocalVariableTypeTable_type_RS", CONSTANT_Signature); - IntBand code_LocalVariableTypeTable_slot = code_attr_bands.newIntBand("code_LocalVariableTypeTable_slot"); - MultiBand code_type_metadata_bands = code_attr_bands.newMultiBand("(code_type_metadata_bands)", UNSIGNED5); - - // bands for bytecodes - MultiBand bc_bands = all_bands.newMultiBand("(byte_codes)", UNSIGNED5); - ByteBand bc_codes = bc_bands.newByteBand("bc_codes"); //BYTE1 - // remaining bands provide typed opcode fields required by the bc_codes - - IntBand bc_case_count = bc_bands.newIntBand("bc_case_count"); // *switch - IntBand bc_case_value = bc_bands.newIntBand("bc_case_value", DELTA5); // *switch - ByteBand bc_byte = bc_bands.newByteBand("bc_byte"); //BYTE1 // bipush, iinc, *newarray - IntBand bc_short = bc_bands.newIntBand("bc_short", DELTA5); // sipush, wide iinc - IntBand bc_local = bc_bands.newIntBand("bc_local"); // *load, *store, iinc, ret - IntBand bc_label = bc_bands.newIntBand("bc_label", BRANCH5); // if*, goto*, jsr*, *switch - - // Most CP refs exhibit some correlation, and benefit from delta coding. - // The notable exceptions are class and method references. - - // ldc* operands: - CPRefBand bc_intref = bc_bands.newCPRefBand("bc_intref", DELTA5, CONSTANT_Integer); - CPRefBand bc_floatref = bc_bands.newCPRefBand("bc_floatref", DELTA5, CONSTANT_Float); - CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long); - CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double); - CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String); - CPRefBand bc_loadablevalueref = bc_bands.newCPRefBand("bc_loadablevalueref", DELTA5, CONSTANT_LoadableValue); - - // nulls produced by bc_classref are taken to mean the current class - CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); // new, *anew*, c*cast, i*of, ldc - CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref); // get*, put* - CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]* - CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface - CPRefBand bc_indyref = bc_bands.newCPRefBand("bc_indyref", DELTA5, CONSTANT_InvokeDynamic); // invokedynamic - - // _self_linker_op family - CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None); // any field within cur. class - CPRefBand bc_superfield = bc_bands.newCPRefBand("bc_superfield", CONSTANT_None); // any field within superclass - CPRefBand bc_thismethod = bc_bands.newCPRefBand("bc_thismethod", CONSTANT_None); // any method within cur. class - CPRefBand bc_supermethod = bc_bands.newCPRefBand("bc_supermethod", CONSTANT_None); // any method within superclass - // bc_invokeinit family: - IntBand bc_initref = bc_bands.newIntBand("bc_initref"); - // escapes - CPRefBand bc_escref = bc_bands.newCPRefBand("bc_escref", CONSTANT_All); - IntBand bc_escrefsize = bc_bands.newIntBand("bc_escrefsize"); - IntBand bc_escsize = bc_bands.newIntBand("bc_escsize"); - ByteBand bc_escbyte = bc_bands.newByteBand("bc_escbyte"); - - // bands for carrying resource files and file attributes: - MultiBand file_bands = all_bands.newMultiBand("(file_bands)", UNSIGNED5); - CPRefBand file_name = file_bands.newCPRefBand("file_name", CONSTANT_Utf8); - IntBand file_size_hi = file_bands.newIntBand("file_size_hi"); - IntBand file_size_lo = file_bands.newIntBand("file_size_lo"); - IntBand file_modtime = file_bands.newIntBand("file_modtime", DELTA5); - IntBand file_options = file_bands.newIntBand("file_options"); - ByteBand file_bits = file_bands.newByteBand("file_bits"); - - // End of band definitions! - - /** Given CP indexes, distribute tag-specific indexes to bands. */ - protected void setBandIndexes() { - // Handle prior calls to setBandIndex: - for (Object[] need : needPredefIndex) { - CPRefBand b = (CPRefBand) need[0]; - Byte which = (Byte) need[1]; - b.setIndex(getCPIndex(which.byteValue())); - } - needPredefIndex = null; // no more predefs - - if (verbose > 3) { - printCDecl(all_bands); - } - } - - protected void setBandIndex(CPRefBand b, byte which) { - Object[] need = { b, Byte.valueOf(which) }; - if (which == CONSTANT_FieldSpecific) { - // I.e., attribute layouts KQ (no null) or KQN (null ok). - allKQBands.add(b); - } else if (needPredefIndex != null) { - needPredefIndex.add(need); - } else { - // Not in predefinition mode; getCPIndex now works. - b.setIndex(getCPIndex(which)); - } - } - - protected void setConstantValueIndex(Field f) { - Index ix = null; - if (f != null) { - byte tag = f.getLiteralTag(); - ix = getCPIndex(tag); - if (verbose > 2) - Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix); - assert(ix != null); - } - // Typically, allKQBands is the singleton of field_ConstantValue_KQ. - for (CPRefBand xxx_KQ : allKQBands) { - xxx_KQ.setIndex(ix); - } - } - - // Table of bands which contain metadata. - protected MultiBand[] metadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; - { - metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands; - metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; - metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; - } - // Table of bands which contains type_metadata (TypeAnnotations) - protected MultiBand[] typeMetadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; - { - typeMetadataBands[ATTR_CONTEXT_CLASS] = class_type_metadata_bands; - typeMetadataBands[ATTR_CONTEXT_FIELD] = field_type_metadata_bands; - typeMetadataBands[ATTR_CONTEXT_METHOD] = method_type_metadata_bands; - typeMetadataBands[ATTR_CONTEXT_CODE] = code_type_metadata_bands; - } - - // Attribute layouts. - public static final int ADH_CONTEXT_MASK = 0x3; // (ad_hdr & ADH_CONTEXT_MASK) - public static final int ADH_BIT_SHIFT = 0x2; // (ad_hdr >> ADH_BIT_SHIFT) - public static final int ADH_BIT_IS_LSB = 1; - public static final int ATTR_INDEX_OVERFLOW = -1; - - public int[] attrIndexLimit = new int[ATTR_CONTEXT_LIMIT]; - // Each index limit is either 32 or 63, depending on AO_HAVE_XXX_FLAGS_HI. - - // Which flag bits are taken over by attributes? - protected long[] attrFlagMask = new long[ATTR_CONTEXT_LIMIT]; - // Which flag bits have been taken over explicitly? - protected long[] attrDefSeen = new long[ATTR_CONTEXT_LIMIT]; - - // What pseudo-attribute bits are there to watch for? - protected int[] attrOverflowMask = new int[ATTR_CONTEXT_LIMIT]; - protected int attrClassFileVersionMask; - - // Mapping from Attribute.Layout to Band[] (layout element bands). - protected Map attrBandTable = new HashMap<>(); - - // Well-known attributes: - protected final Attribute.Layout attrCodeEmpty; - protected final Attribute.Layout attrInnerClassesEmpty; - protected final Attribute.Layout attrClassFileVersion; - protected final Attribute.Layout attrConstantValue; - - // Mapping from Attribute.Layout to Integer (inverse of attrDefs) - Map attrIndexTable = new HashMap<>(); - - // Mapping from attribute index (<32 are flag bits) to attributes. - protected List> attrDefs = - new FixedList<>(ATTR_CONTEXT_LIMIT); - { - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - assert(attrIndexLimit[i] == 0); - attrIndexLimit[i] = 32; // just for the sake of predefs. - attrDefs.set(i, new ArrayList<>(Collections.nCopies( - attrIndexLimit[i], (Attribute.Layout)null))); - - } - - // Add predefined attribute definitions: - attrInnerClassesEmpty = - predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null, - "InnerClasses", ""); - assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty); - predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS, - new Band[] { class_SourceFile_RUN }, - "SourceFile", "RUNH"); - predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS, - new Band[] { - class_EnclosingMethod_RC, - class_EnclosingMethod_RDN - }, - "EnclosingMethod", "RCHRDNH"); - attrClassFileVersion = - predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS, - new Band[] { - class_ClassFile_version_minor_H, - class_ClassFile_version_major_H - }, - ".ClassFile.version", "HH"); - predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS, - new Band[] { class_Signature_RS }, - "Signature", "RSH"); - predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null, - "Deprecated", ""); - //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null, - // "Synthetic", ""); - predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null, - ".Overflow", ""); - attrConstantValue = - predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD, - new Band[] { field_ConstantValue_KQ }, - "ConstantValue", "KQH"); - predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD, - new Band[] { field_Signature_RS }, - "Signature", "RSH"); - predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null, - "Deprecated", ""); - //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null, - // "Synthetic", ""); - predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null, - ".Overflow", ""); - attrCodeEmpty = - predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null, - "Code", ""); - predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD, - new Band[] { - method_Exceptions_N, - method_Exceptions_RC - }, - "Exceptions", "NH[RCH]"); - predefineAttribute(METHOD_ATTR_MethodParameters, ATTR_CONTEXT_METHOD, - new Band[]{ - method_MethodParameters_NB, - method_MethodParameters_name_RUN, - method_MethodParameters_flag_FH - }, - "MethodParameters", "NB[RUNHFH]"); - assert(attrCodeEmpty == Package.attrCodeEmpty); - predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD, - new Band[] { method_Signature_RS }, - "Signature", "RSH"); - predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null, - "Deprecated", ""); - //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null, - // "Synthetic", ""); - predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null, - ".Overflow", ""); - - for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { - MultiBand xxx_metadata_bands = metadataBands[ctype]; - if (ctype != ATTR_CONTEXT_CODE) { - // These arguments cause the bands to be built - // automatically for this complicated layout: - predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, - ATTR_CONTEXT_NAME[ctype]+"_RVA_", - xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleAnnotations")); - predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, - ATTR_CONTEXT_NAME[ctype]+"_RIA_", - xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleAnnotations")); - - if (ctype == ATTR_CONTEXT_METHOD) { - predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, - "method_RVPA_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleParameterAnnotations")); - predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, - "method_RIPA_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleParameterAnnotations")); - predefineAttribute(METHOD_ATTR_AnnotationDefault, - "method_AD_", xxx_metadata_bands, - Attribute.lookup(null, ctype, - "AnnotationDefault")); - } - } - // All contexts have these - MultiBand xxx_type_metadata_bands = typeMetadataBands[ctype]; - predefineAttribute(X_ATTR_RuntimeVisibleTypeAnnotations, - ATTR_CONTEXT_NAME[ctype] + "_RVTA_", - xxx_type_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeVisibleTypeAnnotations")); - predefineAttribute(X_ATTR_RuntimeInvisibleTypeAnnotations, - ATTR_CONTEXT_NAME[ctype] + "_RITA_", - xxx_type_metadata_bands, - Attribute.lookup(null, ctype, - "RuntimeInvisibleTypeAnnotations")); - } - - - Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout(); - predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE, - stackmap_bands.toArray(), - stackMapDef.name(), stackMapDef.layout()); - - predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE, - new Band[] { - code_LineNumberTable_N, - code_LineNumberTable_bci_P, - code_LineNumberTable_line - }, - "LineNumberTable", "NH[PHH]"); - predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE, - new Band[] { - code_LocalVariableTable_N, - code_LocalVariableTable_bci_P, - code_LocalVariableTable_span_O, - code_LocalVariableTable_name_RU, - code_LocalVariableTable_type_RS, - code_LocalVariableTable_slot - }, - "LocalVariableTable", "NH[PHOHRUHRSHH]"); - predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE, - new Band[] { - code_LocalVariableTypeTable_N, - code_LocalVariableTypeTable_bci_P, - code_LocalVariableTypeTable_span_O, - code_LocalVariableTypeTable_name_RU, - code_LocalVariableTypeTable_type_RS, - code_LocalVariableTypeTable_slot - }, - "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); - predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null, - ".Overflow", ""); - - // Clear the record of having seen these definitions, - // so they may be redefined without error. - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - attrDefSeen[i] = 0; - } - - // Set up the special masks: - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - attrOverflowMask[i] = (1< 0) Utils.log.fine("Legacy package version"); - // Revoke definition of pre-1.6 attribute type. - undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); - } - } - - protected void initAttrIndexLimit() { - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - assert(attrIndexLimit[i] == 0); // decide on it now! - attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32); - List defList = attrDefs.get(i); - assert(defList.size() == 32); // all predef indexes are <32 - int addMore = attrIndexLimit[i] - defList.size(); - defList.addAll(Collections.nCopies(addMore, (Attribute.Layout) null)); - } - } - - protected boolean haveFlagsHi(int ctype) { - int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype); - switch (ctype) { - case ATTR_CONTEXT_CLASS: - assert(mask == AO_HAVE_CLASS_FLAGS_HI); break; - case ATTR_CONTEXT_FIELD: - assert(mask == AO_HAVE_FIELD_FLAGS_HI); break; - case ATTR_CONTEXT_METHOD: - assert(mask == AO_HAVE_METHOD_FLAGS_HI); break; - case ATTR_CONTEXT_CODE: - assert(mask == AO_HAVE_CODE_FLAGS_HI); break; - default: - assert(false); - } - return testBit(archiveOptions, mask); - } - - protected List getPredefinedAttrs(int ctype) { - assert(attrIndexLimit[ctype] != 0); - List res = new ArrayList<>(attrIndexLimit[ctype]); - // Remove nulls and non-predefs. - for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) { - if (testBit(attrDefSeen[ctype], 1L<= attrIndexLimit[ctype]) return false; - // If the bit is set, it was explicitly def'd. - if (testBit(attrDefSeen[ctype], 1L<= 0) { - setAttributeLayoutIndex(def, index); - } - if (ab == null) { - ab = new Band[0]; - } - assert(attrBandTable.get(def) == null); // no redef - attrBandTable.put(def, ab); - assert(def.bandCount == ab.length) - : (def+" // "+Arrays.asList(ab)); - // Let's make sure the band types match: - assert(assertBandOKForElems(ab, def.elems)); - return def; - } - - // This version takes bandPrefix/addHere instead of prebuilt Band[] ab. - private - Attribute.Layout predefineAttribute(int index, - String bandPrefix, MultiBand addHere, - Attribute attr) { - //Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); - Attribute.Layout def = attr.layout(); - int ctype = def.ctype(); - return predefineAttribute(index, ctype, - makeNewAttributeBands(bandPrefix, def, addHere), - def.name(), def.layout()); - } - - private - void undefineAttribute(int index, int ctype) { - if (verbose > 1) { - System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+ - " attribute on bit "+index); - } - List defList = attrDefs.get(ctype); - Attribute.Layout def = defList.get(index); - assert(def != null); - defList.set(index, null); - attrIndexTable.put(def, null); - // Clear the def bit. (For predefs, it's already clear.) - assert(index < 64); - attrDefSeen[ctype] &= ~(1L< 1) - Utils.log.fine("Making new bands for "+def); - Band[] newAB = makeNewAttributeBands(pfx, def, - xxx_attr_bands); - assert(newAB.length == def.bandCount); - Band[] prevAB = attrBandTable.put(def, newAB); - if (prevAB != null) { - // We won't be using these predefined bands. - for (int j = 0; j < prevAB.length; j++) { - prevAB[j].doneWithUnusedBand(); - } - } - } - } - //System.out.println(prevForAssertMap); - } - private - Band[] makeNewAttributeBands(String pfx, Attribute.Layout def, - MultiBand addHere) { - int base = addHere.size(); - makeNewAttributeBands(pfx, def.elems, addHere); - int nb = addHere.size() - base; - Band[] newAB = new Band[nb]; - for (int i = 0; i < nb; i++) { - newAB[i] = addHere.get(base+i); - } - return newAB; - } - // Recursive helper, operates on a "body" or other sequence of elems: - private - void makeNewAttributeBands(String pfx, Attribute.Layout.Element[] elems, - MultiBand ab) { - for (int i = 0; i < elems.length; i++) { - Attribute.Layout.Element e = elems[i]; - String name = pfx+ab.size()+"_"+e.layout; - { - int tem; - if ((tem = name.indexOf('[')) > 0) - name = name.substring(0, tem); - if ((tem = name.indexOf('(')) > 0) - name = name.substring(0, tem); - if (name.endsWith("H")) - name = name.substring(0, name.length()-1); - } - Band nb; - switch (e.kind) { - case Attribute.EK_INT: - nb = newElemBand(e, name, ab); - break; - case Attribute.EK_BCI: - if (!e.flagTest(Attribute.EF_DELTA)) { - // PH: transmit R(bci), store bci - nb = ab.newIntBand(name, BCI5); - } else { - // POH: transmit D(R(bci)), store bci - nb = ab.newIntBand(name, BRANCH5); - } - // Note: No case for BYTE1 here. - break; - case Attribute.EK_BCO: - // OH: transmit D(R(bci)), store D(bci) - nb = ab.newIntBand(name, BRANCH5); - // Note: No case for BYTE1 here. - break; - case Attribute.EK_FLAG: - assert(!e.flagTest(Attribute.EF_SIGN)); - nb = newElemBand(e, name, ab); - break; - case Attribute.EK_REPL: - assert(!e.flagTest(Attribute.EF_SIGN)); - nb = newElemBand(e, name, ab); - makeNewAttributeBands(pfx, e.body, ab); - break; - case Attribute.EK_UN: - nb = newElemBand(e, name, ab); - makeNewAttributeBands(pfx, e.body, ab); - break; - case Attribute.EK_CASE: - if (!e.flagTest(Attribute.EF_BACK)) { - // If it's not a duplicate body, make the bands. - makeNewAttributeBands(pfx, e.body, ab); - } - continue; // no new band to make - case Attribute.EK_REF: - byte refKind = e.refKind; - boolean nullOK = e.flagTest(Attribute.EF_NULL); - nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK); - // Note: No case for BYTE1 here. - break; - case Attribute.EK_CALL: - continue; // no new band to make - case Attribute.EK_CBLE: - makeNewAttributeBands(pfx, e.body, ab); - continue; // no new band to make - default: assert(false); continue; - } - if (verbose > 1) { - Utils.log.fine("New attribute band "+nb); - } - } - } - private - Band newElemBand(Attribute.Layout.Element e, String name, MultiBand ab) { - if (e.flagTest(Attribute.EF_SIGN)) { - return ab.newIntBand(name, SIGNED5); - } else if (e.len == 1) { - return ab.newIntBand(name, BYTE1); // Not ByteBand, please. - } else { - return ab.newIntBand(name, UNSIGNED5); - } - } - - protected int setAttributeLayoutIndex(Attribute.Layout def, int index) { - int ctype = def.ctype; - assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]); - List defList = attrDefs.get(ctype); - if (index == ATTR_INDEX_OVERFLOW) { - // Overflow attribute. - index = defList.size(); - defList.add(def); - if (verbose > 0) - Utils.log.info("Adding new attribute at "+def +": "+index); - attrIndexTable.put(def, index); - return index; - } - - // Detect redefinitions: - if (testBit(attrDefSeen[ctype], 1L< (attrClassFileVersionMask == 0? 2:0)) - Utils.log.fine("Fixing new attribute at "+index - +": "+def - +(defList.get(index) == null? "": - "; replacing "+defList.get(index))); - attrFlagMask[ctype] |= (1L<= shortCodeLimits.length) return LONG_CODE_HEADER; - int siglen = code.getMethod().getArgumentSize(); - assert(l0 >= siglen); // enough locals for signature! - if (l0 < siglen) return LONG_CODE_HEADER; - int l1 = l0 - siglen; // do not count locals required by the signature - int lims = shortCodeLimits[h][0]; - int liml = shortCodeLimits[h][1]; - if (s >= lims || l1 >= liml) return LONG_CODE_HEADER; - int sc = shortCodeHeader_h_base(h); - sc += s + lims*l1; - if (sc > 255) return LONG_CODE_HEADER; - assert(shortCodeHeader_max_stack(sc) == s); - assert(shortCodeHeader_max_na_locals(sc) == l1); - assert(shortCodeHeader_handler_count(sc) == h); - return sc; - } - - static final int LONG_CODE_HEADER = 0; - static int shortCodeHeader_handler_count(int sc) { - assert(sc > 0 && sc <= 255); - for (int h = 0; ; h++) { - if (sc < shortCodeHeader_h_base(h+1)) - return h; - } - } - static int shortCodeHeader_max_stack(int sc) { - int h = shortCodeHeader_handler_count(sc); - int lims = shortCodeLimits[h][0]; - return (sc - shortCodeHeader_h_base(h)) % lims; - } - static int shortCodeHeader_max_na_locals(int sc) { - int h = shortCodeHeader_handler_count(sc); - int lims = shortCodeLimits[h][0]; - return (sc - shortCodeHeader_h_base(h)) / lims; - } - - private static int shortCodeHeader_h_base(int h) { - assert(h <= shortCodeLimits.length); - int sc = 1; - for (int h0 = 0; h0 < h; h0++) { - int lims = shortCodeLimits[h0][0]; - int liml = shortCodeLimits[h0][1]; - sc += lims * liml; - } - return sc; - } - - // utilities for accessing the bc_label band: - protected void putLabel(IntBand bc_label, Code c, int pc, int targetPC) { - bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc)); - } - protected int getLabel(IntBand bc_label, Code c, int pc) { - return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc)); - } - - protected CPRefBand getCPRefOpBand(int bc) { - switch (Instruction.getCPRefOpTag(bc)) { - case CONSTANT_Class: - return bc_classref; - case CONSTANT_Fieldref: - return bc_fieldref; - case CONSTANT_Methodref: - return bc_methodref; - case CONSTANT_InterfaceMethodref: - return bc_imethodref; - case CONSTANT_InvokeDynamic: - return bc_indyref; - case CONSTANT_LoadableValue: - switch (bc) { - case _ildc: case _ildc_w: - return bc_intref; - case _fldc: case _fldc_w: - return bc_floatref; - case _lldc2_w: - return bc_longref; - case _dldc2_w: - return bc_doubleref; - case _sldc: case _sldc_w: - return bc_stringref; - case _cldc: case _cldc_w: - return bc_classref; - case _qldc: case _qldc_w: - return bc_loadablevalueref; - } - break; - } - assert(false); - return null; - } - - protected CPRefBand selfOpRefBand(int self_bc) { - assert(Instruction.isSelfLinkerOp(self_bc)); - int idx = (self_bc - _self_linker_op); - boolean isSuper = (idx >= _self_linker_super_flag); - if (isSuper) idx -= _self_linker_super_flag; - boolean isAload = (idx >= _self_linker_aload_flag); - if (isAload) idx -= _self_linker_aload_flag; - int origBC = _first_linker_op + idx; - boolean isField = Instruction.isFieldOp(origBC); - if (!isSuper) - return isField? bc_thisfield: bc_thismethod; - else - return isField? bc_superfield: bc_supermethod; - } - - //////////////////////////////////////////////////////////////////// - - static int nextSeqForDebug; - static File dumpDir = null; - static OutputStream getDumpStream(Band b, String ext) throws IOException { - return getDumpStream(b.name, b.seqForDebug, ext, b); - } - static OutputStream getDumpStream(Index ix, String ext) throws IOException { - if (ix.size() == 0) return new ByteArrayOutputStream(); - int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag]; - return getDumpStream(ix.debugName, seq, ext, ix); - } - static OutputStream getDumpStream(String name, int seq, String ext, Object b) throws IOException { - if (dumpDir == null) { - dumpDir = File.createTempFile("BD_", "", new File(".")); - dumpDir.delete(); - if (dumpDir.mkdir()) - Utils.log.info("Dumping bands to "+dumpDir); - } - name = name.replace('(', ' ').replace(')', ' '); - name = name.replace('/', ' '); - name = name.replace('*', ' '); - name = name.trim().replace(' ','_'); - name = ((10000+seq) + "_" + name).substring(1); - File dumpFile = new File(dumpDir, name+ext); - Utils.log.info("Dumping "+b+" to "+dumpFile); - return new BufferedOutputStream(new FileOutputStream(dumpFile)); - } - - // DEBUG ONLY: Validate me at each length change. - static boolean assertCanChangeLength(Band b) { - switch (b.phase) { - case COLLECT_PHASE: - case READ_PHASE: - return true; - } - return false; - } - - // DEBUG ONLY: Validate a phase. - static boolean assertPhase(Band b, int phaseExpected) { - if (b.phase() != phaseExpected) { - Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b); - return false; - } - return true; - } - - - // DEBUG ONLY: Tells whether verbosity is turned on. - static int verbose() { - return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); - } - - - // DEBUG ONLY: Validate me at each phase change. - static boolean assertPhaseChangeOK(Band b, int p0, int p1) { - switch (p0*10+p1) { - /// Writing phases: - case NO_PHASE*10+COLLECT_PHASE: - // Ready to collect data from the input classes. - assert(!b.isReader()); - assert(b.capacity() >= 0); - assert(b.length() == 0); - return true; - case COLLECT_PHASE*10+FROZEN_PHASE: - case FROZEN_PHASE*10+FROZEN_PHASE: - assert(b.length() == 0); - return true; - case COLLECT_PHASE*10+WRITE_PHASE: - case FROZEN_PHASE*10+WRITE_PHASE: - // Data is all collected. Ready to write bytes to disk. - return true; - case WRITE_PHASE*10+DONE_PHASE: - // Done writing to disk. Ready to reset, in principle. - return true; - - /// Reading phases: - case NO_PHASE*10+EXPECT_PHASE: - assert(b.isReader()); - assert(b.capacity() < 0); - return true; - case EXPECT_PHASE*10+READ_PHASE: - // Ready to read values from disk. - assert(Math.max(0,b.capacity()) >= b.valuesExpected()); - assert(b.length() <= 0); - return true; - case READ_PHASE*10+DISBURSE_PHASE: - // Ready to disburse values. - assert(b.valuesRemainingForDebug() == b.length()); - return true; - case DISBURSE_PHASE*10+DONE_PHASE: - // Done disbursing values. Ready to reset, in principle. - assert(assertDoneDisbursing(b)); - return true; - } - if (p0 == p1) - Utils.log.warning("Already in phase "+p0); - else - Utils.log.warning("Unexpected phase "+p0+" -> "+p1); - return false; - } - - private static boolean assertDoneDisbursing(Band b) { - if (b.phase != DISBURSE_PHASE) { - Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b); - if (verbose() <= 1) return false; // fail now - } - int left = b.valuesRemainingForDebug(); - if (left > 0) { - Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b); - if (verbose() <= 1) return false; // fail now - } - if (b instanceof MultiBand) { - MultiBand mb = (MultiBand) b; - for (int i = 0; i < mb.bandCount; i++) { - Band sub = mb.bands[i]; - if (sub.phase != DONE_PHASE) { - Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub); - if (verbose() <= 1) return false; // fail now - } - } - } - return true; - } - - private static void printCDecl(Band b) { - if (b instanceof MultiBand) { - MultiBand mb = (MultiBand) b; - for (int i = 0; i < mb.bandCount; i++) { - printCDecl(mb.bands[i]); - } - return; - } - String ixS = "NULL"; - if (b instanceof CPRefBand) { - Index ix = ((CPRefBand)b).index; - if (ix != null) ixS = "INDEX("+ix.debugName+")"; - } - Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5, - UDELTA5, SIGNED5, DELTA5, MDELTA5 }; - String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5", - "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" }; - Coding rc = b.regularCoding; - int rci = Arrays.asList(knownc).indexOf(rc); - String cstr; - if (rci >= 0) - cstr = knowns[rci]; - else - cstr = "CODING"+rc.keyString(); - System.out.println(" BAND_INIT(\""+b.name()+"\"" - +", "+cstr+", "+ixS+"),"); - } - - private Map prevForAssertMap; - - // DEBUG ONLY: Record something about the band order. - boolean notePrevForAssert(Band b, Band p) { - if (prevForAssertMap == null) - prevForAssertMap = new HashMap<>(); - prevForAssertMap.put(b, p); - return true; - } - - // DEBUG ONLY: Validate next input band, ensure bands are read in sequence - private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException { - Band p = prevForAssertMap.get(b); - // Any previous band must be done reading before this one starts. - if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) { - Utils.log.warning("Previous band not done reading."); - Utils.log.info(" Previous band: "+p); - Utils.log.info(" Next band: "+b); - assert(verbose > 0); // die unless verbose is true - } - String name = b.name; - if (optDebugBands && !name.startsWith("(")) { - assert(bandSequenceList != null); - // Verify synchronization between reader & writer: - String inName = bandSequenceList.removeFirst(); - // System.out.println("Reading: " + name); - if (!inName.equals(name)) { - Utils.log.warning("Expected " + name + " but read: " + inName); - return false; - } - Utils.log.info("Read band in sequence: " + name); - } - return true; - } - - // DEBUG ONLY: Make sure a bunch of cprefs are correct. - private boolean assertValidCPRefs(CPRefBand b) { - if (b.index == null) return true; - int limit = b.index.size()+1; - for (int i = 0; i < b.length(); i++) { - int v = b.valueAtForDebug(i); - if (v < 0 || v >= limit) { - Utils.log.warning("CP ref out of range "+ - "["+i+"] = "+v+" in "+b); - return false; - } - } - return true; - } - - /* - * DEBUG ONLY: write the bands to a list and read back the list in order, - * this works perfectly if we use the java packer and unpacker, typically - * this will work with --repack or if they are in the same jvm instance. - */ - static LinkedList bandSequenceList = null; - private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException { - Band p = prevForAssertMap.get(b); - // Any previous band must be done writing before this one starts. - if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) { - Utils.log.warning("Previous band not done writing."); - Utils.log.info(" Previous band: "+p); - Utils.log.info(" Next band: "+b); - assert(verbose > 0); // die unless verbose is true - } - String name = b.name; - if (optDebugBands && !name.startsWith("(")) { - if (bandSequenceList == null) - bandSequenceList = new LinkedList<>(); - // Verify synchronization between reader & writer: - bandSequenceList.add(name); - // System.out.println("Writing: " + b); - } - return true; - } - - protected static boolean testBit(int flags, int bitMask) { - return (flags & bitMask) != 0; - } - protected static int setBit(int flags, int bitMask, boolean z) { - return z ? (flags | bitMask) : (flags &~ bitMask); - } - protected static boolean testBit(long flags, long bitMask) { - return (flags & bitMask) != 0; - } - protected static long setBit(long flags, long bitMask, boolean z) { - return z ? (flags | bitMask) : (flags &~ bitMask); - } - - - static void printArrayTo(PrintStream ps, int[] values, int start, int end) { - int len = end-start; - for (int i = 0; i < len; i++) { - if (i % 10 == 0) - ps.println(); - else - ps.print(" "); - ps.print(values[start+i]); - } - ps.println(); - } - - static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) { - printArrayTo(ps, cpMap, start, end, false); - } - static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end, boolean showTags) { - StringBuffer buf = new StringBuffer(); - int len = end-start; - for (int i = 0; i < len; i++) { - Entry e = cpMap[start+i]; - ps.print(start+i); ps.print("="); - if (showTags) { ps.print(e.tag); ps.print(":"); } - String s = e.stringValue(); - buf.setLength(0); - for (int j = 0; j < s.length(); j++) { - char ch = s.charAt(j); - if (!(ch < ' ' || ch > '~' || ch == '\\')) { - buf.append(ch); - } else if (ch == '\\') { - buf.append("\\\\"); - } else if (ch == '\n') { - buf.append("\\n"); - } else if (ch == '\t') { - buf.append("\\t"); - } else if (ch == '\r') { - buf.append("\\r"); - } else { - String str = "000"+Integer.toHexString(ch); - buf.append("\\u").append(str.substring(str.length()-4)); - } - } - ps.println(buf); - } - } - - - // Utilities for reallocating: - protected static Object[] realloc(Object[] a, int len) { - java.lang.Class elt = a.getClass().getComponentType(); - Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len); - System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); - return na; - } - protected static Object[] realloc(Object[] a) { - return realloc(a, Math.max(10, a.length*2)); - } - - protected static int[] realloc(int[] a, int len) { - if (len == 0) return noInts; - if (a == null) return new int[len]; - int[] na = new int[len]; - System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); - return na; - } - protected static int[] realloc(int[] a) { - return realloc(a, Math.max(10, a.length*2)); - } - - protected static byte[] realloc(byte[] a, int len) { - if (len == 0) return noBytes; - if (a == null) return new byte[len]; - byte[] na = new byte[len]; - System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); - return na; - } - protected static byte[] realloc(byte[] a) { - return realloc(a, Math.max(10, a.length*2)); - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java deleted file mode 100644 index 68d0a985a6a..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassReader.java +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; -import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; -import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; -import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry; -import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; -import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; -import com.sun.java.util.jar.pack.Package.Class; -import com.sun.java.util.jar.pack.Package.InnerClass; -import java.io.DataInputStream; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Reader for a class file that is being incorporated into a package. - * @author John Rose - */ -class ClassReader { - int verbose; - - Package pkg; - Class cls; - long inPos; - long constantPoolLimit = -1; - DataInputStream in; - Map attrDefs; - Map attrCommands; - String unknownAttrCommand = "error";; - - ClassReader(Class cls, InputStream in) throws IOException { - this.pkg = cls.getPackage(); - this.cls = cls; - this.verbose = pkg.verbose; - this.in = new DataInputStream(new FilterInputStream(in) { - public int read(byte b[], int off, int len) throws IOException { - int nr = super.read(b, off, len); - if (nr >= 0) inPos += nr; - return nr; - } - public int read() throws IOException { - int ch = super.read(); - if (ch >= 0) inPos += 1; - return ch; - } - public long skip(long n) throws IOException { - long ns = super.skip(n); - if (ns >= 0) inPos += ns; - return ns; - } - }); - } - - public void setAttrDefs(Map attrDefs) { - this.attrDefs = attrDefs; - } - - public void setAttrCommands(Map attrCommands) { - this.attrCommands = attrCommands; - } - - private void skip(int n, String what) throws IOException { - Utils.log.warning("skipping "+n+" bytes of "+what); - long skipped = 0; - while (skipped < n) { - long j = in.skip(n - skipped); - assert(j > 0); - skipped += j; - } - assert(skipped == n); - } - - private int readUnsignedShort() throws IOException { - return in.readUnsignedShort(); - } - - private int readInt() throws IOException { - return in.readInt(); - } - - /** Read a 2-byte int, and return the global CP entry for it. */ - private Entry readRef() throws IOException { - int i = in.readUnsignedShort(); - return i == 0 ? null : cls.cpMap[i]; - } - - private Entry readRef(byte tag) throws IOException { - Entry e = readRef(); - assert(!(e instanceof UnresolvedEntry)); - checkTag(e, tag); - return e; - } - - /** Throw a ClassFormatException if the entry does not match the expected tag type. */ - private Entry checkTag(Entry e, byte tag) throws ClassFormatException { - if (e == null || !e.tagMatches(tag)) { - String where = (inPos == constantPoolLimit - ? " in constant pool" - : " at pos: " + inPos); - String got = (e == null - ? "null CP index" - : "type=" + ConstantPool.tagName(e.tag)); - throw new ClassFormatException("Bad constant, expected type=" + - ConstantPool.tagName(tag) + - " got "+ got + ", in File: " + cls.file.nameString + where); - } - return e; - } - private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException { - return nullOK && e == null ? null : checkTag(e, tag); - } - - private Entry readRefOrNull(byte tag) throws IOException { - Entry e = readRef(); - checkTag(e, tag, true); - return e; - } - - private Utf8Entry readUtf8Ref() throws IOException { - return (Utf8Entry) readRef(CONSTANT_Utf8); - } - - private ClassEntry readClassRef() throws IOException { - return (ClassEntry) readRef(CONSTANT_Class); - } - - private ClassEntry readClassRefOrNull() throws IOException { - return (ClassEntry) readRefOrNull(CONSTANT_Class); - } - - private SignatureEntry readSignatureRef() throws IOException { - // The class file stores a Utf8, but we want a Signature. - Entry e = readRef(CONSTANT_Signature); - return (e != null && e.getTag() == CONSTANT_Utf8) - ? ConstantPool.getSignatureEntry(e.stringValue()) - : (SignatureEntry) e; - } - - void read() throws IOException { - boolean ok = false; - try { - readMagicNumbers(); - readConstantPool(); - readHeader(); - readMembers(false); // fields - readMembers(true); // methods - readAttributes(ATTR_CONTEXT_CLASS, cls); - fixUnresolvedEntries(); - cls.finishReading(); - assert(0 >= in.read(new byte[1])); - ok = true; - } finally { - if (!ok) { - if (verbose > 0) Utils.log.warning("Erroneous data at input offset "+inPos+" of "+cls.file); - } - } - } - - void readMagicNumbers() throws IOException { - cls.magic = in.readInt(); - if (cls.magic != JAVA_MAGIC) - throw new Attribute.FormatException - ("Bad magic number in class file " - +Integer.toHexString(cls.magic), - ATTR_CONTEXT_CLASS, "magic-number", "pass"); - int minver = (short) readUnsignedShort(); - int majver = (short) readUnsignedShort(); - cls.version = Package.Version.of(majver, minver); - - //System.out.println("ClassFile.version="+cls.majver+"."+cls.minver); - String bad = checkVersion(cls.version); - if (bad != null) { - throw new Attribute.FormatException - ("classfile version too "+bad+": " - +cls.version+" in "+cls.file, - ATTR_CONTEXT_CLASS, "version", "pass"); - } - } - - private String checkVersion(Package.Version ver) { - int majver = ver.major; - int minver = ver.minor; - if (majver < pkg.minClassVersion.major || - (majver == pkg.minClassVersion.major && - minver < pkg.minClassVersion.minor)) { - return "small"; - } - if (majver > pkg.maxClassVersion.major || - (majver == pkg.maxClassVersion.major && - minver > pkg.maxClassVersion.minor)) { - return "large"; - } - return null; // OK - } - - void readConstantPool() throws IOException { - int length = in.readUnsignedShort(); - //System.err.println("reading CP, length="+length); - - int[] fixups = new int[length*4]; - int fptr = 0; - - Entry[] cpMap = new Entry[length]; - cpMap[0] = null; - for (int i = 1; i < length; i++) { - //System.err.println("reading CP elt, i="+i); - int tag = in.readByte(); - switch (tag) { - case CONSTANT_Utf8: - cpMap[i] = ConstantPool.getUtf8Entry(in.readUTF()); - break; - case CONSTANT_Integer: - { - cpMap[i] = ConstantPool.getLiteralEntry(in.readInt()); - } - break; - case CONSTANT_Float: - { - cpMap[i] = ConstantPool.getLiteralEntry(in.readFloat()); - } - break; - case CONSTANT_Long: - { - cpMap[i] = ConstantPool.getLiteralEntry(in.readLong()); - cpMap[++i] = null; - } - break; - case CONSTANT_Double: - { - cpMap[i] = ConstantPool.getLiteralEntry(in.readDouble()); - cpMap[++i] = null; - } - break; - - // just read the refs; do not attempt to resolve while reading - case CONSTANT_Class: - case CONSTANT_String: - case CONSTANT_MethodType: - fixups[fptr++] = i; - fixups[fptr++] = tag; - fixups[fptr++] = in.readUnsignedShort(); - fixups[fptr++] = -1; // empty ref2 - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - case CONSTANT_NameandType: - fixups[fptr++] = i; - fixups[fptr++] = tag; - fixups[fptr++] = in.readUnsignedShort(); - fixups[fptr++] = in.readUnsignedShort(); - break; - case CONSTANT_InvokeDynamic: - fixups[fptr++] = i; - fixups[fptr++] = tag; - fixups[fptr++] = -1 ^ in.readUnsignedShort(); // not a ref - fixups[fptr++] = in.readUnsignedShort(); - break; - case CONSTANT_MethodHandle: - fixups[fptr++] = i; - fixups[fptr++] = tag; - fixups[fptr++] = -1 ^ in.readUnsignedByte(); - fixups[fptr++] = in.readUnsignedShort(); - break; - default: - throw new ClassFormatException("Bad constant pool tag " + - tag + " in File: " + cls.file.nameString + - " at pos: " + inPos); - } - } - constantPoolLimit = inPos; - - // Fix up refs, which might be out of order. - while (fptr > 0) { - if (verbose > 3) - Utils.log.fine("CP fixups ["+fptr/4+"]"); - int flimit = fptr; - fptr = 0; - for (int fi = 0; fi < flimit; ) { - int cpi = fixups[fi++]; - int tag = fixups[fi++]; - int ref = fixups[fi++]; - int ref2 = fixups[fi++]; - if (verbose > 3) - Utils.log.fine(" cp["+cpi+"] = "+ConstantPool.tagName(tag)+"{"+ref+","+ref2+"}"); - if (ref >= 0 && cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) { - // Defer. - fixups[fptr++] = cpi; - fixups[fptr++] = tag; - fixups[fptr++] = ref; - fixups[fptr++] = ref2; - continue; - } - switch (tag) { - case CONSTANT_Class: - cpMap[cpi] = ConstantPool.getClassEntry(cpMap[ref].stringValue()); - break; - case CONSTANT_String: - cpMap[cpi] = ConstantPool.getStringEntry(cpMap[ref].stringValue()); - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class); - DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); - cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr); - break; - case CONSTANT_NameandType: - Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8); - Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature); - cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype); - break; - case CONSTANT_MethodType: - cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature)); - break; - case CONSTANT_MethodHandle: - byte refKind = (byte)(-1 ^ ref); - MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember); - cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef); - break; - case CONSTANT_InvokeDynamic: - DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); - cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr); - // Note that ref must be resolved later, using the BootstrapMethods attribute. - break; - default: - assert(false); - } - } - assert(fptr < flimit); // Must make progress. - } - - cls.cpMap = cpMap; - } - - private /*non-static*/ - class UnresolvedEntry extends Entry { - final Object[] refsOrIndexes; - UnresolvedEntry(byte tag, Object... refsOrIndexes) { - super(tag); - this.refsOrIndexes = refsOrIndexes; - ClassReader.this.haveUnresolvedEntry = true; - } - Entry resolve() { - Class cls = ClassReader.this.cls; - Entry res; - switch (tag) { - case CONSTANT_InvokeDynamic: - BootstrapMethodEntry iboots = cls.bootstrapMethods.get((Integer) refsOrIndexes[0]); - DescriptorEntry idescr = (DescriptorEntry) refsOrIndexes[1]; - res = ConstantPool.getInvokeDynamicEntry(iboots, idescr); - break; - default: - throw new AssertionError(); - } - return res; - } - private void unresolved() { throw new RuntimeException("unresolved entry has no string"); } - public int compareTo(Object x) { unresolved(); return 0; } - public boolean equals(Object x) { unresolved(); return false; } - protected int computeValueHash() { unresolved(); return 0; } - public String stringValue() { unresolved(); return toString(); } - public String toString() { return "(unresolved "+ConstantPool.tagName(tag)+")"; } - } - - boolean haveUnresolvedEntry; - private void fixUnresolvedEntries() { - if (!haveUnresolvedEntry) return; - Entry[] cpMap = cls.getCPMap(); - for (int i = 0; i < cpMap.length; i++) { - Entry e = cpMap[i]; - if (e instanceof UnresolvedEntry) { - cpMap[i] = e = ((UnresolvedEntry)e).resolve(); - assert(!(e instanceof UnresolvedEntry)); - } - } - haveUnresolvedEntry = false; - } - - void readHeader() throws IOException { - cls.flags = readUnsignedShort(); - cls.thisClass = readClassRef(); - cls.superClass = readClassRefOrNull(); - int ni = readUnsignedShort(); - cls.interfaces = new ClassEntry[ni]; - for (int i = 0; i < ni; i++) { - cls.interfaces[i] = readClassRef(); - } - } - - void readMembers(boolean doMethods) throws IOException { - int nm = readUnsignedShort(); - for (int i = 0; i < nm; i++) { - readMember(doMethods); - } - } - - void readMember(boolean doMethod) throws IOException { - int mflags = readUnsignedShort(); - Utf8Entry mname = readUtf8Ref(); - SignatureEntry mtype = readSignatureRef(); - DescriptorEntry descr = ConstantPool.getDescriptorEntry(mname, mtype); - Class.Member m; - if (!doMethod) - m = cls.new Field(mflags, descr); - else - m = cls.new Method(mflags, descr); - readAttributes(!doMethod ? ATTR_CONTEXT_FIELD : ATTR_CONTEXT_METHOD, - m); - } - void readAttributes(int ctype, Attribute.Holder h) throws IOException { - int na = readUnsignedShort(); - if (na == 0) return; // nothing to do here - if (verbose > 3) - Utils.log.fine("readAttributes "+h+" ["+na+"]"); - for (int i = 0; i < na; i++) { - String name = readUtf8Ref().stringValue(); - int length = readInt(); - // See if there is a special command that applies. - if (attrCommands != null) { - Attribute.Layout lkey = Attribute.keyForLookup(ctype, name); - String cmd = attrCommands.get(lkey); - if (cmd != null) { - switch (cmd) { - case "pass": - String message1 = "passing attribute bitwise in " + h; - throw new Attribute.FormatException(message1, ctype, name, cmd); - case "error": - String message2 = "attribute not allowed in " + h; - throw new Attribute.FormatException(message2, ctype, name, cmd); - case "strip": - skip(length, name + " attribute in " + h); - continue; - } - } - } - // Find canonical instance of the requested attribute. - Attribute a = Attribute.lookup(Package.attrDefs, ctype, name); - if (verbose > 4 && a != null) - Utils.log.fine("pkg_attribute_lookup "+name+" = "+a); - if (a == null) { - a = Attribute.lookup(this.attrDefs, ctype, name); - if (verbose > 4 && a != null) - Utils.log.fine("this "+name+" = "+a); - } - if (a == null) { - a = Attribute.lookup(null, ctype, name); - if (verbose > 4 && a != null) - Utils.log.fine("null_attribute_lookup "+name+" = "+a); - } - if (a == null && length == 0) { - // Any zero-length attr is "known"... - // We can assume an empty attr. has an empty layout. - // Handles markers like Enum, Bridge, Synthetic, Deprecated. - a = Attribute.find(ctype, name, ""); - } - boolean isStackMap = (ctype == ATTR_CONTEXT_CODE - && (name.equals("StackMap") || - name.equals("StackMapX"))); - if (isStackMap) { - // Known attribute but with a corner case format, "pass" it. - Code code = (Code) h; - final int TOO_BIG = 0x10000; - if (code.max_stack >= TOO_BIG || - code.max_locals >= TOO_BIG || - code.getLength() >= TOO_BIG || - name.endsWith("X")) { - // No, we don't really know what to do with this one. - // Do not compress the rare and strange "u4" and "X" cases. - a = null; - } - } - if (a == null) { - if (isStackMap) { - // Known attribute but w/o a format; pass it. - String message = "unsupported StackMap variant in "+h; - throw new Attribute.FormatException(message, ctype, name, - "pass"); - } else if ("strip".equals(unknownAttrCommand)) { - // Skip the unknown attribute. - skip(length, "unknown "+name+" attribute in "+h); - continue; - } else { - String message = " is unknown attribute in class " + h; - throw new Attribute.FormatException(message, ctype, name, - unknownAttrCommand); - } - } - long pos0 = inPos; // in case we want to check it - if (a.layout() == Package.attrCodeEmpty) { - // These are hardwired. - Class.Method m = (Class.Method) h; - m.code = new Code(m); - try { - readCode(m.code); - } catch (Instruction.FormatException iie) { - String message = iie.getMessage() + " in " + h; - throw new ClassReader.ClassFormatException(message, iie); - } - assert(length == inPos - pos0); - // Keep empty attribute a... - } else if (a.layout() == Package.attrBootstrapMethodsEmpty) { - assert(h == cls); - readBootstrapMethods(cls); - assert(length == inPos - pos0); - // Delete the attribute; it is logically part of the constant pool. - continue; - } else if (a.layout() == Package.attrInnerClassesEmpty) { - // These are hardwired also. - assert(h == cls); - readInnerClasses(cls); - assert(length == inPos - pos0); - // Keep empty attribute a... - } else if (length > 0) { - byte[] bytes = new byte[length]; - in.readFully(bytes); - a = a.addContent(bytes); - } - if (a.size() == 0 && !a.layout().isEmpty()) { - throw new ClassFormatException(name + - ": attribute length cannot be zero, in " + h); - } - h.addAttribute(a); - if (verbose > 2) - Utils.log.fine("read "+a); - } - } - - void readCode(Code code) throws IOException { - code.max_stack = readUnsignedShort(); - code.max_locals = readUnsignedShort(); - code.bytes = new byte[readInt()]; - in.readFully(code.bytes); - Entry[] cpMap = cls.getCPMap(); - Instruction.opcodeChecker(code.bytes, cpMap, this.cls.version); - int nh = readUnsignedShort(); - code.setHandlerCount(nh); - for (int i = 0; i < nh; i++) { - code.handler_start[i] = readUnsignedShort(); - code.handler_end[i] = readUnsignedShort(); - code.handler_catch[i] = readUnsignedShort(); - code.handler_class[i] = readClassRefOrNull(); - } - readAttributes(ATTR_CONTEXT_CODE, code); - } - - void readBootstrapMethods(Class cls) throws IOException { - BootstrapMethodEntry[] bsms = new BootstrapMethodEntry[readUnsignedShort()]; - for (int i = 0; i < bsms.length; i++) { - MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle); - Entry[] argRefs = new Entry[readUnsignedShort()]; - for (int j = 0; j < argRefs.length; j++) { - argRefs[j] = readRef(CONSTANT_LoadableValue); - } - bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs); - } - cls.setBootstrapMethods(Arrays.asList(bsms)); - } - - void readInnerClasses(Class cls) throws IOException { - int nc = readUnsignedShort(); - ArrayList ics = new ArrayList<>(nc); - for (int i = 0; i < nc; i++) { - InnerClass ic = - new InnerClass(readClassRef(), - readClassRefOrNull(), - (Utf8Entry)readRefOrNull(CONSTANT_Utf8), - readUnsignedShort()); - ics.add(ic); - } - cls.innerClasses = ics; // set directly; do not use setInnerClasses. - // (Later, ics may be transferred to the pkg.) - } - - static class ClassFormatException extends IOException { - @java.io.Serial - private static final long serialVersionUID = -3564121733989501833L; - - public ClassFormatException(String message) { - super(message); - } - - public ClassFormatException(String message, Throwable cause) { - super(message, cause); - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java deleted file mode 100644 index da48df9af86..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ClassWriter.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - - -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import com.sun.java.util.jar.pack.ConstantPool.Index; -import com.sun.java.util.jar.pack.ConstantPool.NumberEntry; -import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry; -import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; -import com.sun.java.util.jar.pack.Package.Class; -import com.sun.java.util.jar.pack.Package.InnerClass; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.List; -import static com.sun.java.util.jar.pack.Constants.*; -/** - * Writer for a class file that is incorporated into a package. - * @author John Rose - */ -class ClassWriter { - int verbose; - - Package pkg; - Class cls; - DataOutputStream out; - Index cpIndex; - Index bsmIndex; - - ClassWriter(Class cls, OutputStream out) throws IOException { - this.pkg = cls.getPackage(); - this.cls = cls; - this.verbose = pkg.verbose; - this.out = new DataOutputStream(new BufferedOutputStream(out)); - this.cpIndex = ConstantPool.makeIndex(cls.toString(), cls.getCPMap()); - this.cpIndex.flattenSigs = true; - if (cls.hasBootstrapMethods()) { - this.bsmIndex = ConstantPool.makeIndex(cpIndex.debugName+".BootstrapMethods", - cls.getBootstrapMethodMap()); - } - if (verbose > 1) - Utils.log.fine("local CP="+(verbose > 2 ? cpIndex.dumpString() : cpIndex.toString())); - } - - private void writeShort(int x) throws IOException { - out.writeShort(x); - } - - private void writeInt(int x) throws IOException { - out.writeInt(x); - } - - /** Write a 2-byte int representing a CP entry, using the local cpIndex. */ - private void writeRef(Entry e) throws IOException { - writeRef(e, cpIndex); - } - - /** Write a 2-byte int representing a CP entry, using the given cpIndex. */ - private void writeRef(Entry e, Index cpIndex) throws IOException { - int i = (e == null) ? 0 : cpIndex.indexOf(e); - writeShort(i); - } - - void write() throws IOException { - boolean ok = false; - try { - if (verbose > 1) Utils.log.fine("...writing "+cls); - writeMagicNumbers(); - writeConstantPool(); - writeHeader(); - writeMembers(false); // fields - writeMembers(true); // methods - writeAttributes(ATTR_CONTEXT_CLASS, cls); - /* Closing here will cause all the underlying - streams to close, Causing the jar stream - to close prematurely, instead we just flush. - out.close(); - */ - out.flush(); - ok = true; - } finally { - if (!ok) { - Utils.log.warning("Error on output of "+cls); - } - } - } - - void writeMagicNumbers() throws IOException { - writeInt(cls.magic); - writeShort(cls.version.minor); - writeShort(cls.version.major); - } - - void writeConstantPool() throws IOException { - Entry[] cpMap = cls.cpMap; - writeShort(cpMap.length); - for (int i = 0; i < cpMap.length; i++) { - Entry e = cpMap[i]; - assert((e == null) == (i == 0 || cpMap[i-1] != null && cpMap[i-1].isDoubleWord())); - if (e == null) continue; - byte tag = e.getTag(); - if (verbose > 2) Utils.log.fine(" CP["+i+"] = "+e); - out.write(tag); - switch (tag) { - case CONSTANT_Signature: - throw new AssertionError("CP should have Signatures remapped to Utf8"); - case CONSTANT_Utf8: - out.writeUTF(e.stringValue()); - break; - case CONSTANT_Integer: - out.writeInt(((NumberEntry)e).numberValue().intValue()); - break; - case CONSTANT_Float: - float fval = ((NumberEntry)e).numberValue().floatValue(); - out.writeInt(Float.floatToRawIntBits(fval)); - break; - case CONSTANT_Long: - out.writeLong(((NumberEntry)e).numberValue().longValue()); - break; - case CONSTANT_Double: - double dval = ((NumberEntry)e).numberValue().doubleValue(); - out.writeLong(Double.doubleToRawLongBits(dval)); - break; - case CONSTANT_Class: - case CONSTANT_String: - case CONSTANT_MethodType: - writeRef(e.getRef(0)); - break; - case CONSTANT_MethodHandle: - MethodHandleEntry mhe = (MethodHandleEntry) e; - out.writeByte(mhe.refKind); - writeRef(mhe.getRef(0)); - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - case CONSTANT_NameandType: - writeRef(e.getRef(0)); - writeRef(e.getRef(1)); - break; - case CONSTANT_InvokeDynamic: - writeRef(e.getRef(0), bsmIndex); - writeRef(e.getRef(1)); - break; - case CONSTANT_BootstrapMethod: - throw new AssertionError("CP should have BootstrapMethods moved to side-table"); - default: - throw new IOException("Bad constant pool tag "+tag); - } - } - } - - void writeHeader() throws IOException { - writeShort(cls.flags); - writeRef(cls.thisClass); - writeRef(cls.superClass); - writeShort(cls.interfaces.length); - for (int i = 0; i < cls.interfaces.length; i++) { - writeRef(cls.interfaces[i]); - } - } - - void writeMembers(boolean doMethods) throws IOException { - List mems; - if (!doMethods) - mems = cls.getFields(); - else - mems = cls.getMethods(); - writeShort(mems.size()); - for (Class.Member m : mems) { - writeMember(m, doMethods); - } - } - - void writeMember(Class.Member m, boolean doMethod) throws IOException { - if (verbose > 2) Utils.log.fine("writeMember "+m); - writeShort(m.flags); - writeRef(m.getDescriptor().nameRef); - writeRef(m.getDescriptor().typeRef); - writeAttributes(!doMethod ? ATTR_CONTEXT_FIELD : ATTR_CONTEXT_METHOD, - m); - } - - private void reorderBSMandICS(Attribute.Holder h) { - Attribute bsmAttr = h.getAttribute(Package.attrBootstrapMethodsEmpty); - if (bsmAttr == null) return; - - Attribute icsAttr = h.getAttribute(Package.attrInnerClassesEmpty); - if (icsAttr == null) return; - - int bsmidx = h.attributes.indexOf(bsmAttr); - int icsidx = h.attributes.indexOf(icsAttr); - if (bsmidx > icsidx) { - h.attributes.remove(bsmAttr); - h.attributes.add(icsidx, bsmAttr); - } - return; - } - - // handy buffer for collecting attrs - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - DataOutputStream bufOut = new DataOutputStream(buf); - - void writeAttributes(int ctype, Attribute.Holder h) throws IOException { - if (h.attributes == null) { - writeShort(0); // attribute size - return; - } - // there may be cases if an InnerClass attribute is explicit, then the - // ordering could be wrong, fix the ordering before we write it out. - if (h instanceof Package.Class) - reorderBSMandICS(h); - - writeShort(h.attributes.size()); - for (Attribute a : h.attributes) { - a.finishRefs(cpIndex); - writeRef(a.getNameRef()); - if (a.layout() == Package.attrCodeEmpty || - a.layout() == Package.attrBootstrapMethodsEmpty || - a.layout() == Package.attrInnerClassesEmpty) { - // These are hardwired. - DataOutputStream savedOut = out; - assert(out != bufOut); - buf.reset(); - out = bufOut; - if ("Code".equals(a.name())) { - Class.Method m = (Class.Method) h; - writeCode(m.code); - } else if ("BootstrapMethods".equals(a.name())) { - assert(h == cls); - writeBootstrapMethods(cls); - } else if ("InnerClasses".equals(a.name())) { - assert(h == cls); - writeInnerClasses(cls); - } else { - throw new AssertionError(); - } - out = savedOut; - if (verbose > 2) - Utils.log.fine("Attribute "+a.name()+" ["+buf.size()+"]"); - writeInt(buf.size()); - buf.writeTo(out); - } else { - if (verbose > 2) - Utils.log.fine("Attribute "+a.name()+" ["+a.size()+"]"); - writeInt(a.size()); - out.write(a.bytes()); - } - } - } - - void writeCode(Code code) throws IOException { - code.finishRefs(cpIndex); - writeShort(code.max_stack); - writeShort(code.max_locals); - writeInt(code.bytes.length); - out.write(code.bytes); - int nh = code.getHandlerCount(); - writeShort(nh); - for (int i = 0; i < nh; i++) { - writeShort(code.handler_start[i]); - writeShort(code.handler_end[i]); - writeShort(code.handler_catch[i]); - writeRef(code.handler_class[i]); - } - writeAttributes(ATTR_CONTEXT_CODE, code); - } - - void writeBootstrapMethods(Class cls) throws IOException { - List bsms = cls.getBootstrapMethods(); - writeShort(bsms.size()); - for (BootstrapMethodEntry e : bsms) { - writeRef(e.bsmRef); - writeShort(e.argRefs.length); - for (Entry argRef : e.argRefs) { - writeRef(argRef); - } - } - } - - void writeInnerClasses(Class cls) throws IOException { - List ics = cls.getInnerClasses(); - writeShort(ics.size()); - for (InnerClass ic : ics) { - writeRef(ic.thisClass); - writeRef(ic.outerClass); - writeRef(ic.name); - writeShort(ic.flags); - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java deleted file mode 100644 index c69578af775..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Code.java +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.Package.Class; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collection; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Represents a chunk of bytecodes. - * @author John Rose - */ -class Code extends Attribute.Holder { - Class.Method m; - - public Code(Class.Method m) { - this.m = m; - } - - public Class.Method getMethod() { - return m; - } - public Class thisClass() { - return m.thisClass(); - } - public Package getPackage() { - return m.thisClass().getPackage(); - } - - public ConstantPool.Entry[] getCPMap() { - return m.getCPMap(); - } - - private static final ConstantPool.Entry[] noRefs = ConstantPool.noRefs; - - // The following fields are used directly by the ClassReader, etc. - int max_stack; - int max_locals; - - ConstantPool.Entry handler_class[] = noRefs; - int handler_start[] = noInts; - int handler_end[] = noInts; - int handler_catch[] = noInts; - - byte[] bytes; - Fixups fixups; // reference relocations, if any are required - Object insnMap; // array of instruction boundaries - - int getLength() { return bytes.length; } - - int getMaxStack() { - return max_stack; - } - void setMaxStack(int ms) { - max_stack = ms; - } - - int getMaxNALocals() { - int argsize = m.getArgumentSize(); - return max_locals - argsize; - } - void setMaxNALocals(int ml) { - int argsize = m.getArgumentSize(); - max_locals = argsize + ml; - } - - int getHandlerCount() { - assert(handler_class.length == handler_start.length); - assert(handler_class.length == handler_end.length); - assert(handler_class.length == handler_catch.length); - return handler_class.length; - } - void setHandlerCount(int h) { - if (h > 0) { - handler_class = new ConstantPool.Entry[h]; - handler_start = new int[h]; - handler_end = new int[h]; - handler_catch = new int[h]; - // caller must fill these in ASAP - } - } - - void setBytes(byte[] bytes) { - this.bytes = bytes; - if (fixups != null) - fixups.setBytes(bytes); - } - - void setInstructionMap(int[] insnMap, int mapLen) { - //int[] oldMap = null; - //assert((oldMap = getInstructionMap()) != null); - this.insnMap = allocateInstructionMap(insnMap, mapLen); - //assert(Arrays.equals(oldMap, getInstructionMap())); - } - void setInstructionMap(int[] insnMap) { - setInstructionMap(insnMap, insnMap.length); - } - - int[] getInstructionMap() { - return expandInstructionMap(getInsnMap()); - } - - void addFixups(Collection moreFixups) { - if (fixups == null) { - fixups = new Fixups(bytes); - } - assert(fixups.getBytes() == bytes); - fixups.addAll(moreFixups); - } - - public void trimToSize() { - if (fixups != null) { - fixups.trimToSize(); - if (fixups.size() == 0) - fixups = null; - } - super.trimToSize(); - } - - protected void visitRefs(int mode, Collection refs) { - int verbose = getPackage().verbose; - if (verbose > 2) - System.out.println("Reference scan "+this); - refs.addAll(Arrays.asList(handler_class)); - if (fixups != null) { - fixups.visitRefs(refs); - } else { - // References (to a local cpMap) are embedded in the bytes. - ConstantPool.Entry[] cpMap = getCPMap(); - for (Instruction i = instructionAt(0); i != null; i = i.next()) { - if (verbose > 4) - System.out.println(i); - int cpref = i.getCPIndex(); - if (cpref >= 0) { - refs.add(cpMap[cpref]); - } - } - } - // Handle attribute list: - super.visitRefs(mode, refs); - } - - // Since bytecodes are the single largest contributor to - // package size, it's worth a little bit of trouble - // to reduce the per-bytecode memory footprint. - // In the current scheme, half of the bulk of these arrays - // due to bytes, and half to shorts. (Ints are insignificant.) - // Given an average of 1.8 bytes per instruction, this means - // instruction boundary arrays are about a 75% overhead--tolerable. - // (By using bytes, we get 33% savings over just shorts and ints. - // Using both bytes and shorts gives 66% savings over just ints.) - static final boolean shrinkMaps = true; - - private Object allocateInstructionMap(int[] insnMap, int mapLen) { - int PClimit = getLength(); - if (shrinkMaps && PClimit <= Byte.MAX_VALUE - Byte.MIN_VALUE) { - byte[] map = new byte[mapLen+1]; - for (int i = 0; i < mapLen; i++) { - map[i] = (byte)(insnMap[i] + Byte.MIN_VALUE); - } - map[mapLen] = (byte)(PClimit + Byte.MIN_VALUE); - return map; - } else if (shrinkMaps && PClimit < Short.MAX_VALUE - Short.MIN_VALUE) { - short[] map = new short[mapLen+1]; - for (int i = 0; i < mapLen; i++) { - map[i] = (short)(insnMap[i] + Short.MIN_VALUE); - } - map[mapLen] = (short)(PClimit + Short.MIN_VALUE); - return map; - } else { - int[] map = Arrays.copyOf(insnMap, mapLen + 1); - map[mapLen] = PClimit; - return map; - } - } - private int[] expandInstructionMap(Object map0) { - int[] imap; - if (map0 instanceof byte[]) { - byte[] map = (byte[]) map0; - imap = new int[map.length-1]; - for (int i = 0; i < imap.length; i++) { - imap[i] = map[i] - Byte.MIN_VALUE; - } - } else if (map0 instanceof short[]) { - short[] map = (short[]) map0; - imap = new int[map.length-1]; - for (int i = 0; i < imap.length; i++) { - imap[i] = map[i] - Byte.MIN_VALUE; - } - } else { - int[] map = (int[]) map0; - imap = Arrays.copyOfRange(map, 0, map.length - 1); - } - return imap; - } - - Object getInsnMap() { - // Build a map of instruction boundaries. - if (insnMap != null) { - return insnMap; - } - int[] map = new int[getLength()]; - int fillp = 0; - for (Instruction i = instructionAt(0); i != null; i = i.next()) { - map[fillp++] = i.getPC(); - } - // Make it byte[], short[], or int[] according to the max BCI. - insnMap = allocateInstructionMap(map, fillp); - //assert(assertBCICodingsOK()); - return insnMap; - } - - /** Encode the given BCI as an instruction boundary number. - * For completeness, irregular (non-boundary) BCIs are - * encoded compactly immediately after the boundary numbers. - * This encoding is the identity mapping outside 0..length, - * and it is 1-1 everywhere. All by itself this technique - * improved zipped rt.jar compression by 2.6%. - */ - public int encodeBCI(int bci) { - if (bci <= 0 || bci > getLength()) return bci; - Object map0 = getInsnMap(); - int i, len; - if (shrinkMaps && map0 instanceof byte[]) { - byte[] map = (byte[]) map0; - len = map.length; - i = Arrays.binarySearch(map, (byte)(bci + Byte.MIN_VALUE)); - } else if (shrinkMaps && map0 instanceof short[]) { - short[] map = (short[]) map0; - len = map.length; - i = Arrays.binarySearch(map, (short)(bci + Short.MIN_VALUE)); - } else { - int[] map = (int[]) map0; - len = map.length; - i = Arrays.binarySearch(map, bci); - } - assert(i != -1); - assert(i != 0); - assert(i != len); - assert(i != -len-1); - return (i >= 0) ? i : len + bci - (-i-1); - } - public int decodeBCI(int bciCode) { - if (bciCode <= 0 || bciCode > getLength()) return bciCode; - Object map0 = getInsnMap(); - int i, len; - // len == map.length - // If bciCode < len, result is map[bciCode], the common and fast case. - // Otherwise, let map[i] be the smallest map[*] larger than bci. - // Then, required by the return statement of encodeBCI: - // bciCode == len + bci - i - // Thus: - // bci-i == bciCode-len - // map[i]-adj-i == bciCode-len ; adj in (0..map[i]-map[i-1]) - // We can solve this by searching for adjacent entries - // map[i-1], map[i] such that: - // map[i-1]-(i-1) <= bciCode-len < map[i]-i - // This can be approximated by searching map[i] for bciCode and then - // linear searching backward. Given the right i, we then have: - // bci == bciCode-len + i - // This linear search is at its worst case for indexes in the beginning - // of a large method, but it's not clear that this is a problem in - // practice, since BCIs are usually on instruction boundaries. - if (shrinkMaps && map0 instanceof byte[]) { - byte[] map = (byte[]) map0; - len = map.length; - if (bciCode < len) - return map[bciCode] - Byte.MIN_VALUE; - i = Arrays.binarySearch(map, (byte)(bciCode + Byte.MIN_VALUE)); - if (i < 0) i = -i-1; - int key = bciCode-len + Byte.MIN_VALUE; - for (;; i--) { - if (map[i-1]-(i-1) <= key) break; - } - } else if (shrinkMaps && map0 instanceof short[]) { - short[] map = (short[]) map0; - len = map.length; - if (bciCode < len) - return map[bciCode] - Short.MIN_VALUE; - i = Arrays.binarySearch(map, (short)(bciCode + Short.MIN_VALUE)); - if (i < 0) i = -i-1; - int key = bciCode-len + Short.MIN_VALUE; - for (;; i--) { - if (map[i-1]-(i-1) <= key) break; - } - } else { - int[] map = (int[]) map0; - len = map.length; - if (bciCode < len) - return map[bciCode]; - i = Arrays.binarySearch(map, bciCode); - if (i < 0) i = -i-1; - int key = bciCode-len; - for (;; i--) { - if (map[i-1]-(i-1) <= key) break; - } - } - return bciCode-len + i; - } - - public void finishRefs(ConstantPool.Index ix) { - if (fixups != null) { - fixups.finishRefs(ix); - fixups = null; - } - // Code attributes are finished in ClassWriter.writeAttributes. - } - - Instruction instructionAt(int pc) { - return Instruction.at(bytes, pc); - } - - static boolean flagsRequireCode(int flags) { - // A method's flags force it to have a Code attribute, - // if the flags are neither native nor abstract. - return (flags & (Modifier.NATIVE | Modifier.ABSTRACT)) == 0; - } - - public String toString() { - return m+".Code"; - } - - /// Fetching values from my own array. - public int getInt(int pc) { return Instruction.getInt(bytes, pc); } - public int getShort(int pc) { return Instruction.getShort(bytes, pc); } - public int getByte(int pc) { return Instruction.getByte(bytes, pc); } - void setInt(int pc, int x) { Instruction.setInt(bytes, pc, x); } - void setShort(int pc, int x) { Instruction.setShort(bytes, pc, x); } - void setByte(int pc, int x) { Instruction.setByte(bytes, pc, x); } - -/* TEST CODE ONLY - private boolean assertBCICodingsOK() { - boolean ok = true; - int len = java.lang.reflect.Array.getLength(insnMap); - int base = 0; - if (insnMap.getClass().getComponentType() == Byte.TYPE) - base = Byte.MIN_VALUE; - if (insnMap.getClass().getComponentType() == Short.TYPE) - base = Short.MIN_VALUE; - for (int i = -1, imax = getLength()+1; i <= imax; i++) { - int bci = i; - int enc = Math.min(-999, bci-1); - int dec = enc; - try { - enc = encodeBCI(bci); - dec = decodeBCI(enc); - } catch (RuntimeException ee) { - ee.printStackTrace(); - } - if (dec == bci) { - //System.out.println("BCI="+bci+(enc, CodingMethod, Histogram.BitMetric { - /* - Coding schema for single integers, parameterized by (B,H,S): - - Let B in [1,5], H in [1,256], S in [0,3]. - (S limit is arbitrary. B follows the 32-bit limit. H is byte size.) - - A given (B,H,S) code varies in length from 1 to B bytes. - - The 256 values a byte may take on are divided into L=(256-H) and H - values, with all the H values larger than the L values. - (That is, the L values are [0,L) and the H are [L,256).) - - The last byte is always either the B-th byte, a byte with "L value" - (=L). - - Therefore, if L==0, the code always has the full length of B bytes. - The coding then becomes a classic B-byte little-endian unsigned integer. - (Also, if L==128, the high bit of each byte acts signals the presence - of a following byte, up to the maximum length.) - - In the unsigned case (S==0), the coding is compact and monotonic - in the ordering of byte sequences defined by appending zero bytes - to pad them to a common length B, reversing them, and ordering them - lexicographically. (This agrees with "little-endian" byte order.) - - Therefore, the unsigned value of a byte sequence may be defined as: -
-        U(b0)           == b0
-                           in [0..L)
-                           or [0..256) if B==1 (**)
-
-        U(b0,b1)        == b0 + b1*H
-                           in [L..L*(1+H))
-                           or [L..L*(1+H) + H^2) if B==2
-
-        U(b0,b1,b2)     == b0 + b1*H + b2*H^2
-                           in [L*(1+H)..L*(1+H+H^2))
-                           or [L*(1+H)..L*(1+H+H^2) + H^3) if B==3
-
-        U(b[i]: i
-
-      (**) If B==1, the values H,L play no role in the coding.
-      As a convention, we require that any (1,H,S) code must always
-      encode values less than H.  Thus, a simple unsigned byte is coded
-      specifically by the code (1,256,0).
-
-      (Properly speaking, the unsigned case should be parameterized as
-      S==Infinity.  If the schema were regular, the case S==0 would really
-      denote a numbering in which all coded values are negative.)
-
-      If S>0, the unsigned value of a byte sequence is regarded as a binary
-      integer.  If any of the S low-order bits are zero, the corresponding
-      signed value will be non-negative.  If all of the S low-order bits
-      (S>0) are one, the corresponding signed value will be negative.
-
-      The non-negative signed values are compact and monotonically increasing
-      (from 0) in the ordering of the corresponding unsigned values.
-
-      The negative signed values are compact and monotonically decreasing
-      (from -1) in the ordering of the corresponding unsigned values.
-
-      In essence, the low-order S bits function as a collective sign bit
-      for negative signed numbers, and as a low-order base-(2^S-1) digit
-      for non-negative signed numbers.
-
-      Therefore, the signed value corresponding to an unsigned value is:
-      
-        Sgn(x)  == x                               if S==0
-        Sgn(x)  == (x / 2^S)*(2^S-1) + (x % 2^S),  if S>0, (x % 2^S) < 2^S-1
-        Sgn(x)  == -(x / 2^S)-1,                   if S>0, (x % 2^S) == 2^S-1
-      
- - Finally, the value of a byte sequence, given the coding parameters - (B,H,S), is defined as: -
-        V(b[i]: i
-
-      The extremal positive and negative signed value for a given range
-      of unsigned values may be found by sign-encoding the largest unsigned
-      value which is not 2^S-1 mod 2^S, and that which is, respectively.
-
-      Because B,H,S are variable, this is not a single coding but a schema
-      of codings.  For optimal compression, it is necessary to adaptively
-      select specific codings to the data being compressed.
-
-      For example, if a sequence of values happens never to be negative,
-      S==0 is the best choice.  If the values are equally balanced between
-      negative and positive, S==1.  If negative values are rare, then S>1
-      is more appropriate.
-
-      A (B,H,S) encoding is called a "subrange" if it does not encode
-      the largest 32-bit value, and if the number R of values it does
-      encode can be expressed as a positive 32-bit value.  (Note that
-      B=1 implies R<=256, B=2 implies R<=65536, etc.)
-
-      A delta version of a given (B,H,S) coding encodes an array of integers
-      by writing their successive differences in the (B,H,S) coding.
-      The original integers themselves may be recovered by making a
-      running accumulation of sum of the differences as they are read.
-
-      As a special case, if a (B,H,S) encoding is a subrange, its delta
-      version will only encode arrays of numbers in the coding's unsigned
-      range, [0..R-1].  The coding of deltas is still in the normal signed
-      range, if S!=0.  During delta encoding, all subtraction results are
-      reduced to the signed range, by adding multiples of R.  Likewise,
-.     during encoding, all addition results are reduced to the unsigned range.
-      This special case for subranges allows the benefits of wraparound
-      when encoding correlated sequences of very small positive numbers.
-     */
-
-    // Code-specific limits:
-    private static int saturate32(long x) {
-        if (x > Integer.MAX_VALUE)   return Integer.MAX_VALUE;
-        if (x < Integer.MIN_VALUE)   return Integer.MIN_VALUE;
-        return (int)x;
-    }
-    private static long codeRangeLong(int B, int H) {
-        return codeRangeLong(B, H, B);
-    }
-    private static long codeRangeLong(int B, int H, int nMax) {
-        // Code range for a all (B,H) codes of length <=nMax (<=B).
-        // n < B:   L*Sum[i= 0 && nMax <= B);
-        assert(B >= 1 && B <= 5);
-        assert(H >= 1 && H <= 256);
-        if (nMax == 0)  return 0;  // no codes of zero length
-        if (B == 1)     return H;  // special case; see (**) above
-        int L = 256-H;
-        long sum = 0;
-        long H_i = 1;
-        for (int n = 1; n <= nMax; n++) {
-            sum += H_i;
-            H_i *= H;
-        }
-        sum *= L;
-        if (nMax == B)
-            sum += H_i;
-        return sum;
-    }
-    /** Largest int representable by (B,H,S) in up to nMax bytes. */
-    public static int codeMax(int B, int H, int S, int nMax) {
-        //assert(S >= 0 && S <= S_MAX);
-        long range = codeRangeLong(B, H, nMax);
-        if (range == 0)
-            return -1;  // degenerate max value for empty set of codes
-        if (S == 0 || range >= (long)1<<32)
-            return saturate32(range-1);
-        long maxPos = range-1;
-        while (isNegativeCode(maxPos, S)) {
-            --maxPos;
-        }
-        if (maxPos < 0)  return -1;  // No positive codings at all.
-        int smax = decodeSign32(maxPos, S);
-        // check for 32-bit wraparound:
-        if (smax < 0)
-            return Integer.MAX_VALUE;
-        return smax;
-    }
-    /** Smallest int representable by (B,H,S) in up to nMax bytes.
-        Returns Integer.MIN_VALUE if 32-bit wraparound covers
-        the entire negative range.
-     */
-    public static int codeMin(int B, int H, int S, int nMax) {
-        //assert(S >= 0 && S <= S_MAX);
-        long range = codeRangeLong(B, H, nMax);
-        if (range >= (long)1<<32 && nMax == B) {
-            // Can code negative values via 32-bit wraparound.
-            return Integer.MIN_VALUE;
-        }
-        if (S == 0) {
-            return 0;
-        }
-        long maxNeg = range-1;
-        while (!isNegativeCode(maxNeg, S))
-            --maxNeg;
-
-        if (maxNeg < 0)  return 0;  // No negative codings at all.
-        return decodeSign32(maxNeg, S);
-    }
-
-    // Some of the arithmetic below is on unsigned 32-bit integers.
-    // These must be represented in Java as longs in the range [0..2^32-1].
-    // The conversion to a signed int is just the Java cast (int), but
-    // the conversion to an unsigned int is the following little method:
-    private static long toUnsigned32(int sx) {
-        return ((long)sx << 32) >>> 32;
-    }
-
-    // Sign encoding:
-    private static boolean isNegativeCode(long ux, int S) {
-        assert(S > 0);
-        assert(ux >= -1);  // can be out of 32-bit range; who cares
-        int Smask = (1< 0);
-        // If S>=2 very low negatives are coded by 32-bit-wrapped positives.
-        // The lowest negative representable by a negative coding is
-        // ~(umax32 >> S), and the next lower number is coded by wrapping
-        // the highest positive:
-        //    CodePos(umax32-1)  ->  (umax32-1)-((umax32-1)>>S)
-        // which simplifies to ~(umax32 >> S)-1.
-        return (0 > sx) && (sx >= ~(-1>>>S));
-    }
-    private static int decodeSign32(long ux, int S) {
-        assert(ux == toUnsigned32((int)ux))  // must be unsigned 32-bit number
-            : (Long.toHexString(ux));
-        if (S == 0) {
-            return (int) ux;  // cast to signed int
-        }
-        int sx;
-        if (isNegativeCode(ux, S)) {
-            // Sgn(x)  == -(x / 2^S)-1
-            sx = ~((int)ux >>> S);
-        } else {
-            // Sgn(x)  == (x / 2^S)*(2^S-1) + (x % 2^S)
-            sx = (int)ux - ((int)ux >>> S);
-        }
-        // Assert special case of S==1:
-        assert(!(S == 1) || sx == (((int)ux >>> 1) ^ -((int)ux & 1)));
-        return sx;
-    }
-    private static long encodeSign32(int sx, int S) {
-        if (S == 0) {
-            return toUnsigned32(sx);  // unsigned 32-bit int
-        }
-        int Smask = (1< "+
-               Integer.toHexString(sx)+" != "+
-               Integer.toHexString(decodeSign32(ux, S)));
-        return ux;
-    }
-
-    // Top-level coding of single integers:
-    public static void writeInt(byte[] out, int[] outpos, int sx, int B, int H, int S) {
-        long ux = encodeSign32(sx, S);
-        assert(ux == toUnsigned32((int)ux));
-        assert(ux < codeRangeLong(B, H))
-            : Long.toHexString(ux);
-        int L = 256-H;
-        long sum = ux;
-        int pos = outpos[0];
-        for (int i = 0; i < B-1; i++) {
-            if (sum < L)
-                break;
-            sum -= L;
-            int b_i = (int)( L + (sum % H) );
-            sum /= H;
-            out[pos++] = (byte)b_i;
-        }
-        out[pos++] = (byte)sum;
-        // Report number of bytes written by updating outpos[0]:
-        outpos[0] = pos;
-        // Check right away for mis-coding.
-        //assert(sx == readInt(out, new int[1], B, H, S));
-    }
-    public static int readInt(byte[] in, int[] inpos, int B, int H, int S) {
-        // U(b[i]: i= 0 && sum < codeRangeLong(B, H));
-        // Report number of bytes read by updating inpos[0]:
-        inpos[0] = pos;
-        return decodeSign32(sum, S);
-    }
-    // The Stream version doesn't fetch a byte unless it is needed for coding.
-    public static int readIntFrom(InputStream in, int B, int H, int S) throws IOException {
-        // U(b[i]: i= 0 && sum < codeRangeLong(B, H));
-        return decodeSign32(sum, S);
-    }
-
-    public static final int B_MAX = 5;    /* B: [1,5] */
-    public static final int H_MAX = 256;  /* H: [1,256] */
-    public static final int S_MAX = 2;    /* S: [0,2] */
-
-    // END OF STATICS.
-
-    private final int B; /*1..5*/       // # bytes (1..5)
-    private final int H; /*1..256*/     // # codes requiring a higher byte
-    private final int L; /*0..255*/     // # codes requiring a higher byte
-    private final int S; /*0..3*/       // # low-order bits representing sign
-    private final int del; /*0..2*/     // type of delta encoding (0 == none)
-    private final int min;              // smallest representable value
-    private final int max;              // largest representable value
-    private final int umin;             // smallest representable uns. value
-    private final int umax;             // largest representable uns. value
-    private final int[] byteMin;        // smallest repr. value, given # bytes
-    private final int[] byteMax;        // largest repr. value, given # bytes
-
-    private Coding(int B, int H, int S) {
-        this(B, H, S, 0);
-    }
-    private Coding(int B, int H, int S, int del) {
-        this.B = B;
-        this.H = H;
-        this.L = 256-H;
-        this.S = S;
-        this.del = del;
-        this.min = codeMin(B, H, S, B);
-        this.max = codeMax(B, H, S, B);
-        this.umin = codeMin(B, H, 0, B);
-        this.umax = codeMax(B, H, 0, B);
-        this.byteMin = new int[B];
-        this.byteMax = new int[B];
-
-        for (int nMax = 1; nMax <= B; nMax++) {
-            byteMin[nMax-1] = codeMin(B, H, S, nMax);
-            byteMax[nMax-1] = codeMax(B, H, S, nMax);
-        }
-    }
-
-    public boolean equals(Object x) {
-        if (!(x instanceof Coding))  return false;
-        Coding that = (Coding) x;
-        if (this.B != that.B)  return false;
-        if (this.H != that.H)  return false;
-        if (this.S != that.S)  return false;
-        if (this.del != that.del)  return false;
-        return true;
-    }
-
-    public int hashCode() {
-        return (del<<14)+(S<<11)+(B<<8)+(H<<0);
-    }
-
-    private static Map codeMap;
-
-    private static synchronized Coding of(int B, int H, int S, int del) {
-        if (codeMap == null)  codeMap = new HashMap<>();
-        Coding x0 = new Coding(B, H, S, del);
-        Coding x1 = codeMap.get(x0);
-        if (x1 == null)  codeMap.put(x0, x1 = x0);
-        return x1;
-    }
-
-    public static Coding of(int B, int H) {
-        return of(B, H, 0, 0);
-    }
-
-    public static Coding of(int B, int H, int S) {
-        return of(B, H, S, 0);
-    }
-
-    public boolean canRepresentValue(int x) {
-        if (isSubrange())
-            return canRepresentUnsigned(x);
-        else
-            return canRepresentSigned(x);
-    }
-    /** Can this coding represent a single value, possibly a delta?
-     *  This ignores the D property.  That is, for delta codings,
-     *  this tests whether a delta value of 'x' can be coded.
-     *  For signed delta codings which produce unsigned end values,
-     *  use canRepresentUnsigned.
-     */
-    public boolean canRepresentSigned(int x) {
-        return (x >= min && x <= max);
-    }
-    /** Can this coding, apart from its S property,
-     *  represent a single value?  (Negative values
-     *  can only be represented via 32-bit overflow,
-     *  so this returns true for negative values
-     *  if isFullRange is true.)
-     */
-    public boolean canRepresentUnsigned(int x) {
-        return (x >= umin && x <= umax);
-    }
-
-    // object-oriented code/decode
-    public int readFrom(byte[] in, int[] inpos) {
-        return readInt(in, inpos, B, H, S);
-    }
-    public void writeTo(byte[] out, int[] outpos, int x) {
-        writeInt(out, outpos, x, B, H, S);
-    }
-
-    // Stream versions
-    public int readFrom(InputStream in) throws IOException {
-        return readIntFrom(in, B, H, S);
-    }
-    public void writeTo(OutputStream out, int x) throws IOException {
-        byte[] buf = new byte[B];
-        int[] pos = new int[1];
-        writeInt(buf, pos, x, B, H, S);
-        out.write(buf, 0, pos[0]);
-    }
-
-    // Stream/array versions
-    public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException {
-        // %%% use byte[] buffer
-        for (int i = start; i < end; i++)
-            a[i] = readFrom(in);
-
-        for (int dstep = 0; dstep < del; dstep++) {
-            long state = 0;
-            for (int i = start; i < end; i++) {
-                state += a[i];
-                // Reduce array values to the required range.
-                if (isSubrange()) {
-                    state = reduceToUnsignedRange(state);
-                }
-                a[i] = (int) state;
-            }
-        }
-    }
-    public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException {
-        if (end <= start)  return;
-        for (int dstep = 0; dstep < del; dstep++) {
-            int[] deltas;
-            if (!isSubrange())
-                deltas = makeDeltas(a, start, end, 0, 0);
-            else
-                deltas = makeDeltas(a, start, end, min, max);
-            a = deltas;
-            start = 0;
-            end = deltas.length;
-        }
-        // The following code is a buffered version of this loop:
-        //    for (int i = start; i < end; i++)
-        //        writeTo(out, a[i]);
-        byte[] buf = new byte[1<<8];
-        final int bufmax = buf.length-B;
-        int[] pos = { 0 };
-        for (int i = start; i < end; ) {
-            while (pos[0] <= bufmax) {
-                writeTo(buf, pos, a[i++]);
-                if (i >= end)  break;
-            }
-            out.write(buf, 0, pos[0]);
-            pos[0] = 0;
-        }
-    }
-
-    /** Tell if the range of this coding (number of distinct
-     *  representable values) can be expressed in 32 bits.
-     */
-    boolean isSubrange() {
-        return max < Integer.MAX_VALUE
-            && ((long)max - (long)min + 1) <= Integer.MAX_VALUE;
-    }
-
-    /** Tell if this coding can represent all 32-bit values.
-     *  Note:  Some codings, such as unsigned ones, can be neither
-     *  subranges nor full-range codings.
-     */
-    boolean isFullRange() {
-        return max == Integer.MAX_VALUE && min == Integer.MIN_VALUE;
-    }
-
-    /** Return the number of values this coding (a subrange) can represent. */
-    int getRange() {
-        assert(isSubrange());
-        return (max - min) + 1;  // range includes both min & max
-    }
-
-    Coding setB(int B) { return Coding.of(B, H, S, del); }
-    Coding setH(int H) { return Coding.of(B, H, S, del); }
-    Coding setS(int S) { return Coding.of(B, H, S, del); }
-    Coding setL(int L) { return setH(256-L); }
-    Coding setD(int del) { return Coding.of(B, H, S, del); }
-    Coding getDeltaCoding() { return setD(del+1); }
-
-    /** Return a coding suitable for representing summed, modulo-reduced values. */
-    Coding getValueCoding() {
-        if (isDelta())
-            return Coding.of(B, H, 0, del-1);
-        else
-            return this;
-    }
-
-    /** Reduce the given value to be within this coding's unsigned range,
-     *  by adding or subtracting a multiple of (max-min+1).
-     */
-    int reduceToUnsignedRange(long value) {
-        if (value == (int)value && canRepresentUnsigned((int)value))
-            // already in unsigned range
-            return (int)value;
-        int range = getRange();
-        assert(range > 0);
-        value %= range;
-        if (value < 0)  value += range;
-        assert(canRepresentUnsigned((int)value));
-        return (int)value;
-    }
-
-    int reduceToSignedRange(int value) {
-        if (canRepresentSigned(value))
-            // already in signed range
-            return value;
-        return reduceToSignedRange(value, min, max);
-    }
-    static int reduceToSignedRange(int value, int min, int max) {
-        int range = (max-min+1);
-        assert(range > 0);
-        int value0 = value;
-        value -= min;
-        if (value < 0 && value0 >= 0) {
-            // 32-bit overflow, but the next '%=' op needs to be unsigned
-            value -= range;
-            assert(value >= 0);
-        }
-        value %= range;
-        if (value < 0)  value += range;
-        value += min;
-        assert(min <= value && value <= max);
-        return value;
-    }
-
-    /** Does this coding support at least one negative value?
-        Includes codings that can do so via 32-bit wraparound.
-     */
-    boolean isSigned() {
-        return min < 0;
-    }
-    /** Does this coding code arrays by making successive differences? */
-    boolean isDelta() {
-        return del != 0;
-    }
-
-    public int B() { return B; }
-    public int H() { return H; }
-    public int L() { return L; }
-    public int S() { return S; }
-    public int del() { return del; }
-    public int min() { return min; }
-    public int max() { return max; }
-    public int umin() { return umin; }
-    public int umax() { return umax; }
-    public int byteMin(int b) { return byteMin[b-1]; }
-    public int byteMax(int b) { return byteMax[b-1]; }
-
-    public int compareTo(Coding that) {
-        int dkey = this.del - that.del;
-        if (dkey == 0)
-            dkey = this.B - that.B;
-        if (dkey == 0)
-            dkey = this.H - that.H;
-        if (dkey == 0)
-            dkey = this.S - that.S;
-        return dkey;
-    }
-
-    /** Heuristic measure of the difference between two codings. */
-    public int distanceFrom(Coding that) {
-        int diffdel = this.del - that.del;
-        if (diffdel < 0)  diffdel = -diffdel;
-        int diffS = this.S - that.S;
-        if (diffS < 0)  diffS = -diffS;
-        int diffB = this.B - that.B;
-        if (diffB < 0)  diffB = -diffB;
-        int diffHL;
-        if (this.H == that.H) {
-            diffHL = 0;
-        } else {
-            // Distance in log space of H (<=128) and L (<128).
-            int thisHL = this.getHL();
-            int thatHL = that.getHL();
-            // Double the accuracy of the log:
-            thisHL *= thisHL;
-            thatHL *= thatHL;
-            if (thisHL > thatHL)
-                diffHL = ceil_lg2(1+(thisHL-1)/thatHL);
-            else
-                diffHL = ceil_lg2(1+(thatHL-1)/thisHL);
-        }
-        int norm = 5*(diffdel + diffS + diffB) + diffHL;
-        assert(norm != 0 || this.compareTo(that) == 0);
-        return norm;
-    }
-    private int getHL() {
-        // Follow H in log space by the multiplicative inverse of L.
-        if (H <= 128)  return H;
-        if (L >= 1)    return 128*128/L;
-        return 128*256;
-    }
-
-    /** ceiling(log[2](x)): {1->0, 2->1, 3->2, 4->2, ...} */
-    static int ceil_lg2(int x) {
-        assert(x-1 >= 0);  // x in range (int.MIN_VALUE -> 32)
-        x -= 1;
-        int lg = 0;
-        while (x != 0) {
-            lg++;
-            x >>= 1;
-        }
-        return lg;
-    }
-
-    private static final byte[] byteBitWidths = new byte[0x100];
-    static {
-        for (int b = 0; b < byteBitWidths.length; b++) {
-            byteBitWidths[b] = (byte) ceil_lg2(b + 1);
-        }
-        for (int i = 10; i >= 0; i = (i << 1) - (i >> 3)) {
-            assert(bitWidth(i) == ceil_lg2(i + 1));
-        }
-    }
-
-    /** Number of significant bits in i, not counting sign bits.
-     *  For positive i, it is ceil_lg2(i + 1).
-     */
-    static int bitWidth(int i) {
-        if (i < 0)  i = ~i;  // change sign
-        int w = 0;
-        int lo = i;
-        if (lo < byteBitWidths.length)
-            return byteBitWidths[lo];
-        int hi;
-        hi = (lo >>> 16);
-        if (hi != 0) {
-            lo = hi;
-            w += 16;
-        }
-        hi = (lo >>> 8);
-        if (hi != 0) {
-            lo = hi;
-            w += 8;
-        }
-        w += byteBitWidths[lo];
-        //assert(w == ceil_lg2(i + 1));
-        return w;
-    }
-
-    /** Create an array of successive differences.
-     *  If min==max, accept any and all 32-bit overflow.
-     *  Otherwise, avoid 32-bit overflow, and reduce all differences
-     *  to a value in the given range, by adding or subtracting
-     *  multiples of the range cardinality (max-min+1).
-     *  Also, the values are assumed to be in the range [0..(max-min)].
-     */
-    static int[] makeDeltas(int[] values, int start, int end,
-                            int min, int max) {
-        assert(max >= min);
-        int count = end-start;
-        int[] deltas = new int[count];
-        int state = 0;
-        if (min == max) {
-            for (int i = 0; i < count; i++) {
-                int value = values[start+i];
-                deltas[i] = value - state;
-                state = value;
-            }
-        } else {
-            for (int i = 0; i < count; i++) {
-                int value = values[start+i];
-                assert(value >= 0 && value+min <= max);
-                int delta = value - state;
-                assert(delta == (long)value - (long)state); // no overflow
-                state = value;
-                // Reduce delta values to the required range.
-                delta = reduceToSignedRange(delta, min, max);
-                deltas[i] = delta;
-            }
-        }
-        return deltas;
-    }
-
-    boolean canRepresent(int minValue, int maxValue) {
-        assert(minValue <= maxValue);
-        if (del > 0) {
-            if (isSubrange()) {
-                // We will force the values to reduce to the right subrange.
-                return canRepresentUnsigned(maxValue)
-                    && canRepresentUnsigned(minValue);
-            } else {
-                // Huge range; delta values must assume full 32-bit range.
-                return isFullRange();
-            }
-        }
-        else
-            // final values must be representable
-            return canRepresentSigned(maxValue)
-                && canRepresentSigned(minValue);
-    }
-
-    boolean canRepresent(int[] values, int start, int end) {
-        int len = end-start;
-        if (len == 0)       return true;
-        if (isFullRange())  return true;
-        // Calculate max, min:
-        int lmax = values[start];
-        int lmin = lmax;
-        for (int i = 1; i < len; i++) {
-            int value = values[start+i];
-            if (lmax < value)  lmax = value;
-            if (lmin > value)  lmin = value;
-        }
-        return canRepresent(lmin, lmax);
-    }
-
-    public double getBitLength(int value) {  // implements BitMetric
-        return (double) getLength(value) * 8;
-    }
-
-    /** How many bytes are in the coding of this value?
-     *  Returns Integer.MAX_VALUE if the value has no coding.
-     *  The coding must not be a delta coding, since there is no
-     *  definite size for a single value apart from its context.
-     */
-    public int getLength(int value) {
-        if (isDelta() && isSubrange()) {
-            if (!canRepresentUnsigned(value))
-                return Integer.MAX_VALUE;
-            value = reduceToSignedRange(value);
-        }
-        if (value >= 0) {
-            for (int n = 0; n < B; n++) {
-                if (value <= byteMax[n])  return n+1;
-            }
-        } else {
-            for (int n = 0; n < B; n++) {
-                if (value >= byteMin[n])  return n+1;
-            }
-        }
-        return Integer.MAX_VALUE;
-    }
-
-    public int getLength(int[] values, int start, int end) {
-        int len = end-start;
-        if (B == 1)  return len;
-        if (L == 0)  return len * B;
-        if (isDelta()) {
-            int[] deltas;
-            if (!isSubrange())
-                deltas = makeDeltas(values, start, end, 0, 0);
-            else
-                deltas = makeDeltas(values, start, end, min, max);
-            //return Coding.of(B, H, S).getLength(deltas, 0, len);
-            values = deltas;
-            start = 0;
-        }
-        int sum = len;  // at least 1 byte per
-        // add extra bytes for extra-long values
-        for (int n = 1; n <= B; n++) {
-            // what is the coding interval [min..max] for n bytes?
-            int lmax = byteMax[n-1];
-            int lmin = byteMin[n-1];
-            int longer = 0;  // count of guys longer than n bytes
-            for (int i = 0; i < len; i++) {
-                int value = values[start+i];
-                if (value >= 0) {
-                    if (value > lmax)  longer++;
-                } else {
-                    if (value < lmin)  longer++;
-                }
-            }
-            if (longer == 0)  break;  // no more passes needed
-            if (n == B)  return Integer.MAX_VALUE;  // cannot represent!
-            sum += longer;
-        }
-        return sum;
-    }
-
-    public byte[] getMetaCoding(Coding dflt) {
-        if (dflt == this)  return new byte[]{ (byte) _meta_default };
-        int canonicalIndex = BandStructure.indexOf(this);
-        if (canonicalIndex > 0)
-            return new byte[]{ (byte) canonicalIndex };
-        return new byte[]{
-            (byte)_meta_arb,
-            (byte)(del + 2*S + 8*(B-1)),
-            (byte)(H-1)
-        };
-    }
-    public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod res[]) {
-        int op = bytes[pos++] & 0xFF;
-        if (_meta_canon_min <= op && op <= _meta_canon_max) {
-            Coding c = BandStructure.codingForIndex(op);
-            assert(c != null);
-            res[0] = c;
-            return pos;
-        }
-        if (op == _meta_arb) {
-            int dsb = bytes[pos++] & 0xFF;
-            int H_1 = bytes[pos++] & 0xFF;
-            int del = dsb % 2;
-            int S = (dsb / 2) % 4;
-            int B = (dsb / 8)+1;
-            int H = H_1+1;
-            if (!((1 <= B && B <= B_MAX) &&
-                  (0 <= S && S <= S_MAX) &&
-                  (1 <= H && H <= H_MAX) &&
-                  (0 <= del && del <= 1))
-                || (B == 1 && H != 256)
-                || (B == 5 && H == 256)) {
-                throw new RuntimeException("Bad arb. coding: ("+B+","+H+","+S+","+del);
-            }
-            res[0] = Coding.of(B, H, S, del);
-            return pos;
-        }
-        return pos-1;  // backup
-    }
-
-
-    public String keyString() {
-        return "("+B+","+H+","+S+","+del+")";
-    }
-
-    public String toString() {
-        String str = "Coding"+keyString();
-        // If -ea, print out more informative strings!
-        //assert((str = stringForDebug()) != null);
-        return str;
-    }
-
-    static boolean verboseStringForDebug = false;
-    String stringForDebug() {
-        String minS = (min == Integer.MIN_VALUE ? "min" : ""+min);
-        String maxS = (max == Integer.MAX_VALUE ? "max" : ""+max);
-        String str = keyString()+" L="+L+" r=["+minS+","+maxS+"]";
-        if (isSubrange())
-            str += " subrange";
-        else if (!isFullRange())
-            str += " MIDRANGE";
-        if (verboseStringForDebug) {
-            str += " {";
-            int prev_range = 0;
-            for (int n = 1; n <= B; n++) {
-                int range_n = saturate32((long)byteMax[n-1] - byteMin[n-1] + 1);
-                assert(range_n == saturate32(codeRangeLong(B, H, n)));
-                range_n -= prev_range;
-                prev_range = range_n;
-                String rngS = (range_n == Integer.MAX_VALUE ? "max" : ""+range_n);
-                str += " #"+n+"="+rngS;
-            }
-            str += " }";
-        }
-        return str;
-    }
-}
diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java
deleted file mode 100644
index 4cc1d0898ed..00000000000
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingChooser.java
+++ /dev/null
@@ -1,1489 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.java.util.jar.pack;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import static com.sun.java.util.jar.pack.Constants.*;
-/**
- * Heuristic chooser of basic encodings.
- * Runs "zip" to measure the apparent information content after coding.
- * @author John Rose
- */
-class CodingChooser {
-    int verbose;
-    int effort;
-    boolean optUseHistogram = true;
-    boolean optUsePopulationCoding = true;
-    boolean optUseAdaptiveCoding = true;
-    boolean disablePopCoding;
-    boolean disableRunCoding;
-    boolean topLevel = true;
-
-    // Derived from effort; >1 (<1) means try more (less) experiments
-    // when looking to beat a best score.
-    double fuzz;
-
-    Coding[] allCodingChoices;
-    Choice[] choices;
-    ByteArrayOutputStream context;
-    CodingChooser popHelper;
-    CodingChooser runHelper;
-
-    Random stress;  // If not null, stress mode oracle.
-
-    // Element in sorted set of coding choices:
-    static
-    class Choice {
-        final Coding coding;
-        final int index;       // index in choices
-        final int[] distance;  // cache of distance
-        Choice(Coding coding, int index, int[] distance) {
-            this.coding   = coding;
-            this.index    = index;
-            this.distance = distance;
-        }
-        // These variables are reset and reused:
-        int searchOrder; // order in which it is checked
-        int minDistance; // min distance from already-checked choices
-        int zipSize;     // size of encoding in sample, zipped output
-        int byteSize;    // size of encoding in sample (debug only)
-        int histSize;    // size of encoding, according to histogram
-
-        void reset() {
-            searchOrder = Integer.MAX_VALUE;
-            minDistance = Integer.MAX_VALUE;
-            zipSize = byteSize = histSize = -1;
-        }
-
-        boolean isExtra() {
-            return index < 0;
-        }
-
-        public String toString() {
-            return stringForDebug();
-        }
-
-        private String stringForDebug() {
-            String s = "";
-            if (searchOrder < Integer.MAX_VALUE)
-                s += " so: "+searchOrder;
-            if (minDistance < Integer.MAX_VALUE)
-                s += " md: "+minDistance;
-            if (zipSize > 0)
-                s += " zs: "+zipSize;
-            if (byteSize > 0)
-                s += " bs: "+byteSize;
-            if (histSize > 0)
-                s += " hs: "+histSize;
-            return "Choice["+index+"] "+s+" "+coding;
-        }
-    }
-
-    CodingChooser(int effort, Coding[] allCodingChoices) {
-        PropMap p200 = Utils.currentPropMap();
-        if (p200 != null) {
-            this.verbose
-                = Math.max(p200.getInteger(Utils.DEBUG_VERBOSE),
-                           p200.getInteger(Utils.COM_PREFIX+"verbose.coding"));
-            this.optUseHistogram
-                = !p200.getBoolean(Utils.COM_PREFIX+"no.histogram");
-            this.optUsePopulationCoding
-                = !p200.getBoolean(Utils.COM_PREFIX+"no.population.coding");
-            this.optUseAdaptiveCoding
-                = !p200.getBoolean(Utils.COM_PREFIX+"no.adaptive.coding");
-            int lstress
-                = p200.getInteger(Utils.COM_PREFIX+"stress.coding");
-            if (lstress != 0)
-                this.stress = new Random(lstress);
-        }
-
-        this.effort = effort;
-        // The following line "makes sense" but is too much
-        // work for a simple heuristic.
-        //if (effort > 5)  zipDef.setLevel(effort);
-
-        this.allCodingChoices = allCodingChoices;
-
-        // If effort = 9, look carefully at any solution
-        // whose initial metrics are within 1% of the best
-        // so far.  If effort = 1, look carefully only at
-        // solutions whose initial metrics promise a 1% win.
-        this.fuzz = 1 + (0.0025 * (effort-MID_EFFORT));
-
-        int nc = 0;
-        for (int i = 0; i < allCodingChoices.length; i++) {
-            if (allCodingChoices[i] == null)  continue;
-            nc++;
-        }
-        choices = new Choice[nc];
-        nc = 0;
-        for (int i = 0; i < allCodingChoices.length; i++) {
-            if (allCodingChoices[i] == null)  continue;
-            int[] distance = new int[choices.length];
-            choices[nc++] = new Choice(allCodingChoices[i], i, distance);
-        }
-        for (int i = 0; i < choices.length; i++) {
-            Coding ci = choices[i].coding;
-            assert(ci.distanceFrom(ci) == 0);
-            for (int j = 0; j < i; j++) {
-                Coding cj = choices[j].coding;
-                int dij = ci.distanceFrom(cj);
-                assert(dij > 0);
-                assert(dij == cj.distanceFrom(ci));
-                choices[i].distance[j] = dij;
-                choices[j].distance[i] = dij;
-            }
-        }
-    }
-
-    Choice makeExtraChoice(Coding coding) {
-        int[] distance = new int[choices.length];
-        for (int i = 0; i < distance.length; i++) {
-            Coding ci = choices[i].coding;
-            int dij = coding.distanceFrom(ci);
-            assert(dij > 0);
-            assert(dij == ci.distanceFrom(coding));
-            distance[i] = dij;
-        }
-        Choice c = new Choice(coding, -1, distance);
-        c.reset();
-        return c;
-    }
-
-    ByteArrayOutputStream getContext() {
-        if (context == null)
-            context = new ByteArrayOutputStream(1 << 16);
-        return context;
-    }
-
-    // These variables are reset and reused:
-    private int[] values;
-    private int start, end;  // slice of values
-    private int[] deltas;
-    private int min, max;
-    private Histogram vHist;
-    private Histogram dHist;
-    private int searchOrder;
-    private Choice regularChoice;
-    private Choice bestChoice;
-    private CodingMethod bestMethod;
-    private int bestByteSize;
-    private int bestZipSize;
-    private int targetSize;   // fuzzed target byte size
-
-    private void reset(int[] values, int start, int end) {
-        this.values = values;
-        this.start = start;
-        this.end = end;
-        this.deltas = null;
-        this.min = Integer.MAX_VALUE;
-        this.max = Integer.MIN_VALUE;
-        this.vHist = null;
-        this.dHist = null;
-        this.searchOrder = 0;
-        this.regularChoice = null;
-        this.bestChoice = null;
-        this.bestMethod = null;
-        this.bestZipSize = Integer.MAX_VALUE;
-        this.bestByteSize = Integer.MAX_VALUE;
-        this.targetSize = Integer.MAX_VALUE;
-    }
-
-    public static final int MIN_EFFORT = 1;
-    public static final int MID_EFFORT = 5;
-    public static final int MAX_EFFORT = 9;
-
-    public static final int POP_EFFORT = MID_EFFORT-1;
-    public static final int RUN_EFFORT = MID_EFFORT-2;
-
-    public static final int BYTE_SIZE = 0;
-    public static final int ZIP_SIZE = 1;
-
-    CodingMethod choose(int[] values, int start, int end, Coding regular, int[] sizes) {
-        // Save the value array
-        reset(values, start, end);
-
-        if (effort <= MIN_EFFORT || start >= end) {
-            if (sizes != null) {
-                int[] computed = computeSizePrivate(regular);
-                sizes[BYTE_SIZE] = computed[BYTE_SIZE];
-                sizes[ZIP_SIZE]  = computed[ZIP_SIZE];
-            }
-            return regular;
-        }
-
-        if (optUseHistogram) {
-            getValueHistogram();
-            getDeltaHistogram();
-        }
-
-        for (int i = start; i < end; i++) {
-            int val = values[i];
-            if (min > val)  min = val;
-            if (max < val)  max = val;
-        }
-
-        // Find all the preset choices that might be worth looking at:
-        int numChoices = markUsableChoices(regular);
-
-        if (stress != null) {
-            // Make a random choice.
-            int rand = stress.nextInt(numChoices*2 + 4);
-            CodingMethod coding = null;
-            for (int i = 0; i < choices.length; i++) {
-                Choice c = choices[i];
-                if (c.searchOrder >= 0 && rand-- == 0) {
-                    coding = c.coding;
-                    break;
-                }
-            }
-            if (coding == null) {
-                if ((rand & 7) != 0) {
-                    coding = regular;
-                } else {
-                    // Pick a totally random coding 6% of the time.
-                    coding = stressCoding(min, max);
-                }
-            }
-            if (!disablePopCoding
-                && optUsePopulationCoding
-                && effort >= POP_EFFORT) {
-                coding = stressPopCoding(coding);
-            }
-            if (!disableRunCoding
-                && optUseAdaptiveCoding
-                && effort >= RUN_EFFORT) {
-                coding = stressAdaptiveCoding(coding);
-            }
-            return coding;
-        }
-
-        double searchScale = 1.0;
-        for (int x = effort; x < MAX_EFFORT; x++) {
-            searchScale /= 1.414;  // every 2 effort points doubles work
-        }
-        int searchOrderLimit = (int)Math.ceil( numChoices * searchScale );
-
-        // Start by evaluating the "regular" choice.
-        bestChoice = regularChoice;
-        evaluate(regularChoice);
-        int maxd = updateDistances(regularChoice);
-
-        // save these first-cut numbers for later
-        int zipSize1 = bestZipSize;
-        int byteSize1 = bestByteSize;
-
-        if (regularChoice.coding == regular && topLevel) {
-            // Give credit for being the default; no band header is needed.
-            // Rather than increasing every other size value by the band
-            // header amount, we decrement this one metric, to give it an edge.
-            // Decreasing zipSize by a byte length is conservatively correct,
-            // especially considering that the escape byte is not likely to
-            // zip well with other bytes in the band.
-            int X = BandStructure.encodeEscapeValue(_meta_canon_max, regular);
-            if (regular.canRepresentSigned(X)) {
-                int Xlen = regular.getLength(X);  // band coding header
-                //regularChoice.histSize -= Xlen; // keep exact byteSize
-                //regularChoice.byteSize -= Xlen; // keep exact byteSize
-                regularChoice.zipSize -= Xlen;
-                bestByteSize = regularChoice.byteSize;
-                bestZipSize = regularChoice.zipSize;
-            }
-        }
-
-        int dscale = 1;
-        // Continually select a new choice to evaluate.
-        while (searchOrder < searchOrderLimit) {
-            Choice nextChoice;
-            if (dscale > maxd)  dscale = 1;  // cycle dscale values!
-            int dhi = maxd / dscale;
-            int dlo = maxd / (dscale *= 2) + 1;
-            nextChoice = findChoiceNear(bestChoice, dhi, dlo);
-            if (nextChoice == null)  continue;
-            assert(nextChoice.coding.canRepresent(min, max));
-            evaluate(nextChoice);
-            int nextMaxd = updateDistances(nextChoice);
-            if (nextChoice == bestChoice) {
-                maxd = nextMaxd;
-                if (verbose > 5)  Utils.log.info("maxd = "+maxd);
-            }
-        }
-
-        // Record best "plain coding" choice.
-        Coding plainBest = bestChoice.coding;
-        assert(plainBest == bestMethod);
-
-        if (verbose > 2) {
-            Utils.log.info("chooser: plain result="+bestChoice+" after "+bestChoice.searchOrder+" rounds, "+(regularChoice.zipSize-bestZipSize)+" fewer bytes than regular "+regular);
-        }
-        bestChoice = null;
-
-        if (!disablePopCoding
-            && optUsePopulationCoding
-            && effort >= POP_EFFORT
-            && bestMethod instanceof Coding) {
-            tryPopulationCoding(plainBest);
-        }
-
-        if (!disableRunCoding
-            && optUseAdaptiveCoding
-            && effort >= RUN_EFFORT
-            && bestMethod instanceof Coding) {
-            tryAdaptiveCoding(plainBest);
-        }
-
-        // Pass back the requested information:
-        if (sizes != null) {
-            sizes[BYTE_SIZE] = bestByteSize;
-            sizes[ZIP_SIZE]  = bestZipSize;
-        }
-        if (verbose > 1) {
-            Utils.log.info("chooser: result="+bestMethod+" "+
-                             (zipSize1-bestZipSize)+
-                             " fewer bytes than regular "+regular+
-                             "; win="+pct(zipSize1-bestZipSize, zipSize1));
-        }
-        CodingMethod lbestMethod = this.bestMethod;
-        reset(null, 0, 0);  // for GC
-        return lbestMethod;
-    }
-    CodingMethod choose(int[] values, int start, int end, Coding regular) {
-        return choose(values, start, end, regular, null);
-    }
-    CodingMethod choose(int[] values, Coding regular, int[] sizes) {
-        return choose(values, 0, values.length, regular, sizes);
-    }
-    CodingMethod choose(int[] values, Coding regular) {
-        return choose(values, 0, values.length, regular, null);
-    }
-
-    private int markUsableChoices(Coding regular) {
-        int numChoices = 0;
-        for (int i = 0; i < choices.length; i++) {
-            Choice c = choices[i];
-            c.reset();
-            if (!c.coding.canRepresent(min, max)) {
-                // Mark as already visited:
-                c.searchOrder = -1;
-                if (verbose > 1 && c.coding == regular) {
-                    Utils.log.info("regular coding cannot represent ["+min+".."+max+"]: "+regular);
-                }
-                continue;
-            }
-            if (c.coding == regular)
-                regularChoice = c;
-            numChoices++;
-        }
-        if (regularChoice == null && regular.canRepresent(min, max)) {
-            regularChoice = makeExtraChoice(regular);
-            if (verbose > 1) {
-                Utils.log.info("*** regular choice is extra: "+regularChoice.coding);
-            }
-        }
-        if (regularChoice == null) {
-            for (int i = 0; i < choices.length; i++) {
-                Choice c = choices[i];
-                if (c.searchOrder != -1) {
-                    regularChoice = c;  // arbitrary pick
-                    break;
-                }
-            }
-            if (verbose > 1) {
-                Utils.log.info("*** regular choice does not apply "+regular);
-                Utils.log.info("    using instead "+regularChoice.coding);
-            }
-        }
-        if (verbose > 2) {
-            Utils.log.info("chooser: #choices="+numChoices+" ["+min+".."+max+"]");
-            if (verbose > 4) {
-                for (int i = 0; i < choices.length; i++) {
-                    Choice c = choices[i];
-                    if (c.searchOrder >= 0)
-                        Utils.log.info("  "+c);
-                }
-            }
-        }
-        return numChoices;
-    }
-
-    // Find an arbitrary choice at least dlo away from a previously
-    // evaluated choices, and at most dhi.  Try also to regulate its
-    // min distance to all previously evaluated choices, in this range.
-    private Choice findChoiceNear(Choice near, int dhi, int dlo) {
-        if (verbose > 5)
-            Utils.log.info("findChoice "+dhi+".."+dlo+" near: "+near);
-        int[] distance = near.distance;
-        Choice found = null;
-        for (int i = 0; i < choices.length; i++) {
-            Choice c = choices[i];
-            if (c.searchOrder < searchOrder)
-                continue;  // already searched
-            // Distance from "near" guy must be in bounds:
-            if (distance[i] >= dlo && distance[i] <= dhi) {
-                // Try also to keep min-distance from other guys in bounds:
-                if (c.minDistance >= dlo && c.minDistance <= dhi) {
-                    if (verbose > 5)
-                        Utils.log.info("findChoice => good "+c);
-                    return c;
-                }
-                found = c;
-            }
-        }
-        if (verbose > 5)
-            Utils.log.info("findChoice => found "+found);
-        return found;
-    }
-
-    private void evaluate(Choice c) {
-        assert(c.searchOrder == Integer.MAX_VALUE);
-        c.searchOrder = searchOrder++;
-        boolean mustComputeSize;
-        if (c == bestChoice || c.isExtra()) {
-            mustComputeSize = true;
-        } else if (optUseHistogram) {
-            Histogram hist = getHistogram(c.coding.isDelta());
-            c.histSize = (int)Math.ceil(hist.getBitLength(c.coding) / 8);
-            c.byteSize = c.histSize;
-            mustComputeSize = (c.byteSize <= targetSize);
-        } else {
-            mustComputeSize = true;
-        }
-        if (mustComputeSize) {
-            int[] sizes = computeSizePrivate(c.coding);
-            c.byteSize = sizes[BYTE_SIZE];
-            c.zipSize  = sizes[ZIP_SIZE];
-            if (noteSizes(c.coding, c.byteSize, c.zipSize))
-                bestChoice = c;
-        }
-        if (c.histSize >= 0) {
-            assert(c.byteSize == c.histSize);  // models should agree
-        }
-        if (verbose > 4) {
-            Utils.log.info("evaluated "+c);
-        }
-    }
-
-    private boolean noteSizes(CodingMethod c, int byteSize, int zipSize) {
-        assert(zipSize > 0 && byteSize > 0);
-        boolean better = (zipSize < bestZipSize);
-        if (verbose > 3)
-            Utils.log.info("computed size "+c+" "+byteSize+"/zs="+zipSize+
-                             ((better && bestMethod != null)?
-                              (" better by "+
-                               pct(bestZipSize - zipSize, zipSize)): ""));
-        if (better) {
-            bestMethod = c;
-            bestZipSize = zipSize;
-            bestByteSize = byteSize;
-            targetSize = (int)(byteSize * fuzz);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-
-    private int updateDistances(Choice c) {
-        // update all minDistance values in still unevaluated choices
-        int[] distance = c.distance;
-        int maxd = 0;  // how far is c from everybody else?
-        for (int i = 0; i < choices.length; i++) {
-            Choice c2 = choices[i];
-            if (c2.searchOrder < searchOrder)
-                continue;
-            int d = distance[i];
-            if (verbose > 5)
-                Utils.log.info("evaluate dist "+d+" to "+c2);
-            int mind = c2.minDistance;
-            if (mind > d)
-                c2.minDistance = mind = d;
-            if (maxd < d)
-                maxd = d;
-        }
-        // Now maxd has the distance of the farthest outlier
-        // from all evaluated choices.
-        if (verbose > 5)
-            Utils.log.info("evaluate maxd => "+maxd);
-        return maxd;
-    }
-
-    // Compute the coded size of a sequence of values.
-    // The first int is the size in uncompressed bytes.
-    // The second is an estimate of the compressed size of these bytes.
-    public void computeSize(CodingMethod c, int[] values, int start, int end, int[] sizes) {
-        if (end <= start) {
-            sizes[BYTE_SIZE] = sizes[ZIP_SIZE] = 0;
-            return;
-        }
-        try {
-            resetData();
-            c.writeArrayTo(byteSizer, values, start, end);
-            sizes[BYTE_SIZE] = getByteSize();
-            sizes[ZIP_SIZE] = getZipSize();
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-    }
-    public void computeSize(CodingMethod c, int[] values, int[] sizes) {
-        computeSize(c, values, 0, values.length, sizes);
-    }
-    public int[] computeSize(CodingMethod c, int[] values, int start, int end) {
-        int[] sizes = { 0, 0 };
-        computeSize(c, values, start, end, sizes);
-        return sizes;
-    }
-    public int[] computeSize(CodingMethod c, int[] values) {
-        return computeSize(c, values, 0, values.length);
-    }
-    // This version uses the implicit local arguments
-    private int[] computeSizePrivate(CodingMethod c) {
-        int[] sizes = { 0, 0 };
-        computeSize(c, values, start, end, sizes);
-        return sizes;
-    }
-    public int computeByteSize(CodingMethod cm, int[] values, int start, int end) {
-        int len = end-start;
-        if (len < 0) {
-            return 0;
-        }
-        if (cm instanceof Coding) {
-            Coding c = (Coding) cm;
-            int size = c.getLength(values, start, end);
-            int size2;
-            assert(size == (size2=countBytesToSizer(cm, values, start, end)))
-                : (cm+" : "+size+" != "+size2);
-            return size;
-        }
-        return countBytesToSizer(cm, values, start, end);
-    }
-    private int countBytesToSizer(CodingMethod cm, int[] values, int start, int end) {
-        try {
-            byteOnlySizer.reset();
-            cm.writeArrayTo(byteOnlySizer, values, start, end);
-            return byteOnlySizer.getSize();
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-    }
-
-    int[] getDeltas(int min, int max) {
-        if ((min|max) != 0)
-            return Coding.makeDeltas(values, start, end, min, max);
-        if (deltas == null) {
-            deltas = Coding.makeDeltas(values, start, end, 0, 0);
-        }
-        return deltas;
-    }
-    Histogram getValueHistogram() {
-        if (vHist == null) {
-            vHist = new Histogram(values, start, end);
-            if (verbose > 3) {
-                vHist.print("vHist", System.out);
-            } else if (verbose > 1) {
-                vHist.print("vHist", null, System.out);
-            }
-        }
-        return vHist;
-    }
-    Histogram getDeltaHistogram() {
-        if (dHist == null) {
-            dHist = new Histogram(getDeltas(0, 0));
-            if (verbose > 3) {
-                dHist.print("dHist", System.out);
-            } else if (verbose > 1) {
-                dHist.print("dHist", null, System.out);
-            }
-        }
-        return dHist;
-    }
-    Histogram getHistogram(boolean isDelta) {
-        return isDelta ? getDeltaHistogram(): getValueHistogram();
-    }
-
-    private void tryPopulationCoding(Coding plainCoding) {
-        // assert(plainCoding.canRepresent(min, max));
-        Histogram hist = getValueHistogram();
-        // Start with "reasonable" default codings.
-        final int approxL = 64;
-        Coding favoredCoding = plainCoding.getValueCoding();
-        Coding tokenCoding = BandStructure.UNSIGNED5.setL(approxL);
-        Coding unfavoredCoding = plainCoding.getValueCoding();
-        // There's going to be a band header.  Estimate conservatively large.
-        final int BAND_HEADER = 4;
-        // Keep a running model of the predicted sizes of the F/T/U sequences.
-        int currentFSize;
-        int currentTSize;
-        int currentUSize;
-        // Start by assuming a degenerate favored-value length of 0,
-        // which looks like a bunch of zero tokens followed by the
-        // original sequence.
-        // The {F} list ends with a repeated F value; find worst case:
-        currentFSize =
-            BAND_HEADER + Math.max(favoredCoding.getLength(min),
-                                   favoredCoding.getLength(max));
-        // The {T} list starts out a bunch of zeros, each of length 1.
-        final int ZERO_LEN = tokenCoding.getLength(0);
-        currentTSize = ZERO_LEN * (end-start);
-        // The {U} list starts out a copy of the plainCoding:
-        currentUSize = (int) Math.ceil(hist.getBitLength(unfavoredCoding) / 8);
-
-        int bestPopSize = (currentFSize + currentTSize + currentUSize);
-        int bestPopFVC  = 0;
-
-        // Record all the values, in decreasing order of favor.
-        int[] allFavoredValues = new int[1+hist.getTotalLength()];
-        //int[] allPopSizes    = new int[1+hist.getTotalLength()];
-
-        // What sizes are "interesting"?
-        int targetLowFVC = -1;
-        int targetHighFVC = -1;
-
-        // For each length, adjust the currentXSize model, and look for a win.
-        int[][] matrix = hist.getMatrix();
-        int mrow = -1;
-        int mcol = 1;
-        int mrowFreq = 0;
-        for (int fvcount = 1; fvcount <= hist.getTotalLength(); fvcount++) {
-            // The {F} list gets an additional member.
-            // Take it from the end of the current matrix row.
-            // (It's the end, so that we get larger favored values first.)
-            if (mcol == 1) {
-                mrow += 1;
-                mrowFreq = matrix[mrow][0];
-                mcol = matrix[mrow].length;
-            }
-            int thisValue = matrix[mrow][--mcol];
-            allFavoredValues[fvcount] = thisValue;
-            int thisVLen = favoredCoding.getLength(thisValue);
-            currentFSize += thisVLen;
-            // The token list replaces occurrences of zero with a new token:
-            int thisVCount = mrowFreq;
-            int thisToken = fvcount;
-            currentTSize += (tokenCoding.getLength(thisToken)
-                             - ZERO_LEN) * thisVCount;
-            // The unfavored list loses occurrences of the newly favored value.
-            // (This is the whole point of the exercise!)
-            currentUSize -= thisVLen * thisVCount;
-            int currentSize = (currentFSize + currentTSize + currentUSize);
-            //allPopSizes[fvcount] = currentSize;
-            if (bestPopSize > currentSize) {
-                if (currentSize <= targetSize) {
-                    targetHighFVC = fvcount;
-                    if (targetLowFVC < 0)
-                        targetLowFVC = fvcount;
-                    if (verbose > 4)
-                        Utils.log.info("better pop-size at fvc="+fvcount+
-                                         " by "+pct(bestPopSize-currentSize,
-                                                    bestPopSize));
-                }
-                bestPopSize = currentSize;
-                bestPopFVC = fvcount;
-            }
-        }
-        if (targetLowFVC < 0) {
-            if (verbose > 1) {
-                // Complete loss.
-                if (verbose > 1)
-                    Utils.log.info("no good pop-size; best was "+
-                                     bestPopSize+" at "+bestPopFVC+
-                                     " worse by "+
-                                     pct(bestPopSize-bestByteSize,
-                                         bestByteSize));
-            }
-            return;
-        }
-        if (verbose > 1)
-            Utils.log.info("initial best pop-size at fvc="+bestPopFVC+
-                             " in ["+targetLowFVC+".."+targetHighFVC+"]"+
-                             " by "+pct(bestByteSize-bestPopSize,
-                                        bestByteSize));
-        int oldZipSize = bestZipSize;
-        // Now close onto a specific coding, testing more rigorously
-        // with the zipSize metric.
-        // Questions to decide:
-        //   1. How many favored values?
-        //   2. What token coding (TC)?
-        //   3. Sort favored values by value within length brackets?
-        //   4. What favored coding?
-        //   5. What unfavored coding?
-        // Steps 1/2/3 are interdependent, and may be iterated.
-        // Steps 4 and 5 may be decided independently afterward.
-        int[] LValuesCoded = PopulationCoding.LValuesCoded;
-        List bestFits = new ArrayList<>();
-        List fullFits = new ArrayList<>();
-        List longFits = new ArrayList<>();
-        final int PACK_TO_MAX_S = 1;
-        if (bestPopFVC <= 255) {
-            bestFits.add(BandStructure.BYTE1);
-        } else {
-            int bestB = Coding.B_MAX;
-            boolean doFullAlso = (effort > POP_EFFORT);
-            if (doFullAlso)
-                fullFits.add(BandStructure.BYTE1.setS(PACK_TO_MAX_S));
-            for (int i = LValuesCoded.length-1; i >= 1; i--) {
-                int L = LValuesCoded[i];
-                Coding c0 = PopulationCoding.fitTokenCoding(targetLowFVC,  L);
-                Coding c1 = PopulationCoding.fitTokenCoding(bestPopFVC,    L);
-                Coding c3 = PopulationCoding.fitTokenCoding(targetHighFVC, L);
-                if (c1 != null) {
-                    if (!bestFits.contains(c1))
-                        bestFits.add(c1);
-                    if (bestB > c1.B())
-                        bestB = c1.B();
-                }
-                if (doFullAlso) {
-                    if (c3 == null)  c3 = c1;
-                    for (int B = c0.B(); B <= c3.B(); B++) {
-                        if (B == c1.B())  continue;
-                        if (B == 1)  continue;
-                        Coding c2 = c3.setB(B).setS(PACK_TO_MAX_S);
-                        if (!fullFits.contains(c2))
-                            fullFits.add(c2);
-                    }
-                }
-            }
-            // interleave all B greater than bestB with best and full fits
-            for (Iterator i = bestFits.iterator(); i.hasNext(); ) {
-                Coding c = i.next();
-                if (c.B() > bestB) {
-                    i.remove();
-                    longFits.add(0, c);
-                }
-            }
-        }
-        List allFits = new ArrayList<>();
-        for (Iterator i = bestFits.iterator(),
-                      j = fullFits.iterator(),
-                      k = longFits.iterator();
-             i.hasNext() || j.hasNext() || k.hasNext(); ) {
-            if (i.hasNext())  allFits.add(i.next());
-            if (j.hasNext())  allFits.add(j.next());
-            if (k.hasNext())  allFits.add(k.next());
-        }
-        bestFits.clear();
-        fullFits.clear();
-        longFits.clear();
-        int maxFits = allFits.size();
-        if (effort == POP_EFFORT)
-            maxFits = 2;
-        else if (maxFits > 4) {
-            maxFits -= 4;
-            maxFits = (maxFits * (effort-POP_EFFORT)
-                       ) / (MAX_EFFORT-POP_EFFORT);
-            maxFits += 4;
-        }
-        if (allFits.size() > maxFits) {
-            if (verbose > 4)
-                Utils.log.info("allFits before clip: "+allFits);
-            allFits.subList(maxFits, allFits.size()).clear();
-        }
-        if (verbose > 3)
-            Utils.log.info("allFits: "+allFits);
-        for (Coding tc : allFits) {
-            boolean packToMax = false;
-            if (tc.S() == PACK_TO_MAX_S) {
-                // Kludge:  setS(PACK_TO_MAX_S) means packToMax here.
-                packToMax = true;
-                tc = tc.setS(0);
-            }
-            int fVlen;
-            if (!packToMax) {
-                fVlen = bestPopFVC;
-                assert(tc.umax() >= fVlen);
-                assert(tc.B() == 1 || tc.setB(tc.B()-1).umax() < fVlen);
-            } else {
-                fVlen = Math.min(tc.umax(), targetHighFVC);
-                if (fVlen < targetLowFVC)
-                    continue;
-                if (fVlen == bestPopFVC)
-                    continue;  // redundant test
-            }
-            PopulationCoding pop = new PopulationCoding();
-            pop.setHistogram(hist);
-            pop.setL(tc.L());
-            pop.setFavoredValues(allFavoredValues, fVlen);
-            assert(pop.tokenCoding == tc);  // predict correctly
-            pop.resortFavoredValues();
-            int[] tcsizes =
-                computePopSizePrivate(pop,
-                                      favoredCoding, unfavoredCoding);
-            noteSizes(pop, tcsizes[BYTE_SIZE], BAND_HEADER+tcsizes[ZIP_SIZE]);
-        }
-        if (verbose > 3) {
-            Utils.log.info("measured best pop, size="+bestByteSize+
-                             "/zs="+bestZipSize+
-                             " better by "+
-                             pct(oldZipSize-bestZipSize, oldZipSize));
-            if (bestZipSize < oldZipSize) {
-                Utils.log.info(">>> POP WINS BY "+
-                                 (oldZipSize - bestZipSize));
-            }
-        }
-    }
-
-    private
-    int[] computePopSizePrivate(PopulationCoding pop,
-                                Coding favoredCoding,
-                                Coding unfavoredCoding) {
-        if (popHelper == null) {
-            popHelper = new CodingChooser(effort, allCodingChoices);
-            if (stress != null)
-                popHelper.addStressSeed(stress.nextInt());
-            popHelper.topLevel = false;
-            popHelper.verbose -= 1;
-            popHelper.disablePopCoding = true;
-            popHelper.disableRunCoding = this.disableRunCoding;
-            if (effort < MID_EFFORT)
-                // No nested run codings.
-                popHelper.disableRunCoding = true;
-        }
-        int fVlen = pop.fVlen;
-        if (verbose > 2) {
-            Utils.log.info("computePopSizePrivate fvlen="+fVlen+
-                             " tc="+pop.tokenCoding);
-            Utils.log.info("{ //BEGIN");
-        }
-
-        // Find good coding choices for the token and unfavored sequences.
-        int[] favoredValues = pop.fValues;
-        int[][] vals = pop.encodeValues(values, start, end);
-        int[] tokens = vals[0];
-        int[] unfavoredValues = vals[1];
-        if (verbose > 2)
-            Utils.log.info("-- refine on fv["+fVlen+"] fc="+favoredCoding);
-        pop.setFavoredCoding(popHelper.choose(favoredValues, 1, 1+fVlen, favoredCoding));
-        if (pop.tokenCoding instanceof Coding &&
-            (stress == null || stress.nextBoolean())) {
-            if (verbose > 2)
-                Utils.log.info("-- refine on tv["+tokens.length+"] tc="+pop.tokenCoding);
-            CodingMethod tc = popHelper.choose(tokens, (Coding) pop.tokenCoding);
-            if (tc != pop.tokenCoding) {
-                if (verbose > 2)
-                    Utils.log.info(">>> refined tc="+tc);
-                pop.setTokenCoding(tc);
-            }
-        }
-        if (unfavoredValues.length == 0)
-            pop.setUnfavoredCoding(null);
-        else {
-            if (verbose > 2)
-                Utils.log.info("-- refine on uv["+unfavoredValues.length+"] uc="+pop.unfavoredCoding);
-            pop.setUnfavoredCoding(popHelper.choose(unfavoredValues, unfavoredCoding));
-        }
-        if (verbose > 3) {
-            Utils.log.info("finish computePopSizePrivate fvlen="+fVlen+
-                             " fc="+pop.favoredCoding+
-                             " tc="+pop.tokenCoding+
-                             " uc="+pop.unfavoredCoding);
-            //pop.hist.print("pop-hist", null, System.out);
-            StringBuilder sb = new StringBuilder();
-            sb.append("fv = {");
-            for (int i = 1; i <= fVlen; i++) {
-                if ((i % 10) == 0)
-                    sb.append('\n');
-                sb.append(" ").append(favoredValues[i]);
-            }
-            sb.append('\n');
-            sb.append("}");
-            Utils.log.info(sb.toString());
-        }
-        if (verbose > 2) {
-            Utils.log.info("} //END");
-        }
-        if (stress != null) {
-            return null;  // do not bother with size computation
-        }
-        int[] sizes;
-        try {
-            resetData();
-            // Write the array of favored values.
-            pop.writeSequencesTo(byteSizer, tokens, unfavoredValues);
-            sizes = new int[] { getByteSize(), getZipSize() };
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-        int[] checkSizes = null;
-        assert((checkSizes = computeSizePrivate(pop)) != null);
-        assert(checkSizes[BYTE_SIZE] == sizes[BYTE_SIZE])
-            : (checkSizes[BYTE_SIZE]+" != "+sizes[BYTE_SIZE]);
-        return sizes;
-    }
-
-    private void tryAdaptiveCoding(Coding plainCoding) {
-        int oldZipSize = bestZipSize;
-        // Scan the value sequence, determining whether an interesting
-        // run occupies too much space.  ("Too much" means, say 5% more
-        // than the average integer size of the band as a whole.)
-        // Try to find a better coding for those segments.
-        int   lstart  = this.start;
-        int   lend    = this.end;
-        int[] lvalues = this.values;
-        int len = lend-lstart;
-        if (plainCoding.isDelta()) {
-            lvalues = getDeltas(0,0); //%%% not quite right!
-            lstart = 0;
-            lend = lvalues.length;
-        }
-        int[] sizes = new int[len+1];
-        int fillp = 0;
-        int totalSize = 0;
-        for (int i = lstart; i < lend; i++) {
-            int val = lvalues[i];
-            sizes[fillp++] = totalSize;
-            int size = plainCoding.getLength(val);
-            assert(size < Integer.MAX_VALUE);
-            //System.out.println("len "+val+" = "+size);
-            totalSize += size;
-        }
-        sizes[fillp++] = totalSize;
-        assert(fillp == sizes.length);
-        double avgSize = (double)totalSize / len;
-        double sizeFuzz;
-        double sizeFuzz2;
-        double sizeFuzz3;
-        if (effort >= MID_EFFORT) {
-            if (effort > MID_EFFORT+1)
-                sizeFuzz = 1.001;
-            else
-                sizeFuzz = 1.003;
-        } else {
-            if (effort > RUN_EFFORT)
-                sizeFuzz = 1.01;
-            else
-                sizeFuzz = 1.03;
-        }
-        // for now:
-        sizeFuzz *= sizeFuzz; // double the thresh
-        sizeFuzz2 = (sizeFuzz*sizeFuzz);
-        sizeFuzz3 = (sizeFuzz*sizeFuzz*sizeFuzz);
-        // Find some mesh scales we like.
-        double[] dmeshes = new double[1 + (effort-RUN_EFFORT)];
-        double logLen = Math.log(len);
-        for (int i = 0; i < dmeshes.length; i++) {
-            dmeshes[i] = Math.exp(logLen*(i+1)/(dmeshes.length+1));
-        }
-        int[] meshes = new int[dmeshes.length];
-        int mfillp = 0;
-        for (int i = 0; i < dmeshes.length; i++) {
-            int m = (int)Math.round(dmeshes[i]);
-            m = AdaptiveCoding.getNextK(m-1);
-            if (m <= 0 || m >= len)  continue;
-            if (mfillp > 0 && m == meshes[mfillp-1])  continue;
-            meshes[mfillp++] = m;
-        }
-        meshes = BandStructure.realloc(meshes, mfillp);
-        // There's going to be a band header.  Estimate conservatively large.
-        final int BAND_HEADER = 4; // op, KB, A, B
-        // Threshold values for a "too big" mesh.
-        int[]    threshes = new int[meshes.length];
-        double[] fuzzes   = new double[meshes.length];
-        for (int i = 0; i < meshes.length; i++) {
-            int mesh = meshes[i];
-            double lfuzz;
-            if (mesh < 10)
-                lfuzz = sizeFuzz3;
-            else if (mesh < 100)
-                lfuzz = sizeFuzz2;
-            else
-                lfuzz = sizeFuzz;
-            fuzzes[i] = lfuzz;
-            threshes[i] = BAND_HEADER + (int)Math.ceil(mesh * avgSize * lfuzz);
-        }
-        if (verbose > 1) {
-            System.out.print("tryAdaptiveCoding ["+len+"]"+
-                             " avgS="+avgSize+" fuzz="+sizeFuzz+
-                             " meshes: {");
-            for (int i = 0; i < meshes.length; i++) {
-                System.out.print(" " + meshes[i] + "(" + threshes[i] + ")");
-            }
-            Utils.log.info(" }");
-        }
-        if (runHelper == null) {
-            runHelper = new CodingChooser(effort, allCodingChoices);
-            if (stress != null)
-                runHelper.addStressSeed(stress.nextInt());
-            runHelper.topLevel = false;
-            runHelper.verbose -= 1;
-            runHelper.disableRunCoding = true;
-            runHelper.disablePopCoding = this.disablePopCoding;
-            if (effort < MID_EFFORT)
-                // No nested pop codings.
-                runHelper.disablePopCoding = true;
-        }
-        for (int i = 0; i < len; i++) {
-            i = AdaptiveCoding.getNextK(i-1);
-            if (i > len)  i = len;
-            for (int j = meshes.length-1; j >= 0; j--) {
-                int mesh   = meshes[j];
-                int thresh = threshes[j];
-                if (i+mesh > len)  continue;
-                int size = sizes[i+mesh] - sizes[i];
-                if (size >= thresh) {
-                    // Found a size bulge.
-                    int bend  = i+mesh;
-                    int bsize = size;
-                    double bigSize = avgSize * fuzzes[j];
-                    while (bend < len && (bend-i) <= len/2) {
-                        int bend0 = bend;
-                        int bsize0 = bsize;
-                        bend += mesh;
-                        bend = i+AdaptiveCoding.getNextK(bend-i-1);
-                        if (bend < 0 || bend > len)
-                            bend = len;
-                        bsize = sizes[bend]-sizes[i];
-                        if (bsize < BAND_HEADER + (bend-i) * bigSize) {
-                            bsize = bsize0;
-                            bend = bend0;
-                            break;
-                        }
-                    }
-                    int nexti = bend;
-                    if (verbose > 2) {
-                        Utils.log.info("bulge at "+i+"["+(bend-i)+"] of "+
-                                         pct(bsize - avgSize*(bend-i),
-                                             avgSize*(bend-i)));
-                        Utils.log.info("{ //BEGIN");
-                    }
-                    CodingMethod begcm, midcm, endcm;
-                    midcm = runHelper.choose(this.values,
-                                             this.start+i,
-                                             this.start+bend,
-                                             plainCoding);
-                    if (midcm == plainCoding) {
-                        // No use working further.
-                        begcm = plainCoding;
-                        endcm = plainCoding;
-                    } else {
-                        begcm = runHelper.choose(this.values,
-                                                 this.start,
-                                                 this.start+i,
-                                                 plainCoding);
-                        endcm = runHelper.choose(this.values,
-                                                 this.start+bend,
-                                                 this.start+len,
-                                                 plainCoding);
-                    }
-                    if (verbose > 2)
-                        Utils.log.info("} //END");
-                    if (begcm == midcm && i > 0 &&
-                        AdaptiveCoding.isCodableLength(bend)) {
-                        i = 0;
-                    }
-                    if (midcm == endcm && bend < len) {
-                        bend = len;
-                    }
-                    if (begcm != plainCoding ||
-                        midcm != plainCoding ||
-                        endcm != plainCoding) {
-                        CodingMethod chain;
-                        int hlen = 0;
-                        if (bend == len) {
-                            chain = midcm;
-                        } else {
-                            chain = new AdaptiveCoding(bend-i, midcm, endcm);
-                            hlen += BAND_HEADER;
-                        }
-                        if (i > 0) {
-                            chain = new AdaptiveCoding(i, begcm, chain);
-                            hlen += BAND_HEADER;
-                        }
-                        int[] chainSize = computeSizePrivate(chain);
-                        noteSizes(chain,
-                                  chainSize[BYTE_SIZE],
-                                  chainSize[ZIP_SIZE]+hlen);
-                    }
-                    i = nexti;
-                    break;
-                }
-            }
-        }
-        if (verbose > 3) {
-            if (bestZipSize < oldZipSize) {
-                Utils.log.info(">>> RUN WINS BY "+
-                                 (oldZipSize - bestZipSize));
-            }
-        }
-    }
-
-    private static
-    String pct(double num, double den) {
-        return (Math.round((num / den)*10000)/100.0)+"%";
-    }
-
-    static
-    class Sizer extends OutputStream {
-        final OutputStream out;  // if non-null, copy output here also
-        Sizer(OutputStream out) {
-            this.out = out;
-        }
-        Sizer() {
-            this(null);
-        }
-        private int count;
-        public void write(int b) throws IOException {
-            count++;
-            if (out != null)  out.write(b);
-        }
-        public void write(byte b[], int off, int len) throws IOException {
-            count += len;
-            if (out != null)  out.write(b, off, len);
-        }
-        public void reset() {
-            count = 0;
-        }
-        public int getSize() { return count; }
-
-        public String toString() {
-            String str = super.toString();
-            // If -ea, print out more informative strings!
-            assert((str = stringForDebug()) != null);
-            return str;
-        }
-        String stringForDebug() {
-            return "";
-        }
-    }
-
-    private Sizer zipSizer  = new Sizer();
-    private Deflater zipDef = new Deflater();
-    private DeflaterOutputStream zipOut = new DeflaterOutputStream(zipSizer, zipDef);
-    private Sizer byteSizer = new Sizer(zipOut);
-    private Sizer byteOnlySizer = new Sizer();
-
-    private void resetData() {
-        flushData();
-        zipDef.reset();
-        if (context != null) {
-            // Prepend given salt to the test output.
-            try {
-                context.writeTo(byteSizer);
-            } catch (IOException ee) {
-                throw new RuntimeException(ee); // cannot happen
-            }
-        }
-        zipSizer.reset();
-        byteSizer.reset();
-    }
-    private void flushData() {
-        try {
-            zipOut.finish();
-        } catch (IOException ee) {
-            throw new RuntimeException(ee); // cannot happen
-        }
-    }
-    private int getByteSize() {
-        return byteSizer.getSize();
-    }
-    private int getZipSize() {
-        flushData();
-        return zipSizer.getSize();
-    }
-
-
-    /// Stress-test helpers.
-
-    void addStressSeed(int x) {
-        if (stress == null)  return;
-        stress.setSeed(x + ((long)stress.nextInt() << 32));
-    }
-
-    // Pick a random pop-coding.
-    private CodingMethod stressPopCoding(CodingMethod coding) {
-        assert(stress != null);  // this method is only for testing
-        // Don't turn it into a pop coding if it's already something special.
-        if (!(coding instanceof Coding))  return coding;
-        Coding valueCoding = ((Coding)coding).getValueCoding();
-        Histogram hist = getValueHistogram();
-        int fVlen = stressLen(hist.getTotalLength());
-        if (fVlen == 0)  return coding;
-        List popvals = new ArrayList<>();
-        if (stress.nextBoolean()) {
-            // Build the population from the value list.
-            Set popset = new HashSet<>();
-            for (int i = start; i < end; i++) {
-                if (popset.add(values[i]))  popvals.add(values[i]);
-            }
-        } else {
-            int[][] matrix = hist.getMatrix();
-            for (int mrow = 0; mrow < matrix.length; mrow++) {
-                int[] row = matrix[mrow];
-                for (int mcol = 1; mcol < row.length; mcol++) {
-                    popvals.add(row[mcol]);
-                }
-            }
-        }
-        int reorder = stress.nextInt();
-        if ((reorder & 7) <= 2) {
-            // Lose the order.
-            Collections.shuffle(popvals, stress);
-        } else {
-            // Keep the order, mostly.
-            if (((reorder >>>= 3) & 7) <= 2)  Collections.sort(popvals);
-            if (((reorder >>>= 3) & 7) <= 2)  Collections.reverse(popvals);
-            if (((reorder >>>= 3) & 7) <= 2)  Collections.rotate(popvals, stressLen(popvals.size()));
-        }
-        if (popvals.size() > fVlen) {
-            // Cut the list down.
-            if (((reorder >>>= 3) & 7) <= 2) {
-                // Cut at end.
-                popvals.subList(fVlen,   popvals.size()).clear();
-            } else {
-                // Cut at start.
-                popvals.subList(0, popvals.size()-fVlen).clear();
-            }
-        }
-        fVlen = popvals.size();
-        int[] fvals = new int[1+fVlen];
-        for (int i = 0; i < fVlen; i++) {
-            fvals[1+i] = (popvals.get(i)).intValue();
-        }
-        PopulationCoding pop = new PopulationCoding();
-        pop.setFavoredValues(fvals, fVlen);
-        int[] lvals = PopulationCoding.LValuesCoded;
-        for (int i = 0; i < lvals.length / 2; i++) {
-            int popl = lvals[stress.nextInt(lvals.length)];
-            if (popl < 0)  continue;
-            if (PopulationCoding.fitTokenCoding(fVlen, popl) != null) {
-                pop.setL(popl);
-                break;
-            }
-        }
-        if (pop.tokenCoding == null) {
-            int lmin = fvals[1], lmax = lmin;
-            for (int i = 2; i <= fVlen; i++) {
-                int val = fvals[i];
-                if (lmin > val)  lmin = val;
-                if (lmax < val)  lmax = val;
-            }
-            pop.tokenCoding = stressCoding(lmin, lmax);
-        }
-
-        computePopSizePrivate(pop, valueCoding, valueCoding);
-        return pop;
-    }
-
-    // Pick a random adaptive coding.
-    private CodingMethod stressAdaptiveCoding(CodingMethod coding) {
-        assert(stress != null);  // this method is only for testing
-        // Don't turn it into a run coding if it's already something special.
-        if (!(coding instanceof Coding))  return coding;
-        Coding plainCoding = (Coding)coding;
-        int len = end-start;
-        if (len < 2)  return coding;
-        // Decide how many spans we'll create.
-        int spanlen = stressLen(len-1)+1;
-        if (spanlen == len)  return coding;
-        try {
-            assert(!disableRunCoding);
-            disableRunCoding = true;  // temporary, while I decide spans
-            int[] allValues = values.clone();
-            CodingMethod result = null;
-            int scan  = this.end;
-            int lstart = this.start;
-            for (int split; scan > lstart; scan = split) {
-                int thisspan;
-                int rand = (scan - lstart < 100)? -1: stress.nextInt();
-                if ((rand & 7) != 0) {
-                    thisspan = (spanlen==1? spanlen: stressLen(spanlen-1)+1);
-                } else {
-                    // Every so often generate a value based on KX/KB format.
-                    int KX = (rand >>>= 3) & AdaptiveCoding.KX_MAX;
-                    int KB = (rand >>>= 3) & AdaptiveCoding.KB_MAX;
-                    for (;;) {
-                        thisspan = AdaptiveCoding.decodeK(KX, KB);
-                        if (thisspan <= scan - lstart)  break;
-                        // Try smaller and smaller codings:
-                        if (KB != AdaptiveCoding.KB_DEFAULT)
-                            KB = AdaptiveCoding.KB_DEFAULT;
-                        else
-                            KX -= 1;
-                    }
-                    //System.out.println("KX="+KX+" KB="+KB+" K="+thisspan);
-                    assert(AdaptiveCoding.isCodableLength(thisspan));
-                }
-                if (thisspan > scan - lstart)  thisspan = scan - lstart;
-                while (!AdaptiveCoding.isCodableLength(thisspan)) {
-                    --thisspan;
-                }
-                split = scan - thisspan;
-                assert(split < scan);
-                assert(split >= lstart);
-                // Choose a coding for the span [split..scan).
-                CodingMethod sc = choose(allValues, split, scan, plainCoding);
-                if (result == null) {
-                    result = sc;  // the caboose
-                } else {
-                    result = new AdaptiveCoding(scan-split, sc, result);
-                }
-            }
-            return result;
-        } finally {
-            disableRunCoding = false; // return to normal value
-        }
-    }
-
-    // Return a random value in [0..len], gently biased toward extremes.
-    private Coding stressCoding(int min, int max) {
-        assert(stress != null);  // this method is only for testing
-        for (int i = 0; i < 100; i++) {
-            Coding c = Coding.of(stress.nextInt(Coding.B_MAX)+1,
-                                 stress.nextInt(Coding.H_MAX)+1,
-                                 stress.nextInt(Coding.S_MAX+1));
-            if (c.B() == 1)  c = c.setH(256);
-            if (c.H() == 256 && c.B() >= 5)  c = c.setB(4);
-            if (stress.nextBoolean()) {
-                Coding dc = c.setD(1);
-                if (dc.canRepresent(min, max))  return dc;
-            }
-            if (c.canRepresent(min, max))  return c;
-        }
-        return BandStructure.UNSIGNED5;
-    }
-
-    // Return a random value in [0..len], gently biased toward extremes.
-    private int stressLen(int len) {
-        assert(stress != null);  // this method is only for testing
-        assert(len >= 0);
-        int rand = stress.nextInt(100);
-        if (rand < 20)
-            return Math.min(len/5, rand);
-        else if (rand < 40)
-            return len;
-        else
-            return stress.nextInt(len);
-    }
-
-    // For debug only.
-/*
-    public static
-    int[] readValuesFrom(InputStream instr) {
-        return readValuesFrom(new InputStreamReader(instr));
-    }
-    public static
-    int[] readValuesFrom(Reader inrdr) {
-        inrdr = new BufferedReader(inrdr);
-        final StreamTokenizer in = new StreamTokenizer(inrdr);
-        final int TT_NOTHING = -99;
-        in.commentChar('#');
-        return readValuesFrom(new Iterator() {
-            int token = TT_NOTHING;
-            private int getToken() {
-                if (token == TT_NOTHING) {
-                    try {
-                        token = in.nextToken();
-                        assert(token != TT_NOTHING);
-                    } catch (IOException ee) {
-                        throw new RuntimeException(ee);
-                    }
-                }
-                return token;
-            }
-            public boolean hasNext() {
-                return getToken() != StreamTokenizer.TT_EOF;
-            }
-            public Object next() {
-                int ntok = getToken();
-                token = TT_NOTHING;
-                switch (ntok) {
-                case StreamTokenizer.TT_EOF:
-                    throw new NoSuchElementException();
-                case StreamTokenizer.TT_NUMBER:
-                    return Integer.valueOf((int) in.nval);
-                default:
-                    assert(false);
-                    return null;
-                }
-            }
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        });
-    }
-    public static
-    int[] readValuesFrom(Iterator iter) {
-        return readValuesFrom(iter, 0);
-    }
-    public static
-    int[] readValuesFrom(Iterator iter, int initSize) {
-        int[] na = new int[Math.max(10, initSize)];
-        int np = 0;
-        while (iter.hasNext()) {
-            Integer val = (Integer) iter.next();
-            if (np == na.length) {
-                na = BandStructure.realloc(na);
-            }
-            na[np++] = val.intValue();
-        }
-        if (np != na.length) {
-            na = BandStructure.realloc(na, np);
-        }
-        return na;
-    }
-
-    public static
-    void main(String[] av) throws IOException {
-        int effort = MID_EFFORT;
-        int ap = 0;
-        if (ap < av.length && av[ap].equals("-e")) {
-            ap++;
-            effort = Integer.parseInt(av[ap++]);
-        }
-        int verbose = 1;
-        if (ap < av.length && av[ap].equals("-v")) {
-            ap++;
-            verbose = Integer.parseInt(av[ap++]);
-        }
-        Coding[] bcs = BandStructure.getBasicCodings();
-        CodingChooser cc = new CodingChooser(effort, bcs);
-        if (ap < av.length && av[ap].equals("-p")) {
-            ap++;
-            cc.optUsePopulationCoding = false;
-        }
-        if (ap < av.length && av[ap].equals("-a")) {
-            ap++;
-            cc.optUseAdaptiveCoding = false;
-        }
-        cc.verbose = verbose;
-        int[] values = readValuesFrom(System.in);
-        int[] sizes = {0,0};
-        CodingMethod cm = cc.choose(values, BandStructure.UNSIGNED5, sizes);
-        System.out.println("size: "+sizes[BYTE_SIZE]+"/zs="+sizes[ZIP_SIZE]);
-        System.out.println(cm);
-    }
-//*/
-
-}
diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java
deleted file mode 100644
index c60702fdacf..00000000000
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/CodingMethod.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.java.util.jar.pack;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Interface for encoding and decoding int arrays using bytewise codes.
- * @author John Rose
- */
-interface CodingMethod {
-    // Read and write an array of ints from/to a stream.
-    public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException;
-    public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException;
-
-    // how to express me in a band header?
-    public byte[] getMetaCoding(Coding dflt);
-}
diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java
deleted file mode 100644
index b75d8c4e7a9..00000000000
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/ConstantPool.java
+++ /dev/null
@@ -1,1658 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.java.util.jar.pack;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-import static com.sun.java.util.jar.pack.Constants.*;
-
-/**
- * Representation of constant pool entries and indexes.
- * @author John Rose
- */
-abstract
-class ConstantPool {
-    private ConstantPool() {}  // do not instantiate
-
-    static int verbose() {
-        return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
-    }
-
-    /** Factory for Utf8 string constants.
-     *  Used for well-known strings like "SourceFile", "", etc.
-     *  Also used to back up more complex constant pool entries, like Class.
-     */
-    public static synchronized Utf8Entry getUtf8Entry(String value) {
-        Map utf8Entries  = Utils.getTLGlobals().getUtf8Entries();
-        Utf8Entry e = utf8Entries.get(value);
-        if (e == null) {
-            e = new Utf8Entry(value);
-            utf8Entries.put(e.stringValue(), e);
-        }
-        return e;
-    }
-    /** Factory for Class constants. */
-    public static ClassEntry getClassEntry(String name) {
-        Map classEntries = Utils.getTLGlobals().getClassEntries();
-        ClassEntry e = classEntries.get(name);
-        if (e == null) {
-            e = new ClassEntry(getUtf8Entry(name));
-            assert(name.equals(e.stringValue()));
-            classEntries.put(e.stringValue(), e);
-        }
-        return e;
-    }
-    /** Factory for literal constants (String, Integer, etc.). */
-    public static LiteralEntry getLiteralEntry(Comparable value) {
-        Map literalEntries = Utils.getTLGlobals().getLiteralEntries();
-        LiteralEntry e = literalEntries.get(value);
-        if (e == null) {
-            if (value instanceof String)
-                e = new StringEntry(getUtf8Entry((String)value));
-            else
-                e = new NumberEntry((Number)value);
-            literalEntries.put(value, e);
-        }
-        return e;
-    }
-    /** Factory for literal constants (String, Integer, etc.). */
-    public static StringEntry getStringEntry(String value) {
-        return (StringEntry) getLiteralEntry(value);
-    }
-
-    /** Factory for signature (type) constants. */
-    public static SignatureEntry getSignatureEntry(String type) {
-        Map signatureEntries = Utils.getTLGlobals().getSignatureEntries();
-        SignatureEntry e = signatureEntries.get(type);
-        if (e == null) {
-            e = new SignatureEntry(type);
-            assert(e.stringValue().equals(type));
-            signatureEntries.put(type, e);
-        }
-        return e;
-    }
-    // Convenience overloading.
-    public static SignatureEntry getSignatureEntry(Utf8Entry formRef, ClassEntry[] classRefs) {
-        return getSignatureEntry(SignatureEntry.stringValueOf(formRef, classRefs));
-    }
-
-    /** Factory for descriptor (name-and-type) constants. */
-    public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
-        Map descriptorEntries = Utils.getTLGlobals().getDescriptorEntries();
-        String key = DescriptorEntry.stringValueOf(nameRef, typeRef);
-        DescriptorEntry e = descriptorEntries.get(key);
-        if (e == null) {
-            e = new DescriptorEntry(nameRef, typeRef);
-            assert(e.stringValue().equals(key))
-                : (e.stringValue()+" != "+(key));
-            descriptorEntries.put(key, e);
-        }
-        return e;
-    }
-    // Convenience overloading.
-    public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, Utf8Entry typeRef) {
-        return getDescriptorEntry(nameRef, getSignatureEntry(typeRef.stringValue()));
-    }
-
-    /** Factory for member reference constants. */
-    public static MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
-        Map memberEntries = Utils.getTLGlobals().getMemberEntries();
-        String key = MemberEntry.stringValueOf(tag, classRef, descRef);
-        MemberEntry e = memberEntries.get(key);
-        if (e == null) {
-            e = new MemberEntry(tag, classRef, descRef);
-            assert(e.stringValue().equals(key))
-                : (e.stringValue()+" != "+(key));
-            memberEntries.put(key, e);
-        }
-        return e;
-    }
-
-    /** Factory for MethodHandle constants. */
-    public static MethodHandleEntry getMethodHandleEntry(byte refKind, MemberEntry memRef) {
-        Map methodHandleEntries = Utils.getTLGlobals().getMethodHandleEntries();
-        String key = MethodHandleEntry.stringValueOf(refKind, memRef);
-        MethodHandleEntry e = methodHandleEntries.get(key);
-        if (e == null) {
-            e = new MethodHandleEntry(refKind, memRef);
-            assert(e.stringValue().equals(key));
-            methodHandleEntries.put(key, e);
-        }
-        return e;
-    }
-
-    /** Factory for MethodType constants. */
-    public static MethodTypeEntry getMethodTypeEntry(SignatureEntry sigRef) {
-        Map methodTypeEntries = Utils.getTLGlobals().getMethodTypeEntries();
-        String key = sigRef.stringValue();
-        MethodTypeEntry e = methodTypeEntries.get(key);
-        if (e == null) {
-            e = new MethodTypeEntry(sigRef);
-            assert(e.stringValue().equals(key));
-            methodTypeEntries.put(key, e);
-        }
-        return e;
-    }
-    public static MethodTypeEntry getMethodTypeEntry(Utf8Entry typeRef) {
-        return getMethodTypeEntry(getSignatureEntry(typeRef.stringValue()));
-    }
-
-    /** Factory for InvokeDynamic constants. */
-    public static InvokeDynamicEntry getInvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
-        Map invokeDynamicEntries = Utils.getTLGlobals().getInvokeDynamicEntries();
-        String key = InvokeDynamicEntry.stringValueOf(bssRef, descRef);
-        InvokeDynamicEntry e = invokeDynamicEntries.get(key);
-        if (e == null) {
-            e = new InvokeDynamicEntry(bssRef, descRef);
-            assert(e.stringValue().equals(key));
-            invokeDynamicEntries.put(key, e);
-        }
-        return e;
-    }
-
-    /** Factory for BootstrapMethod pseudo-constants. */
-    public static BootstrapMethodEntry getBootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) {
-        Map bootstrapMethodEntries = Utils.getTLGlobals().getBootstrapMethodEntries();
-        String key = BootstrapMethodEntry.stringValueOf(bsmRef, argRefs);
-        BootstrapMethodEntry e = bootstrapMethodEntries.get(key);
-        if (e == null) {
-            e = new BootstrapMethodEntry(bsmRef, argRefs);
-            assert(e.stringValue().equals(key));
-            bootstrapMethodEntries.put(key, e);
-        }
-        return e;
-    }
-
-
-    /** Entries in the constant pool. */
-    public abstract static
-    class Entry implements Comparable {
-        protected final byte tag;       // a CONSTANT_foo code
-        protected int valueHash;        // cached hashCode
-
-        protected Entry(byte tag) {
-            this.tag = tag;
-        }
-
-        public final byte getTag() {
-            return tag;
-        }
-
-        public final boolean tagEquals(int tag) {
-            return getTag() == tag;
-        }
-
-        public Entry getRef(int i) {
-            return null;
-        }
-
-        public boolean eq(Entry that) {  // same reference
-            assert(that != null);
-            return this == that || this.equals(that);
-        }
-
-        // Equality of Entries is value-based.
-        public abstract boolean equals(Object o);
-        public final int hashCode() {
-            if (valueHash == 0) {
-                valueHash = computeValueHash();
-                if (valueHash == 0)  valueHash = 1;
-            }
-            return valueHash;
-        }
-        protected abstract int computeValueHash();
-
-        public abstract int compareTo(Object o);
-
-        protected int superCompareTo(Object o) {
-            Entry that = (Entry) o;
-
-            if (this.tag != that.tag) {
-                return TAG_ORDER[this.tag] - TAG_ORDER[that.tag];
-            }
-
-            return 0;  // subclasses must refine this
-        }
-
-        public final boolean isDoubleWord() {
-            return tag == CONSTANT_Double || tag == CONSTANT_Long;
-        }
-
-        public final boolean tagMatches(int matchTag) {
-            if (tag == matchTag)
-                return true;
-            byte[] allowedTags;
-            switch (matchTag) {
-                case CONSTANT_All:
-                    return true;
-                case CONSTANT_Signature:
-                    return tag == CONSTANT_Utf8;  // format check also?
-                case CONSTANT_LoadableValue:
-                    allowedTags = LOADABLE_VALUE_TAGS;
-                    break;
-                case CONSTANT_AnyMember:
-                    allowedTags = ANY_MEMBER_TAGS;
-                    break;
-                case CONSTANT_FieldSpecific:
-                    allowedTags = FIELD_SPECIFIC_TAGS;
-                    break;
-                default:
-                    return false;
-            }
-            for (byte b : allowedTags) {
-                if (b == tag)
-                    return true;
-            }
-            return false;
-        }
-
-        public String toString() {
-            String valuePrint = stringValue();
-            if (verbose() > 4) {
-                if (valueHash != 0)
-                    valuePrint += " hash="+valueHash;
-                valuePrint += " id="+System.identityHashCode(this);
-            }
-            return tagName(tag)+"="+valuePrint;
-        }
-        public abstract String stringValue();
-    }
-
-    public static
-    class Utf8Entry extends Entry {
-        final String value;
-
-        Utf8Entry(String value) {
-            super(CONSTANT_Utf8);
-            this.value = value.intern();
-            hashCode();  // force computation of valueHash
-        }
-        protected int computeValueHash() {
-            return value.hashCode();
-        }
-        public boolean equals(Object o) {
-            // Use reference equality of interned strings:
-            return (o != null && o.getClass() == Utf8Entry.class
-                    && ((Utf8Entry) o).value.equals(value));
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                x = value.compareTo(((Utf8Entry)o).value);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return value;
-        }
-    }
-
-    static boolean isMemberTag(byte tag) {
-        switch (tag) {
-        case CONSTANT_Fieldref:
-        case CONSTANT_Methodref:
-        case CONSTANT_InterfaceMethodref:
-            return true;
-        }
-        return false;
-    }
-
-    static byte numberTagOf(Number value) {
-        if (value instanceof Integer)  return CONSTANT_Integer;
-        if (value instanceof Float)    return CONSTANT_Float;
-        if (value instanceof Long)     return CONSTANT_Long;
-        if (value instanceof Double)   return CONSTANT_Double;
-        throw new RuntimeException("bad literal value "+value);
-    }
-
-    static boolean isRefKind(byte refKind) {
-        return (REF_getField <= refKind && refKind <= REF_invokeInterface);
-    }
-
-    public abstract static
-    class LiteralEntry extends Entry {
-        protected LiteralEntry(byte tag) {
-            super(tag);
-        }
-
-        public abstract Comparable literalValue();
-    }
-
-    public static
-    class NumberEntry extends LiteralEntry {
-        final Number value;
-        NumberEntry(Number value) {
-            super(numberTagOf(value));
-            this.value = value;
-            hashCode();  // force computation of valueHash
-        }
-        protected int computeValueHash() {
-            return value.hashCode();
-        }
-
-        public boolean equals(Object o) {
-            return (o != null && o.getClass() == NumberEntry.class
-                    && ((NumberEntry) o).value.equals(value));
-
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                @SuppressWarnings("unchecked")
-                Comparable compValue = (Comparable)value;
-                x = compValue.compareTo(((NumberEntry)o).value);
-            }
-            return x;
-        }
-        public Number numberValue() {
-            return value;
-        }
-        public Comparable literalValue() {
-            return (Comparable) value;
-        }
-        public String stringValue() {
-            return value.toString();
-        }
-    }
-
-    public static
-    class StringEntry extends LiteralEntry {
-        final Utf8Entry ref;
-        public Entry getRef(int i) { return i == 0 ? ref : null; }
-
-        StringEntry(Entry ref) {
-            super(CONSTANT_String);
-            this.ref = (Utf8Entry) ref;
-            hashCode();  // force computation of valueHash
-        }
-        protected int computeValueHash() {
-            return ref.hashCode() + tag;
-        }
-        public boolean equals(Object o) {
-            return (o != null && o.getClass() == StringEntry.class &&
-                    ((StringEntry)o).ref.eq(ref));
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                x = ref.compareTo(((StringEntry)o).ref);
-            }
-            return x;
-        }
-        public Comparable literalValue() {
-            return ref.stringValue();
-        }
-        public String stringValue() {
-            return ref.stringValue();
-        }
-    }
-
-    public static
-    class ClassEntry extends Entry {
-        final Utf8Entry ref;
-        public Entry getRef(int i) { return i == 0 ? ref : null; }
-
-        protected int computeValueHash() {
-            return ref.hashCode() + tag;
-        }
-        ClassEntry(Entry ref) {
-            super(CONSTANT_Class);
-            this.ref = (Utf8Entry) ref;
-            hashCode();  // force computation of valueHash
-        }
-        public boolean equals(Object o) {
-            return (o != null && o.getClass() == ClassEntry.class
-                    && ((ClassEntry) o).ref.eq(ref));
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                x = ref.compareTo(((ClassEntry)o).ref);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return ref.stringValue();
-        }
-    }
-
-    public static
-    class DescriptorEntry extends Entry {
-        final Utf8Entry      nameRef;
-        final SignatureEntry typeRef;
-        public Entry getRef(int i) {
-            if (i == 0)  return nameRef;
-            if (i == 1)  return typeRef;
-            return null;
-        }
-        DescriptorEntry(Entry nameRef, Entry typeRef) {
-            super(CONSTANT_NameandType);
-            if (typeRef instanceof Utf8Entry) {
-                typeRef = getSignatureEntry(typeRef.stringValue());
-            }
-            this.nameRef = (Utf8Entry) nameRef;
-            this.typeRef = (SignatureEntry) typeRef;
-            hashCode();  // force computation of valueHash
-        }
-        protected int computeValueHash() {
-            int hc2 = typeRef.hashCode();
-            return (nameRef.hashCode() + (hc2 << 8)) ^ hc2;
-        }
-        public boolean equals(Object o) {
-            if (o == null || o.getClass() != DescriptorEntry.class) {
-                return false;
-            }
-            DescriptorEntry that = (DescriptorEntry)o;
-            return this.nameRef.eq(that.nameRef)
-                && this.typeRef.eq(that.typeRef);
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                DescriptorEntry that = (DescriptorEntry)o;
-                // Primary key is typeRef, not nameRef.
-                x = this.typeRef.compareTo(that.typeRef);
-                if (x == 0)
-                    x = this.nameRef.compareTo(that.nameRef);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return stringValueOf(nameRef, typeRef);
-        }
-        static
-        String stringValueOf(Entry nameRef, Entry typeRef) {
-            return qualifiedStringValue(typeRef, nameRef);
-        }
-
-        public String prettyString() {
-            return nameRef.stringValue()+typeRef.prettyString();
-        }
-
-        public boolean isMethod() {
-            return typeRef.isMethod();
-        }
-
-        public byte getLiteralTag() {
-            return typeRef.getLiteralTag();
-        }
-    }
-
-    static String qualifiedStringValue(Entry e1, Entry e2) {
-        return qualifiedStringValue(e1.stringValue(), e2.stringValue());
-    }
-    static String qualifiedStringValue(String s1, String s234) {
-        // Qualification by dot must decompose uniquely.  Second string might already be qualified.
-        assert(s1.indexOf('.') < 0);
-        return s1+"."+s234;
-    }
-
-    public static
-    class MemberEntry extends Entry {
-        final ClassEntry classRef;
-        final DescriptorEntry descRef;
-        public Entry getRef(int i) {
-            if (i == 0)  return classRef;
-            if (i == 1)  return descRef;
-            return null;
-        }
-        protected int computeValueHash() {
-            int hc2 = descRef.hashCode();
-            return (classRef.hashCode() + (hc2 << 8)) ^ hc2;
-        }
-
-        MemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
-            super(tag);
-            assert(isMemberTag(tag));
-            this.classRef = classRef;
-            this.descRef  = descRef;
-            hashCode();  // force computation of valueHash
-        }
-        public boolean equals(Object o) {
-            if (o == null || o.getClass() != MemberEntry.class) {
-                return false;
-            }
-            MemberEntry that = (MemberEntry)o;
-            return this.classRef.eq(that.classRef)
-                && this.descRef.eq(that.descRef);
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                MemberEntry that = (MemberEntry)o;
-                if (Utils.SORT_MEMBERS_DESCR_MAJOR)
-                    // descRef is transmitted as UDELTA5; sort it first?
-                    x = this.descRef.compareTo(that.descRef);
-                // Primary key is classRef.
-                if (x == 0)
-                    x = this.classRef.compareTo(that.classRef);
-                if (x == 0)
-                    x = this.descRef.compareTo(that.descRef);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return stringValueOf(tag, classRef, descRef);
-        }
-        static
-        String stringValueOf(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
-            assert(isMemberTag(tag));
-            String pfx;
-            switch (tag) {
-            case CONSTANT_Fieldref:            pfx = "Field:";   break;
-            case CONSTANT_Methodref:           pfx = "Method:";  break;
-            case CONSTANT_InterfaceMethodref:  pfx = "IMethod:"; break;
-            default:                           pfx = tag+"???";  break;
-            }
-            return pfx+qualifiedStringValue(classRef, descRef);
-        }
-
-        public boolean isMethod() {
-            return descRef.isMethod();
-        }
-    }
-
-    public static
-    class SignatureEntry extends Entry {
-        final Utf8Entry    formRef;
-        final ClassEntry[] classRefs;
-        String             value;
-        Utf8Entry          asUtf8Entry;
-        public Entry getRef(int i) {
-            if (i == 0)  return formRef;
-            return i-1 < classRefs.length ? classRefs[i-1] : null;
-        }
-        SignatureEntry(String value) {
-            super(CONSTANT_Signature);
-            value = value.intern();  // always do this
-            this.value = value;
-            String[] parts = structureSignature(value);
-            formRef = getUtf8Entry(parts[0]);
-            classRefs = new ClassEntry[parts.length-1];
-            for (int i = 1; i < parts.length; i++) {
-                classRefs[i - 1] = getClassEntry(parts[i]);
-            }
-            hashCode();  // force computation of valueHash
-        }
-        protected int computeValueHash() {
-            stringValue();  // force computation of value
-            return value.hashCode() + tag;
-        }
-
-        public Utf8Entry asUtf8Entry() {
-            if (asUtf8Entry == null) {
-                asUtf8Entry = getUtf8Entry(stringValue());
-            }
-            return asUtf8Entry;
-        }
-
-        public boolean equals(Object o) {
-            return (o != null && o.getClass() == SignatureEntry.class &&
-                    ((SignatureEntry)o).value.equals(value));
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                SignatureEntry that = (SignatureEntry)o;
-                x = compareSignatures(this.value, that.value);
-            }
-            return x;
-        }
-        public String stringValue() {
-            if (value == null) {
-                value = stringValueOf(formRef, classRefs);
-            }
-            return value;
-        }
-        static
-        String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) {
-            String[] parts = new String[1+classRefs.length];
-            parts[0] = formRef.stringValue();
-            for (int i = 1; i < parts.length; i++) {
-                parts[i] = classRefs[i - 1].stringValue();
-            }
-            return flattenSignature(parts).intern();
-        }
-
-        public int computeSize(boolean countDoublesTwice) {
-            String form = formRef.stringValue();
-            int min = 0;
-            int max = 1;
-            if (isMethod()) {
-                min = 1;
-                max = form.indexOf(')');
-            }
-            int size = 0;
-            for (int i = min; i < max; i++) {
-                switch (form.charAt(i)) {
-                    case 'D':
-                    case 'J':
-                        if (countDoublesTwice) {
-                            size++;
-                        }
-                        break;
-                    case '[':
-                        // Skip rest of array info.
-                        while (form.charAt(i) == '[') {
-                            ++i;
-                        }
-                        break;
-                    case ';':
-                        continue;
-                    default:
-                        assert (0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i)));
-                        break;
-                }
-                size++;
-            }
-            return size;
-        }
-        public boolean isMethod() {
-            return formRef.stringValue().charAt(0) == '(';
-        }
-        public byte getLiteralTag() {
-            switch (formRef.stringValue().charAt(0)) {
-            case 'I': return CONSTANT_Integer;
-            case 'J': return CONSTANT_Long;
-            case 'F': return CONSTANT_Float;
-            case 'D': return CONSTANT_Double;
-            case 'B': case 'S': case 'C': case 'Z':
-                return CONSTANT_Integer;
-            case 'L':
-                /*
-                switch (classRefs[0].stringValue()) {
-                case "java/lang/String":
-                    return CONSTANT_String;
-                case "java/lang/invoke/MethodHandle":
-                    return CONSTANT_MethodHandle;
-                case "java/lang/invoke/MethodType":
-                    return CONSTANT_MethodType;
-                default:  // java/lang/Object, etc.
-                    return CONSTANT_LoadableValue;
-                }
-                */
-                return CONSTANT_String;  // JDK 7 ConstantValue limited to String
-            }
-            assert(false);
-            return CONSTANT_None;
-        }
-        public String prettyString() {
-            String s;
-            if (isMethod()) {
-                s = formRef.stringValue();
-                s = s.substring(0, 1+s.indexOf(')'));
-            } else {
-                s = "/" + formRef.stringValue();
-            }
-            int i;
-            while ((i = s.indexOf(';')) >= 0) {
-                s = s.substring(0, i) + s.substring(i + 1);
-            }
-            return s;
-        }
-    }
-
-    static int compareSignatures(String s1, String s2) {
-        return compareSignatures(s1, s2, null, null);
-    }
-    static int compareSignatures(String s1, String s2, String[] p1, String[] p2) {
-        final int S1_COMES_FIRST = -1;
-        final int S2_COMES_FIRST = +1;
-        char c1 = s1.charAt(0);
-        char c2 = s2.charAt(0);
-        // fields before methods (because there are fewer of them)
-        if (c1 != '(' && c2 == '(')  return S1_COMES_FIRST;
-        if (c2 != '(' && c1 == '(')  return S2_COMES_FIRST;
-        if (p1 == null)  p1 = structureSignature(s1);
-        if (p2 == null)  p2 = structureSignature(s2);
-        /*
-         // non-classes before classes (because there are fewer of them)
-         if (p1.length == 1 && p2.length > 1)  return S1_COMES_FIRST;
-         if (p2.length == 1 && p1.length > 1)  return S2_COMES_FIRST;
-         // all else being equal, use the same comparison as for Utf8 strings
-         return s1.compareTo(s2);
-         */
-        if (p1.length != p2.length)  return p1.length - p2.length;
-        int length = p1.length;
-        for (int i = length; --i >= 0; ) {
-            int res = p1[i].compareTo(p2[i]);
-            if (res != 0)  return res;
-        }
-        assert(s1.equals(s2));
-        return 0;
-    }
-
-    static int countClassParts(Utf8Entry formRef) {
-        int num = 0;
-        String s = formRef.stringValue();
-        for (int i = 0; i < s.length(); i++) {
-            if (s.charAt(i) == 'L')  ++num;
-        }
-        return num;
-    }
-
-    static String flattenSignature(String[] parts) {
-        String form = parts[0];
-        if (parts.length == 1)  return form;
-        int len = form.length();
-        for (int i = 1; i < parts.length; i++) {
-            len += parts[i].length();
-        }
-        char[] sig = new char[len];
-        int j = 0;
-        int k = 1;
-        for (int i = 0; i < form.length(); i++) {
-            char ch = form.charAt(i);
-            sig[j++] = ch;
-            if (ch == 'L') {
-                String cls = parts[k++];
-                cls.getChars(0, cls.length(), sig, j);
-                j += cls.length();
-                //sig[j++] = ';';
-            }
-        }
-        assert(j == len);
-        assert(k == parts.length);
-        return new String(sig);
-    }
-
-    private static int skipTo(char semi, String sig, int i) {
-        i = sig.indexOf(semi, i);
-        return (i >= 0) ? i : sig.length();
-    }
-
-    static String[] structureSignature(String sig) {
-        int firstl = sig.indexOf('L');
-        if (firstl < 0) {
-            String[] parts = { sig };
-            return parts;
-        }
-        // Segment the string like sig.split("L\\([^;<]*\\)").
-        // N.B.: Previous version of this code did a more complex match,
-        // to next ch < ' ' or ch in [';'..'@'].  The only important
-        // characters are ';' and '<', since they are part of the
-        // signature syntax.
-        // Examples:
-        //   "(Ljava/lang/Object;IJLLoo;)V" => {"(L;IJL;)V", "java/lang/Object", "Loo"}
-        //   "Ljava/util/List;" => {"L;", "java/util/List", "java/lang/String"}
-        char[] form = null;
-        String[] parts = null;
-        for (int pass = 0; pass <= 1; pass++) {
-            // pass 0 is a sizing pass, pass 1 packs the arrays
-            int formPtr = 0;
-            int partPtr = 1;
-            int nextsemi = 0, nextangl = 0;  // next ';' or '<', or zero, or sigLen
-            int lastj = 0;
-            for (int i = firstl + 1, j; i > 0; i = sig.indexOf('L', j) + 1) {
-                // sig[i-1] is 'L', while sig[j] will be the first ';' or '<' after it
-                // each part is in sig[i .. j-1]
-                if (nextsemi < i)  nextsemi = skipTo(';', sig, i);
-                if (nextangl < i)  nextangl = skipTo('<', sig, i);
-                j = (nextsemi < nextangl ? nextsemi : nextangl);
-                if (pass != 0) {
-                    sig.getChars(lastj, i, form, formPtr);
-                    parts[partPtr] = sig.substring(i, j);
-                }
-                formPtr += (i - lastj);
-                partPtr += 1;
-                lastj = j;
-            }
-            if (pass != 0) {
-                sig.getChars(lastj, sig.length(), form, formPtr);
-                break;
-            }
-            formPtr += (sig.length() - lastj);
-            form = new char[formPtr];
-            parts = new String[partPtr];
-        }
-        parts[0] = new String(form);
-        //assert(flattenSignature(parts).equals(sig));
-        return parts;
-    }
-
-    /** @since 1.7, JSR 292 */
-    public static
-    class MethodHandleEntry extends Entry {
-        final int refKind;
-        final MemberEntry memRef;
-        public Entry getRef(int i) { return i == 0 ? memRef : null; }
-
-        protected int computeValueHash() {
-            int hc2 = refKind;
-            return (memRef.hashCode() + (hc2 << 8)) ^ hc2;
-        }
-
-        MethodHandleEntry(byte refKind, MemberEntry memRef) {
-            super(CONSTANT_MethodHandle);
-            assert(isRefKind(refKind));
-            this.refKind = refKind;
-            this.memRef  = memRef;
-            hashCode();  // force computation of valueHash
-        }
-        public boolean equals(Object o) {
-            if (o == null || o.getClass() != MethodHandleEntry.class) {
-                return false;
-            }
-            MethodHandleEntry that = (MethodHandleEntry)o;
-            return this.refKind == that.refKind
-                && this.memRef.eq(that.memRef);
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                MethodHandleEntry that = (MethodHandleEntry)o;
-                if (Utils.SORT_HANDLES_KIND_MAJOR)
-                    // Primary key could be refKind.
-                    x = this.refKind - that.refKind;
-                // Primary key is memRef, which is transmitted as UDELTA5.
-                if (x == 0)
-                    x = this.memRef.compareTo(that.memRef);
-                if (x == 0)
-                    x = this.refKind - that.refKind;
-            }
-            return x;
-        }
-        public static String stringValueOf(int refKind, MemberEntry memRef) {
-            return refKindName(refKind)+":"+memRef.stringValue();
-        }
-        public String stringValue() {
-            return stringValueOf(refKind, memRef);
-        }
-    }
-
-    /** @since 1.7, JSR 292 */
-    public static
-    class MethodTypeEntry extends Entry {
-        final SignatureEntry typeRef;
-        public Entry getRef(int i) { return i == 0 ? typeRef : null; }
-
-        protected int computeValueHash() {
-            return typeRef.hashCode() + tag;
-        }
-
-        MethodTypeEntry(SignatureEntry typeRef) {
-            super(CONSTANT_MethodType);
-            this.typeRef  = typeRef;
-            hashCode();  // force computation of valueHash
-        }
-        public boolean equals(Object o) {
-            if (o == null || o.getClass() != MethodTypeEntry.class) {
-                return false;
-            }
-            MethodTypeEntry that = (MethodTypeEntry)o;
-            return this.typeRef.eq(that.typeRef);
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                MethodTypeEntry that = (MethodTypeEntry)o;
-                x = this.typeRef.compareTo(that.typeRef);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return typeRef.stringValue();
-        }
-    }
-
-    /** @since 1.7, JSR 292 */
-    public static
-    class InvokeDynamicEntry extends Entry {
-        final BootstrapMethodEntry bssRef;
-        final DescriptorEntry descRef;
-        public Entry getRef(int i) {
-            if (i == 0)  return bssRef;
-            if (i == 1)  return descRef;
-            return null;
-        }
-        protected int computeValueHash() {
-            int hc2 = descRef.hashCode();
-            return (bssRef.hashCode() + (hc2 << 8)) ^ hc2;
-        }
-
-        InvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
-            super(CONSTANT_InvokeDynamic);
-            this.bssRef  = bssRef;
-            this.descRef = descRef;
-            hashCode();  // force computation of valueHash
-        }
-        public boolean equals(Object o) {
-            if (o == null || o.getClass() != InvokeDynamicEntry.class) {
-                return false;
-            }
-            InvokeDynamicEntry that = (InvokeDynamicEntry)o;
-            return this.bssRef.eq(that.bssRef)
-                && this.descRef.eq(that.descRef);
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                InvokeDynamicEntry that = (InvokeDynamicEntry)o;
-                if (Utils.SORT_INDY_BSS_MAJOR)
-                    // Primary key could be bsmRef.
-                    x = this.bssRef.compareTo(that.bssRef);
-                // Primary key is descriptor, which is transmitted as UDELTA5.
-                if (x == 0)
-                    x = this.descRef.compareTo(that.descRef);
-                if (x == 0)
-                    x = this.bssRef.compareTo(that.bssRef);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return stringValueOf(bssRef, descRef);
-        }
-        static
-        String stringValueOf(BootstrapMethodEntry bssRef, DescriptorEntry descRef) {
-            return "Indy:"+bssRef.stringValue()+"."+descRef.stringValue();
-        }
-    }
-
-    /** @since 1.7, JSR 292 */
-    public static
-    class BootstrapMethodEntry extends Entry {
-        final MethodHandleEntry bsmRef;
-        final Entry[] argRefs;
-        public Entry getRef(int i) {
-            if (i == 0)  return bsmRef;
-            if (i-1 < argRefs.length)  return argRefs[i-1];
-            return null;
-        }
-        protected int computeValueHash() {
-            int hc2 = bsmRef.hashCode();
-            return (Arrays.hashCode(argRefs) + (hc2 << 8)) ^ hc2;
-        }
-
-        BootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) {
-            super(CONSTANT_BootstrapMethod);
-            this.bsmRef  = bsmRef;
-            this.argRefs = argRefs.clone();
-            hashCode();  // force computation of valueHash
-        }
-        public boolean equals(Object o) {
-            if (o == null || o.getClass() != BootstrapMethodEntry.class) {
-                return false;
-            }
-            BootstrapMethodEntry that = (BootstrapMethodEntry)o;
-            return this.bsmRef.eq(that.bsmRef)
-                && Arrays.equals(this.argRefs, that.argRefs);
-        }
-        public int compareTo(Object o) {
-            int x = superCompareTo(o);
-            if (x == 0) {
-                BootstrapMethodEntry that = (BootstrapMethodEntry)o;
-                if (Utils.SORT_BSS_BSM_MAJOR)
-                    // Primary key is bsmRef.
-                    x = this.bsmRef.compareTo(that.bsmRef);
-                // Primary key is args array length, which is transmitted as UDELTA5.
-                if (x == 0)
-                    x = compareArgArrays(this.argRefs, that.argRefs);
-                if (x == 0)
-                    x = this.bsmRef.compareTo(that.bsmRef);
-            }
-            return x;
-        }
-        public String stringValue() {
-            return stringValueOf(bsmRef, argRefs);
-        }
-        static
-        String stringValueOf(MethodHandleEntry bsmRef, Entry[] argRefs) {
-            StringBuilder sb = new StringBuilder(bsmRef.stringValue());
-            // Arguments are formatted as "" instead of "[foo,bar,baz]".
-            // This ensures there will be no confusion if "[,]" appear inside of names.
-            char nextSep = '<';
-            boolean didOne = false;
-            for (Entry argRef : argRefs) {
-                sb.append(nextSep).append(argRef.stringValue());
-                nextSep = ';';
-            }
-            if (nextSep == '<')  sb.append(nextSep);
-            sb.append('>');
-            return sb.toString();
-        }
-        static
-        int compareArgArrays(Entry[] a1, Entry[] a2) {
-            int x = a1.length - a2.length;
-            if (x != 0)  return x;
-            for (int i = 0; i < a1.length; i++) {
-                x = a1[i].compareTo(a2[i]);
-                if (x != 0)  break;
-            }
-            return x;
-        }
-    }
-
-    // Handy constants:
-    protected static final Entry[] noRefs = {};
-    protected static final ClassEntry[] noClassRefs = {};
-
-    /** An Index is a mapping between CP entries and small integers. */
-    public static final
-    class Index extends AbstractList {
-        protected String debugName;
-        protected Entry[] cpMap;
-        protected boolean flattenSigs;
-        protected Entry[] getMap() {
-            return cpMap;
-        }
-        protected Index(String debugName) {
-            this.debugName = debugName;
-        }
-        protected Index(String debugName, Entry[] cpMap) {
-            this(debugName);
-            setMap(cpMap);
-        }
-        protected void setMap(Entry[] cpMap) {
-            clearIndex();
-            this.cpMap = cpMap;
-        }
-        protected Index(String debugName, Collection cpMapList) {
-            this(debugName);
-            setMap(cpMapList);
-        }
-        protected void setMap(Collection cpMapList) {
-            cpMap = new Entry[cpMapList.size()];
-            cpMapList.toArray(cpMap);
-            setMap(cpMap);
-        }
-        public int size() {
-            return cpMap.length;
-        }
-        public Entry get(int i) {
-            return cpMap[i];
-        }
-        public Entry getEntry(int i) {
-            // same as get(), with covariant return type
-            return cpMap[i];
-        }
-
-        // Find index of e in cpMap, or return -1 if none.
-        //
-        // As a special hack, if flattenSigs, signatures are
-        // treated as equivalent entries of cpMap.  This is wrong
-        // from a Collection point of view, because contains()
-        // reports true for signatures, but the iterator()
-        // never produces them!
-        private int findIndexOf(Entry e) {
-            if (indexKey == null) {
-                initializeIndex();
-            }
-            int probe = findIndexLocation(e);
-            if (indexKey[probe] != e) {
-                if (flattenSigs && e.tag == CONSTANT_Signature) {
-                    SignatureEntry se = (SignatureEntry) e;
-                    return findIndexOf(se.asUtf8Entry());
-                }
-                return -1;
-            }
-            int index = indexValue[probe];
-            assert(e.equals(cpMap[index]));
-            return index;
-        }
-        public boolean contains(Entry e) {
-            return findIndexOf(e) >= 0;
-        }
-        // Find index of e in cpMap.  Should not return -1.
-        public int indexOf(Entry e) {
-            int index = findIndexOf(e);
-            if (index < 0 && verbose() > 0) {
-                System.out.println("not found: "+e);
-                System.out.println("       in: "+this.dumpString());
-                Thread.dumpStack();
-            }
-            assert(index >= 0);
-            return index;
-        }
-        public int lastIndexOf(Entry e) {
-            return indexOf(e);
-        }
-
-        public boolean assertIsSorted() {
-            for (int i = 1; i < cpMap.length; i++) {
-                if (cpMap[i-1].compareTo(cpMap[i]) > 0) {
-                    System.out.println("Not sorted at "+(i-1)+"/"+i+": "+this.dumpString());
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        // internal hash table
-        protected Entry[] indexKey;
-        protected int[]   indexValue;
-        protected void clearIndex() {
-            indexKey   = null;
-            indexValue = null;
-        }
-        private int findIndexLocation(Entry e) {
-            int size   = indexKey.length;
-            int hash   = e.hashCode();
-            int probe  = hash & (size - 1);
-            int stride = ((hash >>> 8) | 1) & (size - 1);
-            for (;;) {
-                Entry e1 = indexKey[probe];
-                if (e1 == e || e1 == null)
-                    return probe;
-                probe += stride;
-                if (probe >= size)  probe -= size;
-            }
-        }
-        private void initializeIndex() {
-            if (verbose() > 2)
-                System.out.println("initialize Index "+debugName+" ["+size()+"]");
-            int hsize0 = (int)((cpMap.length + 10) * 1.5);
-            int hsize = 1;
-            while (hsize < hsize0) {
-                hsize <<= 1;
-            }
-            indexKey   = new Entry[hsize];
-            indexValue = new int[hsize];
-            for (int i = 0; i < cpMap.length; i++) {
-                Entry e = cpMap[i];
-                if (e == null)  continue;
-                int probe = findIndexLocation(e);
-                assert(indexKey[probe] == null);  // e has unique index
-                indexKey[probe] = e;
-                indexValue[probe] = i;
-            }
-        }
-        public Entry[] toArray(Entry[] a) {
-            int sz = size();
-            if (a.length < sz)  return super.toArray(a);
-            System.arraycopy(cpMap, 0, a, 0, sz);
-            if (a.length > sz)  a[sz] = null;
-            return a;
-        }
-        public Entry[] toArray() {
-            return toArray(new Entry[size()]);
-        }
-        public Object clone() {
-            return new Index(debugName, cpMap.clone());
-        }
-        public String toString() {
-            return "Index "+debugName+" ["+size()+"]";
-        }
-        public String dumpString() {
-            String s = toString();
-            s += " {\n";
-            for (int i = 0; i < cpMap.length; i++) {
-                s += "    "+i+": "+cpMap[i]+"\n";
-            }
-            s += "}";
-            return s;
-        }
-    }
-
-    // Index methods.
-
-    public static
-    Index makeIndex(String debugName, Entry[] cpMap) {
-        return new Index(debugName, cpMap);
-    }
-
-    public static
-    Index makeIndex(String debugName, Collection cpMapList) {
-        return new Index(debugName, cpMapList);
-    }
-
-    /** Sort this index (destructively) into canonical order. */
-    public static
-    void sort(Index ix) {
-        // %%% Should move this into class Index.
-        ix.clearIndex();
-        Arrays.sort(ix.cpMap);
-        if (verbose() > 2)
-            System.out.println("sorted "+ix.dumpString());
-    }
-
-    /** Return a set of indexes partitioning these entries.
-     *  The keys array must of length this.size(), and marks entries.
-     *  The result array is as long as one plus the largest key value.
-     *  Entries with a negative key are dropped from the partition.
-     */
-    public static
-    Index[] partition(Index ix, int[] keys) {
-        // %%% Should move this into class Index.
-        List> parts = new ArrayList<>();
-        Entry[] cpMap = ix.cpMap;
-        assert(keys.length == cpMap.length);
-        for (int i = 0; i < keys.length; i++) {
-            int key = keys[i];
-            if (key < 0)  continue;
-            while (key >= parts.size()) {
-                parts.add(null);
-            }
-            List part = parts.get(key);
-            if (part == null) {
-                parts.set(key, part = new ArrayList<>());
-            }
-            part.add(cpMap[i]);
-        }
-        Index[] indexes = new Index[parts.size()];
-        for (int key = 0; key < indexes.length; key++) {
-            List part = parts.get(key);
-            if (part == null)  continue;
-            indexes[key] = new Index(ix.debugName+"/part#"+key, part);
-            assert(indexes[key].indexOf(part.get(0)) == 0);
-        }
-        return indexes;
-    }
-    public static
-    Index[] partitionByTag(Index ix) {
-        // Partition by tag.
-        Entry[] cpMap = ix.cpMap;
-        int[] keys = new int[cpMap.length];
-        for (int i = 0; i < keys.length; i++) {
-            Entry e = cpMap[i];
-            keys[i] = (e == null)? -1: e.tag;
-        }
-        Index[] byTag = partition(ix, keys);
-        for (int tag = 0; tag < byTag.length; tag++) {
-            if (byTag[tag] == null)  continue;
-            byTag[tag].debugName = tagName(tag);
-        }
-        if (byTag.length < CONSTANT_Limit) {
-            Index[] longer = new Index[CONSTANT_Limit];
-            System.arraycopy(byTag, 0, longer, 0, byTag.length);
-            byTag = longer;
-        }
-        return byTag;
-    }
-
-    /** Coherent group of constant pool indexes. */
-    public static
-    class IndexGroup {
-        private Index[] indexByTag = new Index[CONSTANT_Limit];
-        private Index[] indexByTagGroup;
-        private int[]   untypedFirstIndexByTag;
-        private int     totalSizeQQ;
-        private Index[][] indexByTagAndClass;
-
-        /** Index of all CP entries of all types, in definition order. */
-        private Index makeTagGroupIndex(byte tagGroupTag, byte[] tagsInGroup) {
-            if (indexByTagGroup == null)
-                indexByTagGroup = new Index[CONSTANT_GroupLimit - CONSTANT_GroupFirst];
-            int which = tagGroupTag - CONSTANT_GroupFirst;
-            assert(indexByTagGroup[which] == null);
-            int fillp = 0;
-            Entry[] cpMap = null;
-            for (int pass = 1; pass <= 2; pass++) {
-                untypedIndexOf(null);  // warm up untypedFirstIndexByTag
-                for (byte tag : tagsInGroup) {
-                    Index ix = indexByTag[tag];
-                    if (ix == null)  continue;
-                    int ixLen = ix.cpMap.length;
-                    if (ixLen == 0)  continue;
-                    assert(tagGroupTag == CONSTANT_All
-                            ? fillp == untypedFirstIndexByTag[tag]
-                            : fillp  < untypedFirstIndexByTag[tag]);
-                    if (cpMap != null) {
-                        assert(cpMap[fillp] == null);
-                        assert(cpMap[fillp+ixLen-1] == null);
-                        System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen);
-                    }
-                    fillp += ixLen;
-                }
-                if (cpMap == null) {
-                    assert(pass == 1);
-                    // get ready for pass 2
-                    cpMap = new Entry[fillp];
-                    fillp = 0;
-                }
-            }
-            indexByTagGroup[which] = new Index(tagName(tagGroupTag), cpMap);
-            return indexByTagGroup[which];
-        }
-
-        public int untypedIndexOf(Entry e) {
-            if (untypedFirstIndexByTag == null) {
-                untypedFirstIndexByTag = new int[CONSTANT_Limit+1];
-                int fillp = 0;
-                for (int i = 0; i < TAGS_IN_ORDER.length; i++) {
-                    byte tag = TAGS_IN_ORDER[i];
-                    Index ix = indexByTag[tag];
-                    if (ix == null)  continue;
-                    int ixLen = ix.cpMap.length;
-                    untypedFirstIndexByTag[tag] = fillp;
-                    fillp += ixLen;
-                }
-                untypedFirstIndexByTag[CONSTANT_Limit] = fillp;
-            }
-            if (e == null)  return -1;
-            int tag = e.tag;
-            Index ix = indexByTag[tag];
-            if (ix == null)  return -1;
-            int idx = ix.findIndexOf(e);
-            if (idx >= 0)
-                idx += untypedFirstIndexByTag[tag];
-            return idx;
-        }
-
-        public void initIndexByTag(byte tag, Index ix) {
-            assert(indexByTag[tag] == null);  // do not init twice
-            Entry[] cpMap = ix.cpMap;
-            for (int i = 0; i < cpMap.length; i++) {
-                // It must be a homogeneous Entry set.
-                assert(cpMap[i].tag == tag);
-            }
-            if (tag == CONSTANT_Utf8) {
-                // Special case:  First Utf8 must always be empty string.
-                assert(cpMap.length == 0 || cpMap[0].stringValue().isEmpty());
-            }
-            indexByTag[tag] = ix;
-            // decache indexes derived from this one:
-            untypedFirstIndexByTag = null;
-            indexByTagGroup = null;
-            if (indexByTagAndClass != null)
-                indexByTagAndClass[tag] = null;
-        }
-
-        /** Index of all CP entries of a given tag. */
-        public Index getIndexByTag(byte tag) {
-            if (tag >= CONSTANT_GroupFirst)
-                return getIndexByTagGroup(tag);
-            Index ix = indexByTag[tag];
-            if (ix == null) {
-                // Make an empty one by default.
-                ix = new Index(tagName(tag), new Entry[0]);
-                indexByTag[tag] = ix;
-            }
-            return ix;
-        }
-
-        private Index getIndexByTagGroup(byte tag) {
-            // pool groups:
-            if (indexByTagGroup != null) {
-                Index ix = indexByTagGroup[tag - CONSTANT_GroupFirst];
-                if (ix != null)  return ix;
-            }
-            switch (tag) {
-            case CONSTANT_All:
-                return makeTagGroupIndex(CONSTANT_All, TAGS_IN_ORDER);
-            case CONSTANT_LoadableValue:
-                    return makeTagGroupIndex(CONSTANT_LoadableValue, LOADABLE_VALUE_TAGS);
-            case CONSTANT_AnyMember:
-                return makeTagGroupIndex(CONSTANT_AnyMember, ANY_MEMBER_TAGS);
-            case CONSTANT_FieldSpecific:
-                // This one does not have any fixed index, since it is context-specific.
-                return null;
-            }
-            throw new AssertionError("bad tag group "+tag);
-        }
-
-        /** Index of all CP entries of a given tag and class. */
-        public Index getMemberIndex(byte tag, ClassEntry classRef) {
-            if (classRef == null)
-                throw new RuntimeException("missing class reference for " + tagName(tag));
-            if (indexByTagAndClass == null)
-                indexByTagAndClass = new Index[CONSTANT_Limit][];
-            Index allClasses =  getIndexByTag(CONSTANT_Class);
-            Index[] perClassIndexes = indexByTagAndClass[tag];
-            if (perClassIndexes == null) {
-                // Create the partition now.
-                // Divide up all entries of the given tag according to their class.
-                Index allMembers = getIndexByTag(tag);
-                int[] whichClasses = new int[allMembers.size()];
-                for (int i = 0; i < whichClasses.length; i++) {
-                    MemberEntry e = (MemberEntry) allMembers.get(i);
-                    int whichClass = allClasses.indexOf(e.classRef);
-                    whichClasses[i] = whichClass;
-                }
-                perClassIndexes = partition(allMembers, whichClasses);
-                for (int i = 0; i < perClassIndexes.length; i++) {
-                    assert (perClassIndexes[i] == null ||
-                            perClassIndexes[i].assertIsSorted());
-                }
-                indexByTagAndClass[tag] = perClassIndexes;
-            }
-            int whichClass = allClasses.indexOf(classRef);
-            return perClassIndexes[whichClass];
-        }
-
-        // Given the sequence of all methods of the given name and class,
-        // produce the ordinal of this particular given overloading.
-        public int getOverloadingIndex(MemberEntry methodRef) {
-            Index ix = getMemberIndex(methodRef.tag, methodRef.classRef);
-            Utf8Entry nameRef = methodRef.descRef.nameRef;
-            int ord = 0;
-            for (int i = 0; i < ix.cpMap.length; i++) {
-                MemberEntry e = (MemberEntry) ix.cpMap[i];
-                if (e.equals(methodRef))
-                    return ord;
-                if (e.descRef.nameRef.equals(nameRef))
-                    // Found a different overloading.  Increment the ordinal.
-                    ord++;
-            }
-            throw new RuntimeException("should not reach here");
-        }
-
-        // Inverse of getOverloadingIndex
-        public MemberEntry getOverloadingForIndex(byte tag, ClassEntry classRef, String name, int which) {
-            assert(name.equals(name.intern()));
-            Index ix = getMemberIndex(tag, classRef);
-            int ord = 0;
-            for (int i = 0; i < ix.cpMap.length; i++) {
-                MemberEntry e = (MemberEntry) ix.cpMap[i];
-                if (e.descRef.nameRef.stringValue().equals(name)) {
-                    if (ord == which)  return e;
-                    ord++;
-                }
-            }
-            throw new RuntimeException("should not reach here");
-        }
-
-        public boolean haveNumbers() {
-            for (byte tag : NUMBER_TAGS) {
-                if (getIndexByTag(tag).size() > 0)  return true;
-            }
-            return false;
-        }
-
-        public boolean haveExtraTags() {
-            for (byte tag : EXTRA_TAGS) {
-                if (getIndexByTag(tag).size() > 0)  return true;
-            }
-            return false;
-        }
-
-    }
-
-    /** Close the set cpRefs under the getRef(*) relation.
-     *  Also, if flattenSigs, replace all signatures in cpRefs
-     *  by their equivalent Utf8s.
-     *  Also, discard null from cpRefs.
-     */
-    public static void completeReferencesIn(Set cpRefs, boolean flattenSigs) {
-         completeReferencesIn(cpRefs, flattenSigs, null);
-    }
-
-    public static
-    void completeReferencesIn(Set cpRefs, boolean flattenSigs,
-                              Listbsms) {
-        cpRefs.remove(null);
-        for (ListIterator work =
-                 new ArrayList<>(cpRefs).listIterator(cpRefs.size());
-             work.hasPrevious(); ) {
-            Entry e = work.previous();
-            work.remove();          // pop stack
-            assert(e != null);
-            if (flattenSigs && e.tag == CONSTANT_Signature) {
-                SignatureEntry se = (SignatureEntry) e;
-                Utf8Entry      ue = se.asUtf8Entry();
-                // Totally replace e by se.
-                cpRefs.remove(se);
-                cpRefs.add(ue);
-                e = ue;   // do not descend into the sig
-            }
-            if (bsms != null && e.tag == CONSTANT_BootstrapMethod) {
-                BootstrapMethodEntry bsm = (BootstrapMethodEntry)e;
-                cpRefs.remove(bsm);
-                // move it away to the side table where it belongs
-                if (!bsms.contains(bsm))
-                    bsms.add(bsm);
-                // fall through to recursively add refs for this entry
-            }
-            // Recursively add the refs of e to cpRefs:
-            for (int i = 0; ; i++) {
-                Entry re = e.getRef(i);
-                if (re == null)
-                    break;          // no more refs in e
-                if (cpRefs.add(re)) // output the ref
-                    work.add(re);   // push stack, if a new ref
-            }
-        }
-    }
-
-    static double percent(int num, int den) {
-        return (int)((10000.0*num)/den + 0.5) / 100.0;
-    }
-
-    public static String tagName(int tag) {
-        switch (tag) {
-            case CONSTANT_Utf8:                 return "Utf8";
-            case CONSTANT_Integer:              return "Integer";
-            case CONSTANT_Float:                return "Float";
-            case CONSTANT_Long:                 return "Long";
-            case CONSTANT_Double:               return "Double";
-            case CONSTANT_Class:                return "Class";
-            case CONSTANT_String:               return "String";
-            case CONSTANT_Fieldref:             return "Fieldref";
-            case CONSTANT_Methodref:            return "Methodref";
-            case CONSTANT_InterfaceMethodref:   return "InterfaceMethodref";
-            case CONSTANT_NameandType:          return "NameandType";
-            case CONSTANT_MethodHandle:         return "MethodHandle";
-            case CONSTANT_MethodType:           return "MethodType";
-            case CONSTANT_InvokeDynamic:        return "InvokeDynamic";
-
-                // pseudo-tags:
-            case CONSTANT_All:                  return "**All";
-            case CONSTANT_None:                 return "**None";
-            case CONSTANT_LoadableValue:        return "**LoadableValue";
-            case CONSTANT_AnyMember:            return "**AnyMember";
-            case CONSTANT_FieldSpecific:        return "*FieldSpecific";
-            case CONSTANT_Signature:            return "*Signature";
-            case CONSTANT_BootstrapMethod:      return "*BootstrapMethod";
-        }
-        return "tag#"+tag;
-    }
-
-    public static String refKindName(int refKind) {
-        switch (refKind) {
-            case REF_getField:                  return "getField";
-            case REF_getStatic:                 return "getStatic";
-            case REF_putField:                  return "putField";
-            case REF_putStatic:                 return "putStatic";
-            case REF_invokeVirtual:             return "invokeVirtual";
-            case REF_invokeStatic:              return "invokeStatic";
-            case REF_invokeSpecial:             return "invokeSpecial";
-            case REF_newInvokeSpecial:          return "newInvokeSpecial";
-            case REF_invokeInterface:           return "invokeInterface";
-        }
-        return "refKind#"+refKind;
-    }
-
-    // archive constant pool definition order
-    static final byte TAGS_IN_ORDER[] = {
-        CONSTANT_Utf8,
-        CONSTANT_Integer,           // cp_Int
-        CONSTANT_Float,
-        CONSTANT_Long,
-        CONSTANT_Double,
-        CONSTANT_String,            // note that String=8 precedes Class=7
-        CONSTANT_Class,
-        CONSTANT_Signature,
-        CONSTANT_NameandType,       // cp_Descr
-        CONSTANT_Fieldref,          // cp_Field
-        CONSTANT_Methodref,         // cp_Method
-        CONSTANT_InterfaceMethodref, // cp_Imethod
-
-        // Constants defined in JDK 7 and later:
-        CONSTANT_MethodHandle,
-        CONSTANT_MethodType,
-        CONSTANT_BootstrapMethod,  // pseudo-tag, really stored in a class attribute
-        CONSTANT_InvokeDynamic
-    };
-    static final byte TAG_ORDER[];
-    static {
-        TAG_ORDER = new byte[CONSTANT_Limit];
-        for (int i = 0; i < TAGS_IN_ORDER.length; i++) {
-            TAG_ORDER[TAGS_IN_ORDER[i]] = (byte)(i+1);
-        }
-        /*
-        System.out.println("TAG_ORDER[] = {");
-        for (int i = 0; i < TAG_ORDER.length; i++)
-            System.out.println("  "+TAG_ORDER[i]+",");
-        System.out.println("};");
-        */
-    }
-    static final byte[] NUMBER_TAGS = {
-        CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double
-    };
-    static final byte[] EXTRA_TAGS = {
-        CONSTANT_MethodHandle, CONSTANT_MethodType,
-        CONSTANT_BootstrapMethod, // pseudo-tag
-        CONSTANT_InvokeDynamic
-    };
-    static final byte[] LOADABLE_VALUE_TAGS = { // for CONSTANT_LoadableValue
-        CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double,
-        CONSTANT_String, CONSTANT_Class,
-        CONSTANT_MethodHandle, CONSTANT_MethodType
-    };
-    static final byte[] ANY_MEMBER_TAGS = { // for CONSTANT_AnyMember
-        CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref
-    };
-    static final byte[] FIELD_SPECIFIC_TAGS = { // for CONSTANT_FieldSpecific
-        CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double,
-        CONSTANT_String
-    };
-    static {
-        assert(
-            verifyTagOrder(TAGS_IN_ORDER) &&
-            verifyTagOrder(NUMBER_TAGS) &&
-            verifyTagOrder(EXTRA_TAGS) &&
-            verifyTagOrder(LOADABLE_VALUE_TAGS) &&
-            verifyTagOrder(ANY_MEMBER_TAGS) &&
-            verifyTagOrder(FIELD_SPECIFIC_TAGS)
-        );
-    }
-    private static boolean verifyTagOrder(byte[] tags) {
-        int prev = -1;
-        for (byte tag : tags) {
-            int next = TAG_ORDER[tag];
-            assert(next > 0) : "tag not found: "+tag;
-            assert(TAGS_IN_ORDER[next-1] == tag) : "tag repeated: "+tag+" => "+next+" => "+TAGS_IN_ORDER[next-1];
-            assert(prev < next) : "tags not in order: "+Arrays.toString(tags)+" at "+tag;
-            prev = next;
-        }
-        return true;
-    }
-}
diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java
deleted file mode 100644
index 3cef47ae5d6..00000000000
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Constants.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.java.util.jar.pack;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Shared constants
- * @author John Rose
- */
-class Constants {
-
-    private Constants(){}
-
-    public static final int JAVA_MAGIC = 0xCAFEBABE;
-
-    /*
-        Java Class Version numbers history
-        1.0 to 1.3.X 45,3
-        1.4 to 1.4.X 46,0
-        1.5 to 1.5.X 49,0
-        1.6 to 1.6.X 50,0
-        1.7 to 1.7.X 51,0
-        1.8 to 1.8.X 52,0
-        1.9 to 1.9.X 53,0
-        1.10 to 1.10.X 54,0
-        1.11 to 1.11.X 55,0
-        1.12 to 1.12.X 56,0
-        1.13 to 1.13.X 57,0
-        1.14 to 1.14.X 58,0
-    */
-
-    public static final Package.Version JAVA_MIN_CLASS_VERSION =
-            Package.Version.of(45, 03);
-
-    public static final Package.Version JAVA5_MAX_CLASS_VERSION =
-            Package.Version.of(49, 00);
-
-    public static final Package.Version JAVA6_MAX_CLASS_VERSION =
-            Package.Version.of(50, 00);
-
-    public static final Package.Version JAVA7_MAX_CLASS_VERSION =
-            Package.Version.of(51, 00);
-
-    public static final Package.Version JAVA8_MAX_CLASS_VERSION =
-            Package.Version.of(52, 00);
-
-    public static final Package.Version JAVA9_MAX_CLASS_VERSION =
-            Package.Version.of(53, 00);
-
-    public static final Package.Version JAVA10_MAX_CLASS_VERSION =
-            Package.Version.of(54, 00);
-
-    public static final Package.Version JAVA11_MAX_CLASS_VERSION =
-            Package.Version.of(55, 00);
-
-    public static final Package.Version JAVA12_MAX_CLASS_VERSION =
-            Package.Version.of(56, 00);
-
-    public static final Package.Version JAVA13_MAX_CLASS_VERSION =
-            Package.Version.of(57, 00);
-
-    public static final Package.Version JAVA14_MAX_CLASS_VERSION =
-            Package.Version.of(58, 00);
-
-    public static final int JAVA_PACKAGE_MAGIC = 0xCAFED00D;
-
-    public static final Package.Version JAVA5_PACKAGE_VERSION =
-            Package.Version.of(150, 7);
-
-    public static final Package.Version JAVA6_PACKAGE_VERSION =
-            Package.Version.of(160, 1);
-
-    public static final Package.Version JAVA7_PACKAGE_VERSION =
-            Package.Version.of(170, 1);
-
-    public static final Package.Version JAVA8_PACKAGE_VERSION =
-            Package.Version.of(171, 0);
-
-    // upper limit, should point to the latest class version
-    public static final Package.Version JAVA_MAX_CLASS_VERSION =
-            JAVA13_MAX_CLASS_VERSION;
-
-    // upper limit should point to the latest package version, for version info!.
-    public static final Package.Version MAX_PACKAGE_VERSION =
-            JAVA7_PACKAGE_VERSION;
-
-    public static final int CONSTANT_POOL_INDEX_LIMIT  = 0x10000;
-    public static final int CONSTANT_POOL_NARROW_LIMIT = 0x00100;
-
-    public static final String JAVA_SIGNATURE_CHARS = "BSCIJFDZLV([";
-
-    public static final byte CONSTANT_Utf8 = 1;
-    public static final byte CONSTANT_unused2 = 2;  // unused, was Unicode
-    public static final byte CONSTANT_Integer = 3;
-    public static final byte CONSTANT_Float = 4;
-    public static final byte CONSTANT_Long = 5;
-    public static final byte CONSTANT_Double = 6;
-    public static final byte CONSTANT_Class = 7;
-    public static final byte CONSTANT_String = 8;
-    public static final byte CONSTANT_Fieldref = 9;
-    public static final byte CONSTANT_Methodref = 10;
-    public static final byte CONSTANT_InterfaceMethodref = 11;
-    public static final byte CONSTANT_NameandType = 12;
-    public static final byte CONSTANT_unused13 = 13;
-    public static final byte CONSTANT_unused14 = 14;
-    public static final byte CONSTANT_MethodHandle = 15;
-    public static final byte CONSTANT_MethodType = 16;
-    public static final byte CONSTANT_unused17 = 17;  // unused
-    public static final byte CONSTANT_InvokeDynamic = 18;
-
-    // pseudo-constants:
-    public static final byte CONSTANT_None = 0;
-    public static final byte CONSTANT_Signature = CONSTANT_unused13;
-    public static final byte CONSTANT_BootstrapMethod = CONSTANT_unused17; // used only in InvokeDynamic constants
-    public static final byte CONSTANT_Limit = 19;
-
-    public static final byte CONSTANT_All = 50;  // combined global map
-    public static final byte CONSTANT_LoadableValue = 51; // used for 'KL' and qldc operands
-    public static final byte CONSTANT_AnyMember = 52; // union of refs to field or (interface) method
-    public static final byte CONSTANT_FieldSpecific = 53; // used only for 'KQ' ConstantValue attrs
-    public static final byte CONSTANT_GroupFirst = CONSTANT_All;
-    public static final byte CONSTANT_GroupLimit = CONSTANT_FieldSpecific+1;
-
-    // CONSTANT_MethodHandle reference kinds
-    public static final byte REF_getField = 1;
-    public static final byte REF_getStatic = 2;
-    public static final byte REF_putField = 3;
-    public static final byte REF_putStatic = 4;
-    public static final byte REF_invokeVirtual = 5;
-    public static final byte REF_invokeStatic = 6;
-    public static final byte REF_invokeSpecial = 7;
-    public static final byte REF_newInvokeSpecial = 8;
-    public static final byte REF_invokeInterface = 9;
-
-    // pseudo-access bits
-    public static final int ACC_IC_LONG_FORM   = (1<<16); //for ic_flags
-
-    // attribute "context types"
-    public static final int ATTR_CONTEXT_CLASS  = 0;
-    public static final int ATTR_CONTEXT_FIELD  = 1;
-    public static final int ATTR_CONTEXT_METHOD = 2;
-    public static final int ATTR_CONTEXT_CODE   = 3;
-    public static final int ATTR_CONTEXT_LIMIT  = 4;
-    public static final String[] ATTR_CONTEXT_NAME
-        = { "class", "field", "method", "code" };
-
-    // predefined attr bits
-    public static final int
-        X_ATTR_OVERFLOW = 16,
-        CLASS_ATTR_SourceFile = 17,
-        METHOD_ATTR_Code = 17,
-        FIELD_ATTR_ConstantValue = 17,
-        CLASS_ATTR_EnclosingMethod = 18,
-        METHOD_ATTR_Exceptions = 18,
-        X_ATTR_Signature = 19,
-        X_ATTR_Deprecated = 20,
-        X_ATTR_RuntimeVisibleAnnotations = 21,
-        X_ATTR_RuntimeInvisibleAnnotations = 22,
-        METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
-        CLASS_ATTR_InnerClasses = 23,
-        METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
-        CLASS_ATTR_ClassFile_version = 24,
-        METHOD_ATTR_AnnotationDefault = 25,
-        METHOD_ATTR_MethodParameters = 26,           // JDK8
-        X_ATTR_RuntimeVisibleTypeAnnotations = 27,   // JDK8
-        X_ATTR_RuntimeInvisibleTypeAnnotations = 28, // JDK8
-        CODE_ATTR_StackMapTable = 0,  // new in Java 6
-        CODE_ATTR_LineNumberTable = 1,
-        CODE_ATTR_LocalVariableTable = 2,
-        CODE_ATTR_LocalVariableTypeTable = 3;
-
-    // File option bits, from LSB in ascending bit position.
-    public static final int FO_DEFLATE_HINT           = 1<<0;
-    public static final int FO_IS_CLASS_STUB          = 1<<1;
-
-    // Archive option bits, from LSB in ascending bit position:
-    public static final int AO_HAVE_SPECIAL_FORMATS   = 1<<0;
-    public static final int AO_HAVE_CP_NUMBERS        = 1<<1;
-    public static final int AO_HAVE_ALL_CODE_FLAGS    = 1<<2;
-    public static final int AO_HAVE_CP_EXTRAS         = 1<<3;
-    public static final int AO_HAVE_FILE_HEADERS      = 1<<4;
-    public static final int AO_DEFLATE_HINT           = 1<<5;
-    public static final int AO_HAVE_FILE_MODTIME      = 1<<6;
-    public static final int AO_HAVE_FILE_OPTIONS      = 1<<7;
-    public static final int AO_HAVE_FILE_SIZE_HI      = 1<<8;
-    public static final int AO_HAVE_CLASS_FLAGS_HI    = 1<<9;
-    public static final int AO_HAVE_FIELD_FLAGS_HI    = 1<<10;
-    public static final int AO_HAVE_METHOD_FLAGS_HI   = 1<<11;
-    public static final int AO_HAVE_CODE_FLAGS_HI     = 1<<12;
-    public static final int AO_UNUSED_MBZ          = (-1)<<13;  // option bits reserved for future use
-
-    public static final int LG_AO_HAVE_XXX_FLAGS_HI   = 9;
-
-    // visitRefs modes:
-    static final int VRM_CLASSIC = 0;
-    static final int VRM_PACKAGE = 1;
-
-    public static final int NO_MODTIME = 0;  // null modtime value
-
-    // some comstantly empty containers
-    public static final int[]        noInts = {};
-    public static final byte[]       noBytes = {};
-    public static final Object[]     noValues = {};
-    public static final String[]     noStrings = {};
-    public static final List emptyList = Arrays.asList(noValues);
-
-    // meta-coding
-    public static final int
-        _meta_default = 0,
-        _meta_canon_min = 1,
-        _meta_canon_max = 115,
-        _meta_arb = 116,
-        _meta_run = 117,
-        _meta_pop = 141,
-        _meta_limit = 189;
-
-    // bytecodes
-    public static final int
-        _nop                  =   0, // 0x00
-        _aconst_null          =   1, // 0x01
-        _iconst_m1            =   2, // 0x02
-        _iconst_0             =   3, // 0x03
-        _iconst_1             =   4, // 0x04
-        _iconst_2             =   5, // 0x05
-        _iconst_3             =   6, // 0x06
-        _iconst_4             =   7, // 0x07
-        _iconst_5             =   8, // 0x08
-        _lconst_0             =   9, // 0x09
-        _lconst_1             =  10, // 0x0a
-        _fconst_0             =  11, // 0x0b
-        _fconst_1             =  12, // 0x0c
-        _fconst_2             =  13, // 0x0d
-        _dconst_0             =  14, // 0x0e
-        _dconst_1             =  15, // 0x0f
-        _bipush               =  16, // 0x10
-        _sipush               =  17, // 0x11
-        _ldc                  =  18, // 0x12
-        _ldc_w                =  19, // 0x13
-        _ldc2_w               =  20, // 0x14
-        _iload                =  21, // 0x15
-        _lload                =  22, // 0x16
-        _fload                =  23, // 0x17
-        _dload                =  24, // 0x18
-        _aload                =  25, // 0x19
-        _iload_0              =  26, // 0x1a
-        _iload_1              =  27, // 0x1b
-        _iload_2              =  28, // 0x1c
-        _iload_3              =  29, // 0x1d
-        _lload_0              =  30, // 0x1e
-        _lload_1              =  31, // 0x1f
-        _lload_2              =  32, // 0x20
-        _lload_3              =  33, // 0x21
-        _fload_0              =  34, // 0x22
-        _fload_1              =  35, // 0x23
-        _fload_2              =  36, // 0x24
-        _fload_3              =  37, // 0x25
-        _dload_0              =  38, // 0x26
-        _dload_1              =  39, // 0x27
-        _dload_2              =  40, // 0x28
-        _dload_3              =  41, // 0x29
-        _aload_0              =  42, // 0x2a
-        _aload_1              =  43, // 0x2b
-        _aload_2              =  44, // 0x2c
-        _aload_3              =  45, // 0x2d
-        _iaload               =  46, // 0x2e
-        _laload               =  47, // 0x2f
-        _faload               =  48, // 0x30
-        _daload               =  49, // 0x31
-        _aaload               =  50, // 0x32
-        _baload               =  51, // 0x33
-        _caload               =  52, // 0x34
-        _saload               =  53, // 0x35
-        _istore               =  54, // 0x36
-        _lstore               =  55, // 0x37
-        _fstore               =  56, // 0x38
-        _dstore               =  57, // 0x39
-        _astore               =  58, // 0x3a
-        _istore_0             =  59, // 0x3b
-        _istore_1             =  60, // 0x3c
-        _istore_2             =  61, // 0x3d
-        _istore_3             =  62, // 0x3e
-        _lstore_0             =  63, // 0x3f
-        _lstore_1             =  64, // 0x40
-        _lstore_2             =  65, // 0x41
-        _lstore_3             =  66, // 0x42
-        _fstore_0             =  67, // 0x43
-        _fstore_1             =  68, // 0x44
-        _fstore_2             =  69, // 0x45
-        _fstore_3             =  70, // 0x46
-        _dstore_0             =  71, // 0x47
-        _dstore_1             =  72, // 0x48
-        _dstore_2             =  73, // 0x49
-        _dstore_3             =  74, // 0x4a
-        _astore_0             =  75, // 0x4b
-        _astore_1             =  76, // 0x4c
-        _astore_2             =  77, // 0x4d
-        _astore_3             =  78, // 0x4e
-        _iastore              =  79, // 0x4f
-        _lastore              =  80, // 0x50
-        _fastore              =  81, // 0x51
-        _dastore              =  82, // 0x52
-        _aastore              =  83, // 0x53
-        _bastore              =  84, // 0x54
-        _castore              =  85, // 0x55
-        _sastore              =  86, // 0x56
-        _pop                  =  87, // 0x57
-        _pop2                 =  88, // 0x58
-        _dup                  =  89, // 0x59
-        _dup_x1               =  90, // 0x5a
-        _dup_x2               =  91, // 0x5b
-        _dup2                 =  92, // 0x5c
-        _dup2_x1              =  93, // 0x5d
-        _dup2_x2              =  94, // 0x5e
-        _swap                 =  95, // 0x5f
-        _iadd                 =  96, // 0x60
-        _ladd                 =  97, // 0x61
-        _fadd                 =  98, // 0x62
-        _dadd                 =  99, // 0x63
-        _isub                 = 100, // 0x64
-        _lsub                 = 101, // 0x65
-        _fsub                 = 102, // 0x66
-        _dsub                 = 103, // 0x67
-        _imul                 = 104, // 0x68
-        _lmul                 = 105, // 0x69
-        _fmul                 = 106, // 0x6a
-        _dmul                 = 107, // 0x6b
-        _idiv                 = 108, // 0x6c
-        _ldiv                 = 109, // 0x6d
-        _fdiv                 = 110, // 0x6e
-        _ddiv                 = 111, // 0x6f
-        _irem                 = 112, // 0x70
-        _lrem                 = 113, // 0x71
-        _frem                 = 114, // 0x72
-        _drem                 = 115, // 0x73
-        _ineg                 = 116, // 0x74
-        _lneg                 = 117, // 0x75
-        _fneg                 = 118, // 0x76
-        _dneg                 = 119, // 0x77
-        _ishl                 = 120, // 0x78
-        _lshl                 = 121, // 0x79
-        _ishr                 = 122, // 0x7a
-        _lshr                 = 123, // 0x7b
-        _iushr                = 124, // 0x7c
-        _lushr                = 125, // 0x7d
-        _iand                 = 126, // 0x7e
-        _land                 = 127, // 0x7f
-        _ior                  = 128, // 0x80
-        _lor                  = 129, // 0x81
-        _ixor                 = 130, // 0x82
-        _lxor                 = 131, // 0x83
-        _iinc                 = 132, // 0x84
-        _i2l                  = 133, // 0x85
-        _i2f                  = 134, // 0x86
-        _i2d                  = 135, // 0x87
-        _l2i                  = 136, // 0x88
-        _l2f                  = 137, // 0x89
-        _l2d                  = 138, // 0x8a
-        _f2i                  = 139, // 0x8b
-        _f2l                  = 140, // 0x8c
-        _f2d                  = 141, // 0x8d
-        _d2i                  = 142, // 0x8e
-        _d2l                  = 143, // 0x8f
-        _d2f                  = 144, // 0x90
-        _i2b                  = 145, // 0x91
-        _i2c                  = 146, // 0x92
-        _i2s                  = 147, // 0x93
-        _lcmp                 = 148, // 0x94
-        _fcmpl                = 149, // 0x95
-        _fcmpg                = 150, // 0x96
-        _dcmpl                = 151, // 0x97
-        _dcmpg                = 152, // 0x98
-        _ifeq                 = 153, // 0x99
-        _ifne                 = 154, // 0x9a
-        _iflt                 = 155, // 0x9b
-        _ifge                 = 156, // 0x9c
-        _ifgt                 = 157, // 0x9d
-        _ifle                 = 158, // 0x9e
-        _if_icmpeq            = 159, // 0x9f
-        _if_icmpne            = 160, // 0xa0
-        _if_icmplt            = 161, // 0xa1
-        _if_icmpge            = 162, // 0xa2
-        _if_icmpgt            = 163, // 0xa3
-        _if_icmple            = 164, // 0xa4
-        _if_acmpeq            = 165, // 0xa5
-        _if_acmpne            = 166, // 0xa6
-        _goto                 = 167, // 0xa7
-        _jsr                  = 168, // 0xa8
-        _ret                  = 169, // 0xa9
-        _tableswitch          = 170, // 0xaa
-        _lookupswitch         = 171, // 0xab
-        _ireturn              = 172, // 0xac
-        _lreturn              = 173, // 0xad
-        _freturn              = 174, // 0xae
-        _dreturn              = 175, // 0xaf
-        _areturn              = 176, // 0xb0
-        _return               = 177, // 0xb1
-        _getstatic            = 178, // 0xb2
-        _putstatic            = 179, // 0xb3
-        _getfield             = 180, // 0xb4
-        _putfield             = 181, // 0xb5
-        _invokevirtual        = 182, // 0xb6
-        _invokespecial        = 183, // 0xb7
-        _invokestatic         = 184, // 0xb8
-        _invokeinterface      = 185, // 0xb9
-        _invokedynamic        = 186, // 0xba
-        _new                  = 187, // 0xbb
-        _newarray             = 188, // 0xbc
-        _anewarray            = 189, // 0xbd
-        _arraylength          = 190, // 0xbe
-        _athrow               = 191, // 0xbf
-        _checkcast            = 192, // 0xc0
-        _instanceof           = 193, // 0xc1
-        _monitorenter         = 194, // 0xc2
-        _monitorexit          = 195, // 0xc3
-        _wide                 = 196, // 0xc4
-        _multianewarray       = 197, // 0xc5
-        _ifnull               = 198, // 0xc6
-        _ifnonnull            = 199, // 0xc7
-        _goto_w               = 200, // 0xc8
-        _jsr_w                = 201, // 0xc9
-        _bytecode_limit       = 202; // 0xca
-
-    // End marker, used to terminate bytecode sequences:
-    public static final int _end_marker = 255;
-    // Escapes:
-    public static final int _byte_escape = 254;
-    public static final int _ref_escape = 253;
-
-    // Self-relative pseudo-opcodes for better compression.
-    // A "linker op" is a bytecode which links to a class member.
-    // (But in what follows, "invokeinterface" ops are excluded.)
-    //
-    // A "self linker op" is a variant bytecode which works only
-    // with the current class or its super.  Because the number of
-    // possible targets is small, it admits a more compact encoding.
-    // Self linker ops are allowed to absorb a previous "aload_0" op.
-    // There are (7 * 4) self linker ops (super or not, aload_0 or not).
-    //
-    // For simplicity, we define the full symmetric set of variants.
-    // However, some of them are relatively useless.
-    // Self linker ops are enabled by Pack.selfCallVariants (true).
-    public static final int _first_linker_op = _getstatic;
-    public static final int _last_linker_op  = _invokestatic;
-    public static final int _num_linker_ops  = (_last_linker_op - _first_linker_op) + 1;
-    public static final int _self_linker_op  = _bytecode_limit;
-    public static final int _self_linker_aload_flag = 1*_num_linker_ops;
-    public static final int _self_linker_super_flag = 2*_num_linker_ops;
-    public static final int _self_linker_limit = _self_linker_op + 4*_num_linker_ops;
-    // An "invoke init" op is a variant of invokespecial which works
-    // only with the method name "".  There are variants which
-    // link to the current class, the super class, or the class of the
-    // immediately previous "newinstance" op.  There are 3 of these ops.
-    // They all take method signature references as operands.
-    // Invoke init ops are enabled by Pack.initCallVariants (true).
-    public static final int _invokeinit_op = _self_linker_limit;
-    public static final int _invokeinit_self_option = 0;
-    public static final int _invokeinit_super_option = 1;
-    public static final int _invokeinit_new_option = 2;
-    public static final int _invokeinit_limit = _invokeinit_op+3;
-
-    public static final int _pseudo_instruction_limit = _invokeinit_limit;
-    // linker variant limit == 202+(7*4)+3 == 233
-
-    // Ldc variants support strongly typed references to constants.
-    // This lets us index constant pool entries completely according to tag,
-    // which is a great simplification.
-    // Ldc variants gain us only 0.007% improvement in compression ratio,
-    // but they simplify the file format greatly.
-    public static final int _xldc_op = _invokeinit_limit;
-    public static final int _sldc = _ldc;  // previously named _aldc
-    public static final int _cldc = _xldc_op+0;
-    public static final int _ildc = _xldc_op+1;
-    public static final int _fldc = _xldc_op+2;
-    public static final int _sldc_w = _ldc_w;  // previously named _aldc_w
-    public static final int _cldc_w = _xldc_op+3;
-    public static final int _ildc_w = _xldc_op+4;
-    public static final int _fldc_w = _xldc_op+5;
-    public static final int _lldc2_w = _ldc2_w;
-    public static final int _dldc2_w = _xldc_op+6;
-    // anything other than primitive, string, or class must be handled with qldc:
-    public static final int _qldc   = _xldc_op+7;
-    public static final int _qldc_w = _xldc_op+8;
-    public static final int _xldc_limit = _xldc_op+9;
-
-    // handling of InterfaceMethodRef
-    public static final int _invoke_int_op = _xldc_limit;
-    public static final int _invokespecial_int = _invoke_int_op+0;
-    public static final int _invokestatic_int = _invoke_int_op+1;
-    public static final int _invoke_int_limit = _invoke_int_op+2;
-}
diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java
deleted file mode 100644
index b9fe2147b74..00000000000
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Driver.java
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.java.util.jar.pack;
-
-import sun.nio.cs.UTF_8;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.text.MessageFormat;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Pack200;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-/** Command line interface for Pack200.
- */
-
-@SuppressWarnings({"removal"})
-class Driver {
-    private static final ResourceBundle RESOURCE =
-        ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource");
-    private static boolean suppressDeprecateMsg = false;
-
-    public static void main(String[] ava) throws IOException {
-        List av = new ArrayList<>(Arrays.asList(ava));
-
-        boolean doPack   = true;
-        boolean doUnpack = false;
-        boolean doRepack = false;
-        boolean doZip = true;
-        suppressDeprecateMsg = av.remove("-XDsuppress-tool-removal-message");
-        String logFile = null;
-        String verboseProp = Utils.DEBUG_VERBOSE;
-
-        {
-            // Non-standard, undocumented "--unpack" switch enables unpack mode.
-            String arg0 = av.isEmpty() ? "" : av.get(0);
-            switch (arg0) {
-                case "--pack":
-                av.remove(0);
-                    break;
-                case "--unpack":
-                av.remove(0);
-                doPack = false;
-                doUnpack = true;
-                    break;
-            }
-        }
-
-        if (!suppressDeprecateMsg) {
-            printDeprecateWarning(doPack, System.out);
-        }
-
-        // Collect engine properties here:
-        Map engProps = new HashMap<>();
-        engProps.put(verboseProp, System.getProperty(verboseProp));
-
-        String optionMap;
-        String[] propTable;
-        if (doPack) {
-            optionMap = PACK200_OPTION_MAP;
-            propTable = PACK200_PROPERTY_TO_OPTION;
-        } else {
-            optionMap = UNPACK200_OPTION_MAP;
-            propTable = UNPACK200_PROPERTY_TO_OPTION;
-        }
-
-        // Collect argument properties here:
-        Map avProps = new HashMap<>();
-        try {
-            for (;;) {
-                String state = parseCommandOptions(av, optionMap, avProps);
-                // Translate command line options to Pack200 properties:
-            eachOpt:
-                for (Iterator opti = avProps.keySet().iterator();
-                     opti.hasNext(); ) {
-                    String opt = opti.next();
-                    String prop = null;
-                    for (int i = 0; i < propTable.length; i += 2) {
-                        if (opt.equals(propTable[1+i])) {
-                            prop = propTable[0+i];
-                            break;
-                        }
-                    }
-                    if (prop != null) {
-                        String val = avProps.get(opt);
-                        opti.remove();  // remove opt from avProps
-                        if (!prop.endsWith(".")) {
-                            // Normal string or boolean.
-                            if (!(opt.equals("--verbose")
-                                  || opt.endsWith("="))) {
-                                // Normal boolean; convert to T/F.
-                                boolean flag = (val != null);
-                                if (opt.startsWith("--no-"))
-                                    flag = !flag;
-                                val = flag? "true": "false";
-                            }
-                            engProps.put(prop, val);
-                        } else if (prop.contains(".attribute.")) {
-                            for (String val1 : val.split("\0")) {
-                                String[] val2 = val1.split("=", 2);
-                                engProps.put(prop+val2[0], val2[1]);
-                            }
-                        } else {
-                            // Collection property: pack.pass.file.cli.NNN
-                            int idx = 1;
-                            for (String val1 : val.split("\0")) {
-                                String prop1;
-                                do {
-                                    prop1 = prop+"cli."+(idx++);
-                                } while (engProps.containsKey(prop1));
-                                engProps.put(prop1, val1);
-                            }
-                        }
-                    }
-                }
-
-                // See if there is any other action to take.
-                if ("--config-file=".equals(state)) {
-                    String propFile = av.remove(0);
-                    Properties fileProps = new Properties();
-                    try (InputStream propIn = new FileInputStream(propFile)) {
-                        fileProps.load(propIn);
-                    }
-                    if (engProps.get(verboseProp) != null)
-                        fileProps.list(System.out);
-                    for (Map.Entry me : fileProps.entrySet()) {
-                        engProps.put((String) me.getKey(), (String) me.getValue());
-                    }
-                } else if ("--version".equals(state)) {
-                        System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION),
-                                                                Driver.class.getName(), "1.31, 07/05/05"));
-                    return;
-                } else if ("--help".equals(state)) {
-                    printUsage(doPack, true, System.out);
-                    System.exit(0);
-                    return;
-                } else {
-                    break;
-                }
-            }
-        } catch (IllegalArgumentException ee) {
-                System.err.println(MessageFormat.format(RESOURCE.getString(DriverResource.BAD_ARGUMENT), ee));
-            printUsage(doPack, false, System.err);
-            System.exit(2);
-            return;
-        }
-
-        // Deal with remaining non-engine properties:
-        for (String opt : avProps.keySet()) {
-            String val = avProps.get(opt);
-            switch (opt) {
-                case "--repack":
-                    doRepack = true;
-                    break;
-                case "--no-gzip":
-                    doZip = (val == null);
-                    break;
-                case "--log-file=":
-                    logFile = val;
-                    break;
-                default:
-                    throw new InternalError(MessageFormat.format(
-                            RESOURCE.getString(DriverResource.BAD_OPTION),
-                            opt, avProps.get(opt)));
-            }
-        }
-
-        if (logFile != null && !logFile.isEmpty()) {
-            if (logFile.equals("-")) {
-                System.setErr(System.out);
-            } else {
-                OutputStream log = new FileOutputStream(logFile);
-                //log = new BufferedOutputStream(out);
-                System.setErr(new PrintStream(log));
-            }
-        }
-
-        boolean verbose = (engProps.get(verboseProp) != null);
-
-        String packfile = "";
-        if (!av.isEmpty())
-            packfile = av.remove(0);
-
-        String jarfile = "";
-        if (!av.isEmpty())
-            jarfile = av.remove(0);
-
-        String newfile = "";  // output JAR file if --repack
-        String bakfile = "";  // temporary backup of input JAR
-        String tmpfile = "";  // temporary file to be deleted
-        if (doRepack) {
-            // The first argument is the target JAR file.
-            // (Note:  *.pac is nonstandard, but may be necessary
-            // if a host OS truncates file extensions.)
-            if (packfile.toLowerCase().endsWith(".pack") ||
-                packfile.toLowerCase().endsWith(".pac") ||
-                packfile.toLowerCase().endsWith(".gz")) {
-                System.err.println(MessageFormat.format(
-                        RESOURCE.getString(DriverResource.BAD_REPACK_OUTPUT),
-                        packfile));
-                printUsage(doPack, false, System.err);
-                System.exit(2);
-            }
-            newfile = packfile;
-            // The optional second argument is the source JAR file.
-            if (jarfile.isEmpty()) {
-                // If only one file is given, it is the only JAR.
-                // It serves as both input and output.
-                jarfile = newfile;
-            }
-            tmpfile = createTempFile(newfile, ".pack").getPath();
-            packfile = tmpfile;
-            doZip = false;  // no need to zip the temporary file
-        }
-
-        if (!av.isEmpty()
-            // Accept jarfiles ending with .jar or .zip.
-            // Accept jarfile of "-" (stdout), but only if unpacking.
-            || !(jarfile.toLowerCase().endsWith(".jar")
-                 || jarfile.toLowerCase().endsWith(".zip")
-                 || (jarfile.equals("-") && !doPack))) {
-            printUsage(doPack, false, System.err);
-            System.exit(2);
-            return;
-        }
-
-        if (doRepack)
-            doPack = doUnpack = true;
-        else if (doPack)
-            doUnpack = false;
-
-        Pack200.Packer jpack = Pack200.newPacker();
-        Pack200.Unpacker junpack = Pack200.newUnpacker();
-
-        jpack.properties().putAll(engProps);
-        junpack.properties().putAll(engProps);
-        if (doRepack && newfile.equals(jarfile)) {
-            String zipc = getZipComment(jarfile);
-            if (verbose && !zipc.isEmpty())
-                System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.DETECTED_ZIP_COMMENT), zipc));
-            if (zipc.indexOf(Utils.PACK_ZIP_ARCHIVE_MARKER_COMMENT) >= 0) {
-                    System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.SKIP_FOR_REPACKED), jarfile));
-                        doPack = false;
-                        doUnpack = false;
-                        doRepack = false;
-            }
-        }
-
-        try {
-
-            if (doPack) {
-                // Mode = Pack.
-                JarFile in = new JarFile(new File(jarfile));
-                OutputStream out;
-                // Packfile must be -, *.gz, *.pack, or *.pac.
-                if (packfile.equals("-")) {
-                    out = System.out;
-                    // Send warnings, etc., to stderr instead of stdout.
-                    System.setOut(System.err);
-                } else if (doZip) {
-                    if (!packfile.endsWith(".gz")) {
-                    System.err.println(MessageFormat.format(RESOURCE.getString(DriverResource.WRITE_PACK_FILE), packfile));
-                        printUsage(doPack, false, System.err);
-                        System.exit(2);
-                    }
-                    out = new FileOutputStream(packfile);
-                    out = new BufferedOutputStream(out);
-                    out = new GZIPOutputStream(out);
-                } else {
-                    if (!packfile.toLowerCase().endsWith(".pack") &&
-                            !packfile.toLowerCase().endsWith(".pac")) {
-                        System.err.println(MessageFormat.format(RESOURCE.getString(DriverResource.WRITE_PACKGZ_FILE),packfile));
-                        printUsage(doPack, false, System.err);
-                        System.exit(2);
-                    }
-                    out = new FileOutputStream(packfile);
-                    out = new BufferedOutputStream(out);
-                }
-                jpack.pack(in, out);
-                //in.close();  // p200 closes in but not out
-                out.close();
-            }
-
-            if (doRepack && newfile.equals(jarfile)) {
-                // If the source and destination are the same,
-                // we will move the input JAR aside while regenerating it.
-                // This allows us to restore it if something goes wrong.
-                File bakf = createTempFile(jarfile, ".bak");
-                // On Windows target must be deleted see 4017593
-                bakf.delete();
-                boolean okBackup = new File(jarfile).renameTo(bakf);
-                if (!okBackup) {
-                        throw new Error(MessageFormat.format(RESOURCE.getString(DriverResource.SKIP_FOR_MOVE_FAILED),bakfile));
-                } else {
-                    // Open jarfile recovery bracket.
-                    bakfile = bakf.getPath();
-                }
-            }
-
-            if (doUnpack) {
-                // Mode = Unpack.
-                InputStream in;
-                if (packfile.equals("-"))
-                    in = System.in;
-                else
-                    in = new FileInputStream(new File(packfile));
-                BufferedInputStream inBuf = new BufferedInputStream(in);
-                in = inBuf;
-                if (Utils.isGZIPMagic(Utils.readMagic(inBuf))) {
-                    in = new GZIPInputStream(in);
-                }
-                String outfile = newfile.isEmpty()? jarfile: newfile;
-                OutputStream fileOut;
-                if (outfile.equals("-"))
-                    fileOut = System.out;
-                else
-                    fileOut = new FileOutputStream(outfile);
-                fileOut = new BufferedOutputStream(fileOut);
-                try (JarOutputStream out = new JarOutputStream(fileOut)) {
-                    junpack.unpack(in, out);
-                    // p200 closes in but not out
-                }
-                // At this point, we have a good jarfile (or newfile, if -r)
-            }
-
-            if (!bakfile.isEmpty()) {
-                        // On success, abort jarfile recovery bracket.
-                        new File(bakfile).delete();
-                        bakfile = "";
-            }
-
-        } finally {
-            // Close jarfile recovery bracket.
-            if (!bakfile.isEmpty()) {
-                File jarFile = new File(jarfile);
-                jarFile.delete(); // Win32 requires this, see above
-                new File(bakfile).renameTo(jarFile);
-            }
-            // In all cases, delete temporary *.pack.
-            if (!tmpfile.isEmpty())
-                new File(tmpfile).delete();
-        }
-    }
-
-    private static
-    File createTempFile(String basefile, String suffix) throws IOException {
-        File base = new File(basefile);
-        String prefix = base.getName();
-        if (prefix.length() < 3)  prefix += "tmp";
-
-        File where = (base.getParentFile() == null && suffix.equals(".bak"))
-                ? new File(".").getAbsoluteFile()
-                : base.getParentFile();
-
-        Path tmpfile = (where == null)
-                ? Files.createTempFile(prefix, suffix)
-                : Files.createTempFile(where.toPath(), prefix, suffix);
-
-        return tmpfile.toFile();
-    }
-
-    private static
-    void printDeprecateWarning(boolean doPack, PrintStream out) {
-        String prog = doPack ? "pack200" : "unpack200";
-        out.println(MessageFormat.format(RESOURCE.getString(DriverResource.DEPRECATED), prog));
-    }
-
-    private static
-    void printUsage(boolean doPack, boolean full, PrintStream out) {
-        String prog = doPack ? "pack200" : "unpack200";
-        String[] packUsage = (String[])RESOURCE.getObject(DriverResource.PACK_HELP);
-        String[] unpackUsage = (String[])RESOURCE.getObject(DriverResource.UNPACK_HELP);
-        String[] usage = doPack? packUsage: unpackUsage;
-        for (int i = 0; i < usage.length; i++) {
-            out.println(usage[i]);
-            if (!full) {
-            out.println(MessageFormat.format(RESOURCE.getString(DriverResource.MORE_INFO), prog));
-                break;
-            }
-        }
-        // Print a warning at the end
-        // The full help page is long, the beginning warning could be out of sight
-        if (full && !suppressDeprecateMsg) {
-            printDeprecateWarning(doPack, out);
-        }
-    }
-
-    private static
-        String getZipComment(String jarfile) throws IOException {
-        byte[] tail = new byte[1000];
-        long filelen = new File(jarfile).length();
-        if (filelen <= 0)  return "";
-        long skiplen = Math.max(0, filelen - tail.length);
-        try (InputStream in = new FileInputStream(new File(jarfile))) {
-            in.skip(skiplen);
-            in.read(tail);
-            for (int i = tail.length-4; i >= 0; i--) {
-                if (tail[i+0] == 'P' && tail[i+1] == 'K' &&
-                    tail[i+2] ==  5  && tail[i+3] ==  6) {
-                    // Skip sig4, disks4, entries4, clen4, coff4, cmt2
-                    i += 4+4+4+4+4+2;
-                    if (i < tail.length)
-                        return new String(tail, i, tail.length-i, UTF_8.INSTANCE);
-                    return "";
-                }
-            }
-            return "";
-        }
-    }
-
-    private static final String PACK200_OPTION_MAP =
-        (""
-         +"--repack                 $ \n  -r +>- @--repack              $ \n"
-         +"--no-gzip                $ \n  -g +>- @--no-gzip             $ \n"
-         +"--strip-debug            $ \n  -G +>- @--strip-debug         $ \n"
-         +"--no-keep-file-order     $ \n  -O +>- @--no-keep-file-order  $ \n"
-         +"--segment-limit=      *> = \n  -S +>  @--segment-limit=      = \n"
-         +"--effort=             *> = \n  -E +>  @--effort=             = \n"
-         +"--deflate-hint=       *> = \n  -H +>  @--deflate-hint=       = \n"
-         +"--modification-time=  *> = \n  -m +>  @--modification-time=  = \n"
-         +"--pass-file=        *> &\0 \n  -P +>  @--pass-file=        &\0 \n"
-         +"--unknown-attribute=  *> = \n  -U +>  @--unknown-attribute=  = \n"
-         +"--class-attribute=  *> &\0 \n  -C +>  @--class-attribute=  &\0 \n"
-         +"--field-attribute=  *> &\0 \n  -F +>  @--field-attribute=  &\0 \n"
-         +"--method-attribute= *> &\0 \n  -M +>  @--method-attribute= &\0 \n"
-         +"--code-attribute=   *> &\0 \n  -D +>  @--code-attribute=   &\0 \n"
-         +"--config-file=      *>   . \n  -f +>  @--config-file=        . \n"
-
-         // Negative options as required by CLIP:
-         +"--no-strip-debug  !--strip-debug         \n"
-         +"--gzip            !--no-gzip             \n"
-         +"--keep-file-order !--no-keep-file-order  \n"
-
-         // Non-Standard Options
-         +"--verbose                $ \n  -v +>- @--verbose             $ \n"
-         +"--quiet        !--verbose  \n  -q +>- !--verbose               \n"
-         +"--log-file=           *> = \n  -l +>  @--log-file=           = \n"
-         //+"--java-option=      *> = \n  -J +>  @--java-option=        = \n"
-         +"--version                . \n  -V +>  @--version             . \n"
-         +"--help               . \n  -? +> @--help . \n  -h +> @--help . \n"
-
-         // Termination:
-         +"--           . \n"  // end option sequence here
-         +"-   +?    >- . \n"  // report error if -XXX present; else use stdout
-         );
-    // Note: Collection options use "\0" as a delimiter between arguments.
-
-    // For Java version of unpacker (used for testing only):
-    private static final String UNPACK200_OPTION_MAP =
-        (""
-         +"--deflate-hint=       *> = \n  -H +>  @--deflate-hint=       = \n"
-         +"--verbose                $ \n  -v +>- @--verbose             $ \n"
-         +"--quiet        !--verbose  \n  -q +>- !--verbose               \n"
-         +"--remove-pack-file       $ \n  -r +>- @--remove-pack-file    $ \n"
-         +"--log-file=           *> = \n  -l +>  @--log-file=           = \n"
-         +"--config-file=        *> . \n  -f +>  @--config-file=        . \n"
-
-         // Termination:
-         +"--           . \n"  // end option sequence here
-         +"-   +?    >- . \n"  // report error if -XXX present; else use stdin
-         +"--version                . \n  -V +>  @--version             . \n"
-         +"--help               . \n  -? +> @--help . \n  -h +> @--help . \n"
-         );
-
-    private static final String[] PACK200_PROPERTY_TO_OPTION = {
-        Pack200.Packer.SEGMENT_LIMIT, "--segment-limit=",
-        Pack200.Packer.KEEP_FILE_ORDER, "--no-keep-file-order",
-        Pack200.Packer.EFFORT, "--effort=",
-        Pack200.Packer.DEFLATE_HINT, "--deflate-hint=",
-        Pack200.Packer.MODIFICATION_TIME, "--modification-time=",
-        Pack200.Packer.PASS_FILE_PFX, "--pass-file=",
-        Pack200.Packer.UNKNOWN_ATTRIBUTE, "--unknown-attribute=",
-        Pack200.Packer.CLASS_ATTRIBUTE_PFX, "--class-attribute=",
-        Pack200.Packer.FIELD_ATTRIBUTE_PFX, "--field-attribute=",
-        Pack200.Packer.METHOD_ATTRIBUTE_PFX, "--method-attribute=",
-        Pack200.Packer.CODE_ATTRIBUTE_PFX, "--code-attribute=",
-        //Pack200.Packer.PROGRESS, "--progress=",
-        Utils.DEBUG_VERBOSE, "--verbose",
-        Utils.COM_PREFIX+"strip.debug", "--strip-debug",
-    };
-
-    private static final String[] UNPACK200_PROPERTY_TO_OPTION = {
-        Pack200.Unpacker.DEFLATE_HINT, "--deflate-hint=",
-        //Pack200.Unpacker.PROGRESS, "--progress=",
-        Utils.DEBUG_VERBOSE, "--verbose",
-        Utils.UNPACK_REMOVE_PACKFILE, "--remove-pack-file",
-    };
-
-    /*-*
-     * Remove a set of command-line options from args,
-     * storing them in the map in a canonicalized form.
-     * 

- * The options string is a newline-separated series of - * option processing specifiers. - */ - private static - String parseCommandOptions(List args, - String options, - Map properties) { - //System.out.println(args+" // "+properties); - - String resultString = null; - - // Convert options string into optLines dictionary. - TreeMap optmap = new TreeMap<>(); - loadOptmap: - for (String optline : options.split("\n")) { - String[] words = optline.split("\\p{Space}+"); - if (words.length == 0) continue loadOptmap; - String opt = words[0]; - words[0] = ""; // initial word is not a spec - if (opt.isEmpty() && words.length >= 1) { - opt = words[1]; // initial "word" is empty due to leading ' ' - words[1] = ""; - } - if (opt.length() == 0) continue loadOptmap; - String[] prevWords = optmap.put(opt, words); - if (prevWords != null) - throw new RuntimeException(MessageFormat.format(RESOURCE.getString(DriverResource.DUPLICATE_OPTION), optline.trim())); - } - - // State machine for parsing a command line. - ListIterator argp = args.listIterator(); - ListIterator pbp = new ArrayList().listIterator(); - doArgs: - for (;;) { - // One trip through this loop per argument. - // Multiple trips per option only if several options per argument. - String arg; - if (pbp.hasPrevious()) { - arg = pbp.previous(); - pbp.remove(); - } else if (argp.hasNext()) { - arg = argp.next(); - } else { - // No more arguments at all. - break doArgs; - } - tryOpt: - for (int optlen = arg.length(); ; optlen--) { - // One time through this loop for each matching arg prefix. - String opt; - // Match some prefix of the argument to a key in optmap. - findOpt: - for (;;) { - opt = arg.substring(0, optlen); - if (optmap.containsKey(opt)) break findOpt; - if (optlen == 0) break tryOpt; - // Decide on a smaller prefix to search for. - SortedMap pfxmap = optmap.headMap(opt); - // pfxmap.lastKey is no shorter than any prefix in optmap. - int len = pfxmap.isEmpty() ? 0 : pfxmap.lastKey().length(); - optlen = Math.min(len, optlen - 1); - opt = arg.substring(0, optlen); - // (Note: We could cut opt down to its common prefix with - // pfxmap.lastKey, but that wouldn't save many cycles.) - } - opt = opt.intern(); - assert(arg.startsWith(opt)); - assert(opt.length() == optlen); - String val = arg.substring(optlen); // arg == opt+val - - // Execute the option processing specs for this opt. - // If no actions are taken, then look for a shorter prefix. - boolean didAction = false; - boolean isError = false; - - int pbpMark = pbp.nextIndex(); // in case of backtracking - String[] specs = optmap.get(opt); - eachSpec: - for (String spec : specs) { - if (spec.length() == 0) continue eachSpec; - if (spec.startsWith("#")) break eachSpec; - int sidx = 0; - char specop = spec.charAt(sidx++); - - // Deal with '+'/'*' prefixes (spec conditions). - boolean ok; - switch (specop) { - case '+': - // + means we want an non-empty val suffix. - ok = !val.isEmpty(); - specop = spec.charAt(sidx++); - break; - case '*': - // * means we accept empty or non-empty - ok = true; - specop = spec.charAt(sidx++); - break; - default: - // No condition prefix means we require an exact - // match, as indicated by an empty val suffix. - ok = (val.length() == 0); - break; - } - if (!ok) continue eachSpec; - - String specarg = spec.substring(sidx); - switch (specop) { - case '.': // terminate the option sequence - resultString = specarg.isEmpty() ? opt : specarg.intern(); - break doArgs; - case '?': // abort the option sequence - resultString = specarg.isEmpty() ? arg : specarg.intern(); - isError = true; - break eachSpec; - case '@': // change the effective opt name - opt = specarg.intern(); - break; - case '>': // shift remaining arg val to next arg - pbp.add(specarg + val); // push a new argument - val = ""; - break; - case '!': // negation option - String negopt = specarg.isEmpty() ? opt : specarg.intern(); - properties.remove(negopt); - properties.put(negopt, null); // leave placeholder - didAction = true; - break; - case '$': // normal "boolean" option - String boolval; - if (!specarg.isEmpty()) { - // If there is a given spec token, store it. - boolval = specarg; - } else { - String old = properties.get(opt); - if (old == null || old.length() == 0) { - boolval = "1"; - } else { - // Increment any previous value as a numeral. - boolval = ""+(1+Integer.parseInt(old)); - } - } - properties.put(opt, boolval); - didAction = true; - break; - case '=': // "string" option - case '&': // "collection" option - // Read an option. - boolean append = (specop == '&'); - String strval; - if (pbp.hasPrevious()) { - strval = pbp.previous(); - pbp.remove(); - } else if (argp.hasNext()) { - strval = argp.next(); - } else { - resultString = arg + " ?"; - isError = true; - break eachSpec; - } - if (append) { - String old = properties.get(opt); - if (old != null) { - // Append new val to old with embedded delim. - String delim = specarg; - if (delim.length() == 0) delim = " "; - strval = old + specarg + strval; - } - } - properties.put(opt, strval); - didAction = true; - break; - default: - throw new RuntimeException(MessageFormat.format(RESOURCE.getString(DriverResource.BAD_SPEC),opt, spec)); - } - } - - // Done processing specs. - if (didAction && !isError) { - continue doArgs; - } - - // The specs should have done something, but did not. - while (pbp.nextIndex() > pbpMark) { - // Remove anything pushed during these specs. - pbp.previous(); - pbp.remove(); - } - - if (isError) { - throw new IllegalArgumentException(resultString); - } - - if (optlen == 0) { - // We cannot try a shorter matching option. - break tryOpt; - } - } - - // If we come here, there was no matching option. - // So, push back the argument, and return to caller. - pbp.add(arg); - break doArgs; - } - // Report number of arguments consumed. - args.subList(0, argp.nextIndex()).clear(); - // Report any unconsumed partial argument. - while (pbp.hasPrevious()) { - args.add(0, pbp.previous()); - } - //System.out.println(args+" // "+properties+" -> "+resultString); - return resultString; - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java deleted file mode 100644 index c20f320f2c8..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.java.util.jar.pack; - -import java.util.ListResourceBundle; - -public class DriverResource extends ListResourceBundle { - - public static final String VERSION = "VERSION"; - public static final String BAD_ARGUMENT = "BAD_ARGUMENT"; - public static final String BAD_OPTION = "BAD_OPTION"; - public static final String BAD_REPACK_OUTPUT = "BAD_REPACK_OUTPUT"; - public static final String DETECTED_ZIP_COMMENT = "DETECTED_ZIP_COMMENT"; - public static final String SKIP_FOR_REPACKED = "SKIP_FOR_REPACKED"; - public static final String WRITE_PACK_FILE = "WRITE_PACK_FILE"; - public static final String WRITE_PACKGZ_FILE = "WRITE_PACKGZ_FILE"; - public static final String SKIP_FOR_MOVE_FAILED = "SKIP_FOR_MOVE_FAILED"; - public static final String PACK_HELP = "PACK_HELP"; - public static final String UNPACK_HELP = "UNPACK_HELP"; - public static final String MORE_INFO = "MORE_INFO"; - public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION"; - public static final String BAD_SPEC = "BAD_SPEC"; - public static final String DEPRECATED = "DEPRECATED"; - - /* - * The following are the output of 'pack200' and 'unpack200' commands. - * Do not translate command arguments and words with a prefix of '-' or '--'. - */ - private static final Object[][] resource = { - {VERSION, "{0} version {1}"}, // parameter 0:class name;parameter 1: version value - {BAD_ARGUMENT, "Bad argument: {0}"}, - {BAD_OPTION, "Bad option: {0}={1}"}, // parameter 0:option name;parameter 1:option value - {BAD_REPACK_OUTPUT, "Bad --repack output: {0}"}, // parameter 0:filename - {DETECTED_ZIP_COMMENT, "Detected ZIP comment: {0}"}, // parameter 0:comment - {SKIP_FOR_REPACKED, "Skipping because already repacked: {0}"}, // parameter 0:filename - {WRITE_PACK_FILE, "To write a *.pack file, specify --no-gzip: {0}"}, // parameter 0:filename - {WRITE_PACKGZ_FILE, "To write a *.pack.gz file, specify --gzip: {0}"}, // parameter 0:filename - {SKIP_FOR_MOVE_FAILED, "Skipping unpack because move failed: {0}"}, // parameter 0:filename - {PACK_HELP, new String[] { - "Usage: pack200 [-opt... | --option=value]... x.pack[.gz] y.jar", - "", - "Packing Options", - " -r, --repack repack or normalize a jar, suitable for ", - " signing with jarsigner", - " -g, --no-gzip output a plain pack file, suitable to be", - " compressed with a file compression utility", - " --gzip (default) post compress the pack output", - " with gzip", - " -G, --strip-debug remove debugging attributes (SourceFile,", - " LineNumberTable, LocalVariableTable", - " and LocalVariableTypeTable) while packing", - " -O, --no-keep-file-order do not transmit file ordering information", - " --keep-file-order (default) preserve input file ordering", - " -S{N}, --segment-limit={N} limit segment sizes (default unlimited)", - " -E{N}, --effort={N} packing effort (default N=5)", - " -H{h}, --deflate-hint={h} transmit deflate hint: true, false,", - " or keep (default)", - " -m{V}, --modification-time={V} transmit modtimes: latest or keep (default)", - " -P{F}, --pass-file={F} transmit the given input element(s) unchanged", - " -U{a}, --unknown-attribute={a} unknown attribute action: error, strip,", - " or pass (default)", - " -C{N}={L}, --class-attribute={N}={L} (user-defined attribute)", - " -F{N}={L}, --field-attribute={N}={L} (user-defined attribute)", - " -M{N}={L}, --method-attribute={N}={L} (user-defined attribute)", - " -D{N}={L}, --code-attribute={N}={L} (user-defined attribute)", - " -f{F}, --config-file={F} read file F for Pack200.Packer properties", - " -v, --verbose increase program verbosity", - " -q, --quiet set verbosity to lowest level", - " -l{F}, --log-file={F} output to the given log file, ", - " or '-' for System.out", - " -?, -h, --help print this help message", - " -V, --version print program version", - " -J{X} pass option X to underlying Java VM", - "", - "Notes:", - " The -P, -C, -F, -M, and -D options accumulate.", - " Example attribute definition: -C SourceFile=RUH .", - " Config. file properties are defined by the Pack200 API.", - " For meaning of -S, -E, -H-, -m, -U values, see Pack200 API.", - " Layout definitions (like RUH) are defined by JSR 200.", - "", - "Repacking mode updates the JAR file with a pack/unpack cycle:", - " pack200 [-r|--repack] [-opt | --option=value]... [repackedy.jar] y.jar\n", - "", - "Exit Status:", - " 0 if successful, >0 if an error occurred" - } - }, - {UNPACK_HELP, new String[] { - "Usage: unpack200 [-opt... | --option=value]... x.pack[.gz] y.jar\n", - "", - "Unpacking Options", - " -H{h}, --deflate-hint={h} override transmitted deflate hint:", - " true, false, or keep (default)", - " -r, --remove-pack-file remove input file after unpacking", - " -v, --verbose increase program verbosity", - " -q, --quiet set verbosity to lowest level", - " -l{F}, --log-file={F} output to the given log file, or", - " '-' for System.out", - " -?, -h, --help print this help message", - " -V, --version print program version", - " -J{X} pass option X to underlying Java VM" - } - }, - {MORE_INFO, "(For more information, run {0} --help .)"}, // parameter 0:command name - {DUPLICATE_OPTION, "duplicate option: {0}"}, // parameter 0:option - {BAD_SPEC, "bad spec for {0}: {1}"}, // parameter 0:option;parameter 1:specifier - {DEPRECATED, "\nWarning: The {0} tool is deprecated, and is planned for removal in a future JDK release.\n"} // parameter 0:command name - }; - - protected Object[][] getContents() { - return resource; - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java deleted file mode 100644 index de9d314e68c..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.java.util.jar.pack; - -import java.util.ListResourceBundle; - -public class DriverResource_ja extends ListResourceBundle { - - public static final String VERSION = "VERSION"; - public static final String BAD_ARGUMENT = "BAD_ARGUMENT"; - public static final String BAD_OPTION = "BAD_OPTION"; - public static final String BAD_REPACK_OUTPUT = "BAD_REPACK_OUTPUT"; - public static final String DETECTED_ZIP_COMMENT = "DETECTED_ZIP_COMMENT"; - public static final String SKIP_FOR_REPACKED = "SKIP_FOR_REPACKED"; - public static final String WRITE_PACK_FILE = "WRITE_PACK_FILE"; - public static final String WRITE_PACKGZ_FILE = "WRITE_PACKGZ_FILE"; - public static final String SKIP_FOR_MOVE_FAILED = "SKIP_FOR_MOVE_FAILED"; - public static final String PACK_HELP = "PACK_HELP"; - public static final String UNPACK_HELP = "UNPACK_HELP"; - public static final String MORE_INFO = "MORE_INFO"; - public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION"; - public static final String BAD_SPEC = "BAD_SPEC"; - public static final String DEPRECATED = "DEPRECATED"; - - /* - * The following are the output of 'pack200' and 'unpack200' commands. - * Do not translate command arguments and words with a prefix of '-' or '--'. - */ - private static final Object[][] resource = { - {VERSION, "{0}\u30D0\u30FC\u30B8\u30E7\u30F3{1}"}, // parameter 0:class name;parameter 1: version value - {BAD_ARGUMENT, "\u7121\u52B9\u306A\u5F15\u6570: {0}"}, - {BAD_OPTION, "\u7121\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0}={1}"}, // parameter 0:option name;parameter 1:option value - {BAD_REPACK_OUTPUT, "\u7121\u52B9\u306A--repack\u51FA\u529B: {0}"}, // parameter 0:filename - {DETECTED_ZIP_COMMENT, "\u691C\u51FA\u3055\u308C\u305FZIP\u30B3\u30E1\u30F3\u30C8: {0}"}, // parameter 0:comment - {SKIP_FOR_REPACKED, "\u3059\u3067\u306B\u518D\u5727\u7E2E\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059: {0}"}, // parameter 0:filename - {WRITE_PACK_FILE, "*.pack\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080\u306B\u306F\u3001--no-gzip\u3092\u6307\u5B9A\u3057\u307E\u3059: {0}"}, // parameter 0:filename - {WRITE_PACKGZ_FILE, "*.pack.gz\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080\u306B\u306F\u3001--gzip\u3092\u6307\u5B9A\u3057\u307E\u3059: {0}"}, // parameter 0:filename - {SKIP_FOR_MOVE_FAILED, "\u79FB\u52D5\u304C\u5931\u6557\u3057\u305F\u305F\u3081\u89E3\u51CD\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059: {0}"}, // parameter 0:filename - {PACK_HELP, new String[] { - "\u4F7F\u7528\u65B9\u6CD5: pack200 [-opt... | --option=value]... x.pack[.gz] y.jar", - "", - "\u5727\u7E2E\u30AA\u30D7\u30B7\u30E7\u30F3", - " -r\u3001--repack jar\u3092\u518D\u5727\u7E2E\u307E\u305F\u306F\u6B63\u898F\u5316\u3059\u308B\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3001", - " jarsigner\u306B\u3088\u308B\u7F72\u540D\u306B\u9069\u3057\u307E\u3059", - " -g\u3001--no-gzip \u30D7\u30EC\u30FC\u30F3\u306Apack\u30D5\u30A1\u30A4\u30EB\u3092\u51FA\u529B\u3059\u308B\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3001", - " \u30D5\u30A1\u30A4\u30EB\u5727\u7E2E\u30E6\u30FC\u30C6\u30A3\u30EA\u30C6\u30A3\u306B\u3088\u308B\u5727\u7E2E\u306B\u9069\u3057\u307E\u3059", - " --gzip (\u30C7\u30D5\u30A9\u30EB\u30C8) pack\u51FA\u529B\u3092\u5F8C\u51E6\u7406\u3067\u5727\u7E2E\u3057\u307E\u3059", - " (gzip\u3092\u4F7F\u7528)", - " -G\u3001--strip-debug \u5727\u7E2E\u4E2D\u306B\u30C7\u30D0\u30C3\u30B0\u5C5E\u6027(SourceFile\u3001", - " LineNumberTable\u3001LocalVariableTable", - " \u3001LocalVariableTypeTable)\u3092\u524A\u9664\u3057\u307E\u3059", - " -O\u3001--no-keep-file-order \u30D5\u30A1\u30A4\u30EB\u306E\u9806\u5E8F\u4ED8\u3051\u60C5\u5831\u3092\u8EE2\u9001\u3057\u307E\u305B\u3093", - " --keep-file-order (\u30C7\u30D5\u30A9\u30EB\u30C8)\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u9806\u5E8F\u4ED8\u3051\u3092\u4FDD\u6301\u3057\u307E\u3059", - " -S{N}\u3001--segment-limit={N} \u30BB\u30B0\u30E1\u30F3\u30C8\u30FB\u30B5\u30A4\u30BA\u3092\u5236\u9650\u3057\u307E\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u7121\u5236\u9650)", - " -E{N}\u3001--effort={N} \u5727\u7E2E\u306E\u8A66\u884C(\u30C7\u30D5\u30A9\u30EB\u30C8N=5)", - " -H{h}\u3001--deflate-hint={h} \u30C7\u30D5\u30EC\u30FC\u30C8\u30FB\u30D2\u30F3\u30C8\u3092\u8EE2\u9001\u3057\u307E\u3059: true\u3001false", - " \u307E\u305F\u306Fkeep(\u30C7\u30D5\u30A9\u30EB\u30C8)", - " -m{V}\u3001--modification-time={V} \u5909\u66F4\u6642\u9593\u3092\u8EE2\u9001\u3057\u307E\u3059: latest\u307E\u305F\u306Fkeep(\u30C7\u30D5\u30A9\u30EB\u30C8)", - " -P{F}\u3001--pass-file={F} \u6307\u5B9A\u3055\u308C\u305F\u5165\u529B\u8981\u7D20\u3092\u305D\u306E\u307E\u307E\u8EE2\u9001\u3057\u307E\u3059", - " -U{a}\u3001--unknown-attribute={a} \u4E0D\u660E\u306E\u5C5E\u6027\u30A2\u30AF\u30B7\u30E7\u30F3: error\u3001strip", - " \u307E\u305F\u306Fpass(\u30C7\u30D5\u30A9\u30EB\u30C8)", - " -C{N}={L}\u3001--class-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", - " -F{N}={L}\u3001--field-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", - " -M{N}={L}\u3001--method-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", - " -D{N}={L}\u3001--code-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", - " -f{F}\u3001--config-file={F} Pack200.Packer\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u30D5\u30A1\u30A4\u30EBF\u3092\u8AAD\u307F\u8FBC\u307F\u307E\u3059", - " -v\u3001--verbose \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u5197\u9577\u6027\u3092\u9AD8\u3081\u307E\u3059", - " -q\u3001--quiet \u5197\u9577\u6027\u3092\u6700\u4F4E\u30EC\u30D9\u30EB\u306B\u8A2D\u5B9A\u3057\u307E\u3059", - " -l{F}\u3001--log-file={F} \u6307\u5B9A\u306E\u30ED\u30B0\u30FB\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306FSystem.out ", - " ('-'\u306E\u5834\u5408)\u306B\u51FA\u529B\u3057\u307E\u3059", - " -?\u3001-h\u3001--help \u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u3057\u307E\u3059", - " -V\u3001--version \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059", - " -J{X} \u30AA\u30D7\u30B7\u30E7\u30F3X\u3092\u57FA\u790E\u3068\u306A\u308BJava VM\u306B\u6E21\u3057\u307E\u3059", - "", - "\u6CE8:", - " -P\u3001-C\u3001-F\u3001-M\u304A\u3088\u3073-D\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u7D2F\u7A4D\u3055\u308C\u307E\u3059\u3002", - " \u5C5E\u6027\u5B9A\u7FA9\u306E\u4F8B: -C SourceFile=RUH .", - " Config.\u30D5\u30A1\u30A4\u30EB\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306F\u3001Pack200 API\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002", - " -S\u3001-E\u3001-H\u3001-m\u3001-U\u306E\u5024\u306E\u610F\u5473\u306F\u3001Pack200 API\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002", - " \u30EC\u30A4\u30A2\u30A6\u30C8\u5B9A\u7FA9(RUH\u306A\u3069)\u306FJSR 200\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002", - "", - "\u518D\u5727\u7E2E\u30E2\u30FC\u30C9\u3067\u306F\u3001JAR\u30D5\u30A1\u30A4\u30EB\u304C\u5727\u7E2E/\u89E3\u51CD\u30B5\u30A4\u30AF\u30EB\u3067\u66F4\u65B0\u3055\u308C\u307E\u3059:", - " pack200 [-r|--repack] [-opt | --option=value]... [repackedy.jar] y.jar\n", - "", - "\u7D42\u4E86\u30B9\u30C6\u30FC\u30BF\u30B9:", - " 0 (\u6210\u529F\u3057\u305F\u5834\u5408)\u3001>0 (\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u305F\u5834\u5408)" - } - }, - {UNPACK_HELP, new String[] { - "\u4F7F\u7528\u65B9\u6CD5: unpack200 [-opt... | --option=value]... x.pack[.gz] y.jar\n", - "", - "\u89E3\u51CD\u30AA\u30D7\u30B7\u30E7\u30F3", - " -H{h}\u3001--deflate-hint={h} \u8EE2\u9001\u3055\u308C\u305F\u30C7\u30D5\u30EC\u30FC\u30C8\u30FB\u30D2\u30F3\u30C8\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059:", - " true\u3001false\u307E\u305F\u306Fkeep(\u30C7\u30D5\u30A9\u30EB\u30C8)", - " -r\u3001--remove-pack-file \u89E3\u51CD\u5F8C\u306B\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u307E\u3059", - " -v\u3001--verbose \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u5197\u9577\u6027\u3092\u9AD8\u3081\u307E\u3059", - " -q\u3001--quiet \u5197\u9577\u6027\u3092\u6700\u4F4E\u30EC\u30D9\u30EB\u306B\u8A2D\u5B9A\u3057\u307E\u3059", - " -l{F}\u3001--log-file={F} \u6307\u5B9A\u306E\u30ED\u30B0\u30FB\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F", - " System.out ('-'\u306E\u5834\u5408)\u306B\u51FA\u529B\u3057\u307E\u3059", - " -?\u3001-h\u3001--help \u3053\u306E\u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u3057\u307E\u3059", - " -V\u3001--version \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059", - " -J{X} \u30AA\u30D7\u30B7\u30E7\u30F3X\u3092\u57FA\u790E\u3068\u306A\u308BJava VM\u306B\u6E21\u3057\u307E\u3059" - } - }, - {MORE_INFO, "(\u8A73\u7D30\u306F\u3001{0} --help\u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002)"}, // parameter 0:command name - {DUPLICATE_OPTION, "\u91CD\u8907\u30AA\u30D7\u30B7\u30E7\u30F3: {0}"}, // parameter 0:option - {BAD_SPEC, "{0}\u306E\u7121\u52B9\u306A\u4ED5\u69D8: {1}"}, // parameter 0:option;parameter 1:specifier - {DEPRECATED, "\n\u8B66\u544A: {0}\u30C4\u30FC\u30EB\u306F\u975E\u63A8\u5968\u3067\u3042\u308A\u3001\u4ECA\u5F8C\u306EJDK\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059\u3002\n"} // parameter 0:command name - }; - - protected Object[][] getContents() { - return resource; - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java deleted file mode 100644 index dc64ab0ae07..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.java.util.jar.pack; - -import java.util.ListResourceBundle; - -public class DriverResource_zh_CN extends ListResourceBundle { - - public static final String VERSION = "VERSION"; - public static final String BAD_ARGUMENT = "BAD_ARGUMENT"; - public static final String BAD_OPTION = "BAD_OPTION"; - public static final String BAD_REPACK_OUTPUT = "BAD_REPACK_OUTPUT"; - public static final String DETECTED_ZIP_COMMENT = "DETECTED_ZIP_COMMENT"; - public static final String SKIP_FOR_REPACKED = "SKIP_FOR_REPACKED"; - public static final String WRITE_PACK_FILE = "WRITE_PACK_FILE"; - public static final String WRITE_PACKGZ_FILE = "WRITE_PACKGZ_FILE"; - public static final String SKIP_FOR_MOVE_FAILED = "SKIP_FOR_MOVE_FAILED"; - public static final String PACK_HELP = "PACK_HELP"; - public static final String UNPACK_HELP = "UNPACK_HELP"; - public static final String MORE_INFO = "MORE_INFO"; - public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION"; - public static final String BAD_SPEC = "BAD_SPEC"; - public static final String DEPRECATED = "DEPRECATED"; - - /* - * The following are the output of 'pack200' and 'unpack200' commands. - * Do not translate command arguments and words with a prefix of '-' or '--'. - */ - private static final Object[][] resource = { - {VERSION, "{0}\u7248\u672C {1}"}, // parameter 0:class name;parameter 1: version value - {BAD_ARGUMENT, "\u9519\u8BEF\u53C2\u6570: {0}"}, - {BAD_OPTION, "\u9519\u8BEF\u9009\u9879: {0}={1}"}, // parameter 0:option name;parameter 1:option value - {BAD_REPACK_OUTPUT, "--repack \u8F93\u51FA\u9519\u8BEF: {0}"}, // parameter 0:filename - {DETECTED_ZIP_COMMENT, "\u68C0\u6D4B\u5230 ZIP \u6CE8\u91CA: {0}"}, // parameter 0:comment - {SKIP_FOR_REPACKED, "\u7531\u4E8E\u5DF2\u91CD\u65B0\u6253\u5305\u800C\u8DF3\u8FC7: {0}"}, // parameter 0:filename - {WRITE_PACK_FILE, "\u8981\u5199\u5165 *.pack \u6587\u4EF6, \u8BF7\u6307\u5B9A --no-gzip: {0}"}, // parameter 0:filename - {WRITE_PACKGZ_FILE, "\u8981\u5199\u5165 *.pack.gz \u6587\u4EF6, \u8BF7\u6307\u5B9A --gzip: {0}"}, // parameter 0:filename - {SKIP_FOR_MOVE_FAILED, "\u7531\u4E8E\u79FB\u52A8\u5931\u8D25\u800C\u8DF3\u8FC7\u89E3\u5305: {0}"}, // parameter 0:filename - {PACK_HELP, new String[] { - "\u7528\u6CD5: pack200 [-opt... | --option=value]... x.pack[.gz] y.jar", - "", - "\u6253\u5305\u9009\u9879", - " -r, --repack \u518D\u6B21\u6253\u5305\u6216\u89C4\u8303\u5316 jar, \u9002\u5408\u4E8E ", - " \u4F7F\u7528 jarsigner \u8FDB\u884C\u7B7E\u540D", - " -g, --no-gzip \u8F93\u51FA\u65E0\u683C\u5F0F\u7684\u5305\u6587\u4EF6, \u9002\u5408\u4E8E", - " \u4F7F\u7528\u6587\u4EF6\u538B\u7F29\u5B9E\u7528\u7A0B\u5E8F\u8FDB\u884C\u538B\u7F29", - " --gzip (\u9ED8\u8BA4\u503C) \u4F7F\u7528 gzip \u5BF9\u5305\u8F93\u51FA\u8FDB\u884C", - " \u538B\u7F29\u540E\u5904\u7406", - " -G, --strip-debug \u6253\u5305\u65F6\u5220\u9664\u8C03\u8BD5\u5C5E\u6027 (SourceFile,", - " LineNumberTable, LocalVariableTable", - " \u548C LocalVariableTypeTable)", - " -O, --no-keep-file-order \u4E0D\u4F20\u8F93\u6587\u4EF6\u6392\u5E8F\u4FE1\u606F", - " --keep-file-order (\u9ED8\u8BA4\u503C) \u4FDD\u7559\u8F93\u5165\u6587\u4EF6\u6392\u5E8F", - " -S{N}, --segment-limit={N} \u9650\u5236\u6BB5\u5927\u5C0F (\u9ED8\u8BA4\u4E3A\u65E0\u9650\u5236)", - " -E{N}, --effort={N} \u6253\u5305\u6548\u679C (\u9ED8\u8BA4\u503C N=5)", - " -H{h}, --deflate-hint={h} \u4F20\u8F93\u538B\u7F29\u63D0\u793A: true, false", - " \u6216 keep (\u9ED8\u8BA4\u503C)", - " -m{V}, --modification-time={V} \u4F20\u8F93 modtimes: latest \u6216 keep (\u9ED8\u8BA4\u503C)", - " -P{F}, --pass-file={F} \u4F20\u8F93\u672A\u66F4\u6539\u7684\u7ED9\u5B9A\u8F93\u5165\u5143\u7D20", - " -U{a}, --unknown-attribute={a} \u672A\u77E5\u5C5E\u6027\u64CD\u4F5C: error, strip", - " \u6216 pass (\u9ED8\u8BA4\u503C)", - " -C{N}={L}, --class-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", - " -F{N}={L}, --field-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", - " -M{N}={L}, --method-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", - " -D{N}={L}, --code-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", - " -f{F}, --config-file={F} \u8BFB\u53D6\u6587\u4EF6 F \u7684 Pack200.Packer \u5C5E\u6027", - " -v, --verbose \u63D0\u9AD8\u7A0B\u5E8F\u8BE6\u7EC6\u7A0B\u5EA6", - " -q, --quiet \u5C06\u8BE6\u7EC6\u7A0B\u5EA6\u8BBE\u7F6E\u4E3A\u6700\u4F4E\u7EA7\u522B", - " -l{F}, --log-file={F} \u8F93\u51FA\u5230\u7ED9\u5B9A\u65E5\u5FD7\u6587\u4EF6, ", - " \u6216\u5BF9\u4E8E System.out \u6307\u5B9A '-'", - " -?, -h, --help \u8F93\u51FA\u6B64\u5E2E\u52A9\u6D88\u606F", - " -V, --version \u8F93\u51FA\u7A0B\u5E8F\u7248\u672C", - " -J{X} \u5C06\u9009\u9879 X \u4F20\u9012\u7ED9\u57FA\u7840 Java VM", - "", - "\u6CE8:", - " -P, -C, -F, -M \u548C -D \u9009\u9879\u7D2F\u8BA1\u3002", - " \u793A\u4F8B\u5C5E\u6027\u5B9A\u4E49: -C SourceFile=RUH\u3002", - " Config. \u6587\u4EF6\u5C5E\u6027\u7531 Pack200 API \u5B9A\u4E49\u3002", - " \u6709\u5173 -S, -E, -H-, -m, -U \u503C\u7684\u542B\u4E49, \u8BF7\u53C2\u9605 Pack200 API\u3002", - " \u5E03\u5C40\u5B9A\u4E49 (\u4F8B\u5982 RUH) \u7531 JSR 200 \u5B9A\u4E49\u3002", - "", - "\u91CD\u65B0\u6253\u5305\u6A21\u5F0F\u901A\u8FC7\u6253\u5305/\u89E3\u5305\u5468\u671F\u66F4\u65B0 JAR \u6587\u4EF6:", - " pack200 [-r|--repack] [-opt | --option=value]... [repackedy.jar] y.jar\n", - "", - "\u9000\u51FA\u72B6\u6001:", - " \u5982\u679C\u6210\u529F\u5219\u4E3A 0; \u5982\u679C\u51FA\u73B0\u9519\u8BEF, \u5219\u4E3A\u5927\u4E8E 0 \u7684\u503C" - } - }, - {UNPACK_HELP, new String[] { - "\u7528\u6CD5: unpack200 [-opt... | --option=value]... x.pack[.gz] y.jar\n", - "", - "\u89E3\u5305\u9009\u9879", - " -H{h}, --deflate-hint={h} \u8986\u76D6\u5DF2\u4F20\u8F93\u7684\u538B\u7F29\u63D0\u793A:", - " true, false \u6216 keep (\u9ED8\u8BA4\u503C)", - " -r, --remove-pack-file \u89E3\u5305\u4E4B\u540E\u5220\u9664\u8F93\u5165\u6587\u4EF6", - " -v, --verbose \u63D0\u9AD8\u7A0B\u5E8F\u8BE6\u7EC6\u7A0B\u5EA6", - " -q, --quiet \u5C06\u8BE6\u7EC6\u7A0B\u5EA6\u8BBE\u7F6E\u4E3A\u6700\u4F4E\u7EA7\u522B", - " -l{F}, --log-file={F} \u8F93\u51FA\u5230\u7ED9\u5B9A\u65E5\u5FD7\u6587\u4EF6, \u6216", - " \u5BF9\u4E8E System.out \u6307\u5B9A '-'", - " -?, -h, --help \u8F93\u51FA\u6B64\u5E2E\u52A9\u6D88\u606F", - " -V, --version \u8F93\u51FA\u7A0B\u5E8F\u7248\u672C", - " -J{X} \u5C06\u9009\u9879 X \u4F20\u9012\u7ED9\u57FA\u7840 Java VM" - } - }, - {MORE_INFO, "(\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u8FD0\u884C {0} --help\u3002)"}, // parameter 0:command name - {DUPLICATE_OPTION, "\u91CD\u590D\u7684\u9009\u9879: {0}"}, // parameter 0:option - {BAD_SPEC, "{0}\u7684\u89C4\u8303\u9519\u8BEF: {1}"}, // parameter 0:option;parameter 1:specifier - {DEPRECATED, "\n\u8B66\u544A\uFF1A{0} \u5DE5\u5177\u5DF2\u8FC7\u65F6\uFF0C\u8BA1\u5212\u5728\u672A\u6765\u7684 JDK \u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n"} // parameter 0:command name - }; - - protected Object[][] getContents() { - return resource; - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/FixedList.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/FixedList.java deleted file mode 100644 index 450635ad5ba..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/FixedList.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.java.util.jar.pack; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -/* - * @author ksrini - */ - -/* - * This class provides an ArrayList implementation which has a fixed size, - * thus all the operations which modifies the size have been rendered - * inoperative. This essentially allows us to use generified array - * lists in lieu of arrays. - */ -final class FixedList implements List { - - private final ArrayList flist; - - protected FixedList(int capacity) { - flist = new ArrayList<>(capacity); - // initialize the list to null - for (int i = 0 ; i < capacity ; i++) { - flist.add(null); - } - } - @Override - public int size() { - return flist.size(); - } - - @Override - public boolean isEmpty() { - return flist.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return flist.contains(o); - } - - @Override - public Iterator iterator() { - return flist.iterator(); - } - - @Override - public Object[] toArray() { - return flist.toArray(); - } - - @Override - public T[] toArray(T[] a) { - return flist.toArray(a); - } - - @Override - public boolean add(E e) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public boolean remove(Object o) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public boolean containsAll(Collection c) { - return flist.containsAll(c); - } - - @Override - public boolean addAll(Collection c) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public boolean addAll(int index, Collection c) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public boolean removeAll(Collection c) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public boolean retainAll(Collection c) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public void clear() throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public E get(int index) { - return flist.get(index); - } - - @Override - public E set(int index, E element) { - return flist.set(index, element); - } - - @Override - public void add(int index, E element) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public E remove(int index) throws UnsupportedOperationException { - throw new UnsupportedOperationException("operation not permitted"); - } - - @Override - public int indexOf(Object o) { - return flist.indexOf(o); - } - - @Override - public int lastIndexOf(Object o) { - return flist.lastIndexOf(o); - } - - @Override - public ListIterator listIterator() { - return flist.listIterator(); - } - - @Override - public ListIterator listIterator(int index) { - return flist.listIterator(index); - } - - @Override - public List subList(int fromIndex, int toIndex) { - return flist.subList(fromIndex, toIndex); - } - - @Override - public String toString() { - return "FixedList{" + "plist=" + flist + '}'; - } -} - diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Fixups.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Fixups.java deleted file mode 100644 index 647d1dbc413..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Fixups.java +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import java.util.AbstractCollection; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Objects; - -/** - * Collection of relocatable constant pool references. - * It operates with respect to a particular byte array, - * and stores some of its state in the bytes themselves. - *

- * As a Collection, it can be iterated over, but it is not a List, - * since it does not natively support indexed access. - *

- * - * @author John Rose - */ -final class Fixups extends AbstractCollection { - byte[] bytes; // the subject of the relocations - int head; // desc locating first reloc - int tail; // desc locating last reloc - int size; // number of relocations - Entry[] entries; // [0..size-1] relocations - int[] bigDescs; // descs which cannot be stored in the bytes - - // A "desc" (descriptor) is a bit-encoded pair of a location - // and format. Every fixup occurs at a "desc". Until final - // patching, bytes addressed by descs may also be used to - // link this data structure together. If the bytes are missing, - // or if the "desc" is too large to encode in the bytes, - // it is kept in the bigDescs array. - - Fixups(byte[] bytes) { - this.bytes = bytes; - entries = new Entry[3]; - bigDescs = noBigDescs; - } - Fixups() { - // If there are no bytes, all descs are kept in bigDescs. - this((byte[])null); - } - Fixups(byte[] bytes, Collection fixups) { - this(bytes); - addAll(fixups); - } - Fixups(Collection fixups) { - this((byte[])null); - addAll(fixups); - } - - private static final int MINBIGSIZE = 1; - // cleverly share empty bigDescs: - private static final int[] noBigDescs = {MINBIGSIZE}; - - @Override - public int size() { - return size; - } - - public void trimToSize() { - if (size != entries.length) { - Entry[] oldEntries = entries; - entries = new Entry[size]; - System.arraycopy(oldEntries, 0, entries, 0, size); - } - int bigSize = bigDescs[BIGSIZE]; - if (bigSize == MINBIGSIZE) { - bigDescs = noBigDescs; - } else if (bigSize != bigDescs.length) { - int[] oldBigDescs = bigDescs; - bigDescs = new int[bigSize]; - System.arraycopy(oldBigDescs, 0, bigDescs, 0, bigSize); - } - } - - public void visitRefs(Collection refs) { - for (int i = 0; i < size; i++) { - refs.add(entries[i]); - } - } - - @Override - public void clear() { - if (bytes != null) { - // Clean the bytes: - for (Fixup fx : this) { - //System.out.println("clean "+fx); - storeIndex(fx.location(), fx.format(), 0); - } - } - size = 0; - if (bigDescs != noBigDescs) - bigDescs[BIGSIZE] = MINBIGSIZE; - // do not trim to size, however - } - - public byte[] getBytes() { - return bytes; - } - - public void setBytes(byte[] newBytes) { - if (bytes == newBytes) return; - ArrayList old = null; - assert((old = new ArrayList<>(this)) != null); - if (bytes == null || newBytes == null) { - // One or the other representations is deficient. - // Construct a checkpoint. - ArrayList save = new ArrayList<>(this); - clear(); - bytes = newBytes; - addAll(save); - } else { - // assume newBytes is some sort of bitwise copy of the old bytes - bytes = newBytes; - } - assert(old.equals(new ArrayList<>(this))); - } - - private static final int LOC_SHIFT = 1; - private static final int FMT_MASK = 0x1; - private static final byte UNUSED_BYTE = 0; - private static final byte OVERFLOW_BYTE = -1; - // fill pointer of bigDescs array is in element [0] - private static final int BIGSIZE = 0; - - // Format values: - private static final int U2_FORMAT = 0; - private static final int U1_FORMAT = 1; - - // Special values for the static methods. - private static final int SPECIAL_LOC = 0; - private static final int SPECIAL_FMT = U2_FORMAT; - - static int fmtLen(int fmt) { return 1+(fmt-U1_FORMAT)/(U2_FORMAT-U1_FORMAT); } - static int descLoc(int desc) { return desc >>> LOC_SHIFT; } - static int descFmt(int desc) { return desc & FMT_MASK; } - static int descEnd(int desc) { return descLoc(desc) + fmtLen(descFmt(desc)); } - static int makeDesc(int loc, int fmt) { - int desc = (loc << LOC_SHIFT) | fmt; - assert(descLoc(desc) == loc); - assert(descFmt(desc) == fmt); - return desc; - } - int fetchDesc(int loc, int fmt) { - byte b1 = bytes[loc]; - assert(b1 != OVERFLOW_BYTE); - int value; - if (fmt == U2_FORMAT) { - byte b2 = bytes[loc+1]; - value = ((b1 & 0xFF) << 8) + (b2 & 0xFF); - } else { - value = (b1 & 0xFF); - } - // Stored loc field is difference between its own loc and next loc. - return value + (loc << LOC_SHIFT); - } - boolean storeDesc(int loc, int fmt, int desc) { - if (bytes == null) - return false; - int value = desc - (loc << LOC_SHIFT); - byte b1, b2; - switch (fmt) { - case U2_FORMAT: - assert(bytes[loc+0] == UNUSED_BYTE); - assert(bytes[loc+1] == UNUSED_BYTE); - b1 = (byte)(value >> 8); - b2 = (byte)(value >> 0); - if (value == (value & 0xFFFF) && b1 != OVERFLOW_BYTE) { - bytes[loc+0] = b1; - bytes[loc+1] = b2; - assert(fetchDesc(loc, fmt) == desc); - return true; - } - break; - case U1_FORMAT: - assert(bytes[loc] == UNUSED_BYTE); - b1 = (byte)value; - if (value == (value & 0xFF) && b1 != OVERFLOW_BYTE) { - bytes[loc] = b1; - assert(fetchDesc(loc, fmt) == desc); - return true; - } - break; - default: assert(false); - } - // Failure. Caller must allocate a bigDesc. - bytes[loc] = OVERFLOW_BYTE; - assert(fmt==U1_FORMAT || (bytes[loc+1]=(byte)bigDescs[BIGSIZE])!=999); - return false; - } - void storeIndex(int loc, int fmt, int value) { - storeIndex(bytes, loc, fmt, value); - } - static - void storeIndex(byte[] bytes, int loc, int fmt, int value) { - switch (fmt) { - case U2_FORMAT: - assert(value == (value & 0xFFFF)) : (value); - bytes[loc+0] = (byte)(value >> 8); - bytes[loc+1] = (byte)(value >> 0); - break; - case U1_FORMAT: - assert(value == (value & 0xFF)) : (value); - bytes[loc] = (byte)value; - break; - default: assert(false); - } - } - - void addU1(int pc, Entry ref) { - add(pc, U1_FORMAT, ref); - } - - void addU2(int pc, Entry ref) { - add(pc, U2_FORMAT, ref); - } - - /** Simple and necessary tuple to present each fixup. */ - public static - class Fixup implements Comparable { - int desc; // location and format of reloc - Entry entry; // which entry to plug into the bytes - Fixup(int desc, Entry entry) { - this.desc = desc; - this.entry = entry; - } - public Fixup(int loc, int fmt, Entry entry) { - this.desc = makeDesc(loc, fmt); - this.entry = entry; - } - public int location() { return descLoc(desc); } - public int format() { return descFmt(desc); } - public Entry entry() { return entry; } - @Override - public int compareTo(Fixup that) { - // Ordering depends only on location. - return this.location() - that.location(); - } - @Override - public boolean equals(Object x) { - if (!(x instanceof Fixup)) return false; - Fixup that = (Fixup) x; - return this.desc == that.desc && this.entry == that.entry; - } - @Override - public int hashCode() { - int hash = 7; - hash = 59 * hash + this.desc; - hash = 59 * hash + Objects.hashCode(this.entry); - return hash; - } - @Override - public String toString() { - return "@"+location()+(format()==U1_FORMAT?".1":"")+"="+entry; - } - } - - private - class Itr implements Iterator { - int index = 0; // index into entries - int bigIndex = BIGSIZE+1; // index into bigDescs - int next = head; // desc pointing to next fixup - @Override - public boolean hasNext() { return index < size; } - @Override - public void remove() { throw new UnsupportedOperationException(); } - @Override - public Fixup next() { - int thisIndex = index; - return new Fixup(nextDesc(), entries[thisIndex]); - } - int nextDesc() { - index++; - int thisDesc = next; - if (index < size) { - // Fetch next desc eagerly, in case this fixup gets finalized. - int loc = descLoc(thisDesc); - int fmt = descFmt(thisDesc); - if (bytes != null && bytes[loc] != OVERFLOW_BYTE) { - next = fetchDesc(loc, fmt); - } else { - // The unused extra byte is "asserted" to be equal to BI. - // This helps keep the overflow descs in sync. - assert(fmt==U1_FORMAT || bytes == null || bytes[loc+1]==(byte)bigIndex); - next = bigDescs[bigIndex++]; - } - } - return thisDesc; - } - } - - @Override - public Iterator iterator() { - return new Itr(); - } - public void add(int location, int format, Entry entry) { - addDesc(makeDesc(location, format), entry); - } - @Override - public boolean add(Fixup f) { - addDesc(f.desc, f.entry); - return true; - } - - @Override - public boolean addAll(Collection c) { - if (c instanceof Fixups) { - // Use knowledge of Itr structure to avoid building little structs. - Fixups that = (Fixups) c; - if (that.size == 0) return false; - if (this.size == 0 && entries.length < that.size) - growEntries(that.size); // presize exactly - Entry[] thatEntries = that.entries; - for (Itr i = that.new Itr(); i.hasNext(); ) { - int ni = i.index; - addDesc(i.nextDesc(), thatEntries[ni]); - } - return true; - } else { - return super.addAll(c); - } - } - // Here is how things get added: - private void addDesc(int thisDesc, Entry entry) { - if (entries.length == size) - growEntries(size * 2); - entries[size] = entry; - if (size == 0) { - head = tail = thisDesc; - } else { - int prevDesc = tail; - // Store new desc in previous tail. - int prevLoc = descLoc(prevDesc); - int prevFmt = descFmt(prevDesc); - int prevLen = fmtLen(prevFmt); - int thisLoc = descLoc(thisDesc); - // The collection must go in ascending order, and not overlap. - if (thisLoc < prevLoc + prevLen) - badOverlap(thisLoc); - tail = thisDesc; - if (!storeDesc(prevLoc, prevFmt, thisDesc)) { - // overflow - int bigSize = bigDescs[BIGSIZE]; - if (bigDescs.length == bigSize) - growBigDescs(); - //System.out.println("bigDescs["+bigSize+"] = "+thisDesc); - bigDescs[bigSize++] = thisDesc; - bigDescs[BIGSIZE] = bigSize; - } - } - size += 1; - } - private void badOverlap(int thisLoc) { - throw new IllegalArgumentException("locs must be ascending and must not overlap: "+thisLoc+" >> "+this); - } - - private void growEntries(int newSize) { - Entry[] oldEntries = entries; - entries = new Entry[Math.max(3, newSize)]; - System.arraycopy(oldEntries, 0, entries, 0, oldEntries.length); - } - private void growBigDescs() { - int[] oldBigDescs = bigDescs; - bigDescs = new int[oldBigDescs.length * 2]; - System.arraycopy(oldBigDescs, 0, bigDescs, 0, oldBigDescs.length); - } - - /// Static methods that optimize the use of this class. - static Object addRefWithBytes(Object f, byte[] bytes, Entry e) { - return add(f, bytes, 0, U2_FORMAT, e); - } - static Object addRefWithLoc(Object f, int loc, Entry entry) { - return add(f, null, loc, U2_FORMAT, entry); - } - private static - Object add(Object prevFixups, - byte[] bytes, int loc, int fmt, - Entry e) { - Fixups f; - if (prevFixups == null) { - if (loc == SPECIAL_LOC && fmt == SPECIAL_FMT) { - // Special convention: If the attribute has a - // U2 relocation at position zero, store the Entry - // rather than building a Fixups structure. - return e; - } - f = new Fixups(bytes); - } else if (!(prevFixups instanceof Fixups)) { - // Recognize the special convention: - Entry firstEntry = (Entry) prevFixups; - f = new Fixups(bytes); - f.add(SPECIAL_LOC, SPECIAL_FMT, firstEntry); - } else { - f = (Fixups) prevFixups; - assert(f.bytes == bytes); - } - f.add(loc, fmt, e); - return f; - } - - public static - void setBytes(Object fixups, byte[] bytes) { - if (fixups instanceof Fixups) { - Fixups f = (Fixups) fixups; - f.setBytes(bytes); - } - } - - public static - Object trimToSize(Object fixups) { - if (fixups instanceof Fixups) { - Fixups f = (Fixups) fixups; - f.trimToSize(); - if (f.size() == 0) - fixups = null; - } - return fixups; - } - - // Iterate over all the references in this set of fixups. - public static - void visitRefs(Object fixups, Collection refs) { - if (fixups == null) { - } else if (!(fixups instanceof Fixups)) { - // Special convention; see above. - refs.add((Entry) fixups); - } else { - Fixups f = (Fixups) fixups; - f.visitRefs(refs); - } - } - - // Clear out this set of fixups by replacing each reference - // by a hardcoded coding of its reference, drawn from ix. - public static - void finishRefs(Object fixups, byte[] bytes, ConstantPool.Index ix) { - if (fixups == null) - return; - if (!(fixups instanceof Fixups)) { - // Special convention; see above. - int index = ix.indexOf((Entry) fixups); - storeIndex(bytes, SPECIAL_LOC, SPECIAL_FMT, index); - return; - } - Fixups f = (Fixups) fixups; - assert(f.bytes == bytes); - f.finishRefs(ix); - } - - void finishRefs(ConstantPool.Index ix) { - if (isEmpty()) - return; - for (Fixup fx : this) { - int index = ix.indexOf(fx.entry); - //System.out.println("finish "+fx+" = "+index); - // Note that the iterator has already fetched the - // bytes we are about to overwrite. - storeIndex(fx.location(), fx.format(), index); - } - // Further iterations should do nothing: - bytes = null; // do not clean them - clear(); - } - -/* - /// Testing. - public static void main(String[] av) { - byte[] bytes = new byte[1 << 20]; - ConstantPool cp = new ConstantPool(); - Fixups f = new Fixups(bytes); - boolean isU1 = false; - int span = 3; - int nextLoc = 0; - int[] locs = new int[100]; - final int[] indexes = new int[100]; - int iptr = 1; - for (int loc = 0; loc < bytes.length; loc++) { - if (loc == nextLoc && loc+1 < bytes.length) { - int fmt = (isU1 ? U1_FORMAT : U2_FORMAT); - Entry e = ConstantPool.getUtf8Entry("L"+loc); - f.add(loc, fmt, e); - isU1 ^= true; - if (iptr < 10) { - // Make it close in. - nextLoc += fmtLen(fmt) + (iptr < 5 ? 0 : 1); - } else { - nextLoc += span; - span = (int)(span * 1.77); - } - // Here are the bytes that would have gone here: - locs[iptr] = loc; - if (fmt == U1_FORMAT) { - indexes[iptr++] = (loc & 0xFF); - } else { - indexes[iptr++] = ((loc & 0xFF) << 8) | ((loc+1) & 0xFF); - ++loc; // skip a byte - } - continue; - } - bytes[loc] = (byte)loc; - } - System.out.println("size="+f.size() - +" overflow="+(f.bigDescs[BIGSIZE]-1)); - System.out.println("Fixups: "+f); - // Test collection contents. - assert(iptr == 1+f.size()); - List l = new ArrayList(f); - Collections.sort(l); // should not change the order - if (!l.equals(new ArrayList(f))) System.out.println("** disordered"); - f.setBytes(null); - if (!l.equals(new ArrayList(f))) System.out.println("** bad set 1"); - f.setBytes(bytes); - if (!l.equals(new ArrayList(f))) System.out.println("** bad set 2"); - Fixups f3 = new Fixups(f); - if (!l.equals(new ArrayList(f3))) System.out.println("** bad set 3"); - Iterator fi = f.iterator(); - for (int i = 1; i < iptr; i++) { - Fixup fx = (Fixup) fi.next(); - if (fx.location() != locs[i]) { - System.out.println("** "+fx+" != "+locs[i]); - } - if (fx.format() == U1_FORMAT) - System.out.println(fx+" -> "+bytes[locs[i]]); - else - System.out.println(fx+" -> "+bytes[locs[i]]+" "+bytes[locs[i]+1]); - } - assert(!fi.hasNext()); - indexes[0] = 1; // like iptr - Index ix = new Index("ix") { - public int indexOf(Entry e) { - return indexes[indexes[0]++]; - } - }; - f.finishRefs(ix); - for (int loc = 0; loc < bytes.length; loc++) { - if (bytes[loc] != (byte)loc) { - System.out.println("** ["+loc+"] = "+bytes[loc]+" != "+(byte)loc); - } - } - } -//*/ -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Histogram.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Histogram.java deleted file mode 100644 index e6ea5b4c077..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Histogram.java +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.Arrays; - -/** - * Histogram derived from an integer array of events (int[]). - * @author John Rose - */ -final class Histogram { - // Compact histogram representation: 4 bytes per distinct value, - // plus 5 words per distinct count. - protected final int[][] matrix; // multi-row matrix {{counti,valueij...}} - protected final int totalWeight; // sum of all counts - - // These are created eagerly also, since that saves work. - // They cost another 8 bytes per distinct value. - protected final int[] values; // unique values, sorted by value - protected final int[] counts; // counts, same order as values - - private static final long LOW32 = (long)-1 >>> 32; - - /** Build a histogram given a sequence of values. - * To save work, the input should be sorted, but need not be. - */ - public - Histogram(int[] valueSequence) { - long[] hist2col = computeHistogram2Col(maybeSort(valueSequence)); - int[][] table = makeTable(hist2col); - values = table[0]; - counts = table[1]; - this.matrix = makeMatrix(hist2col); - this.totalWeight = valueSequence.length; - assert(assertWellFormed(valueSequence)); - } - public - Histogram(int[] valueSequence, int start, int end) { - this(sortedSlice(valueSequence, start, end)); - } - - /** Build a histogram given a compact matrix of counts and values. */ - public - Histogram(int[][] matrix) { - // sort the rows - matrix = normalizeMatrix(matrix); // clone and sort - this.matrix = matrix; - int length = 0; - int weight = 0; - for (int i = 0; i < matrix.length; i++) { - int rowLength = matrix[i].length-1; - length += rowLength; - weight += matrix[i][0] * rowLength; - } - this.totalWeight = weight; - long[] hist2col = new long[length]; - int fillp = 0; - for (int i = 0; i < matrix.length; i++) { - for (int j = 1; j < matrix[i].length; j++) { - // sort key is value, so put it in the high 32! - hist2col[fillp++] = ((long) matrix[i][j] << 32) - | (LOW32 & matrix[i][0]); - } - } - assert(fillp == hist2col.length); - Arrays.sort(hist2col); - int[][] table = makeTable(hist2col); - values = table[1]; //backwards - counts = table[0]; //backwards - assert(assertWellFormed(null)); - } - - /** Histogram of int values, reported compactly as a ragged matrix, - * indexed by descending frequency rank. - *

- * Format of matrix: - * Each row in the matrix begins with an occurrence count, - * and continues with all int values that occur at that frequency. - *

-     *  int[][] matrix = {
-     *    { count1, value11, value12, value13, ...  },
-     *    { count2, value21, value22, ... },
-     *    ...
-     *  }
-     *  
- * The first column of the matrix { count1, count2, ... } - * is sorted in descending order, and contains no duplicates. - * Each row of the matrix (apart from its first element) - * is sorted in ascending order, and contains no duplicates. - * That is, each sequence { valuei1, valuei2, ... } is sorted. - */ - public - int[][] getMatrix() { return matrix; } - - public - int getRowCount() { return matrix.length; } - - public - int getRowFrequency(int rn) { return matrix[rn][0]; } - - public - int getRowLength(int rn) { return matrix[rn].length-1; } - - public - int getRowValue(int rn, int vn) { return matrix[rn][vn+1]; } - - public - int getRowWeight(int rn) { - return getRowFrequency(rn) * getRowLength(rn); - } - - public - int getTotalWeight() { - return totalWeight; - } - - public - int getTotalLength() { - return values.length; - } - - /** Returns an array of all values, sorted. */ - public - int[] getAllValues() { - - return values; - } - - /** Returns an array parallel with {@link #getValues}, - * with a frequency for each value. - */ - public - int[] getAllFrequencies() { - return counts; - } - - private static double log2 = Math.log(2); - - public - int getFrequency(int value) { - int pos = Arrays.binarySearch(values, value); - if (pos < 0) return 0; - assert(values[pos] == value); - return counts[pos]; - } - - public - double getBitLength(int value) { - double prob = (double) getFrequency(value) / getTotalWeight(); - return - Math.log(prob) / log2; - } - - public - double getRowBitLength(int rn) { - double prob = (double) getRowFrequency(rn) / getTotalWeight(); - return - Math.log(prob) / log2; - } - - public - interface BitMetric { - public double getBitLength(int value); - } - private final BitMetric bitMetric = new BitMetric() { - public double getBitLength(int value) { - return Histogram.this.getBitLength(value); - } - }; - public BitMetric getBitMetric() { - return bitMetric; - } - - /** bit-length is negative entropy: -H(matrix). */ - public - double getBitLength() { - double sum = 0; - for (int i = 0; i < matrix.length; i++) { - sum += getRowBitLength(i) * getRowWeight(i); - } - assert(0.1 > Math.abs(sum - getBitLength(bitMetric))); - return sum; - } - - /** bit-length in to another coding (cross-entropy) */ - public - double getBitLength(BitMetric len) { - double sum = 0; - for (int i = 0; i < matrix.length; i++) { - for (int j = 1; j < matrix[i].length; j++) { - sum += matrix[i][0] * len.getBitLength(matrix[i][j]); - } - } - return sum; - } - - private static - double round(double x, double scale) { - return Math.round(x * scale) / scale; - } - - /** Sort rows and columns. - * Merge adjacent rows with the same key element [0]. - * Make a fresh copy of all of it. - */ - public int[][] normalizeMatrix(int[][] matrix) { - long[] rowMap = new long[matrix.length]; - for (int i = 0; i < matrix.length; i++) { - if (matrix[i].length <= 1) continue; - int count = matrix[i][0]; - if (count <= 0) continue; - rowMap[i] = (long) count << 32 | i; - } - Arrays.sort(rowMap); - int[][] newMatrix = new int[matrix.length][]; - int prevCount = -1; - int fillp1 = 0; - int fillp2 = 0; - for (int i = 0; ; i++) { - int[] row; - if (i < matrix.length) { - long rowMapEntry = rowMap[rowMap.length-i-1]; - if (rowMapEntry == 0) continue; - row = matrix[(int)rowMapEntry]; - assert(rowMapEntry>>>32 == row[0]); - } else { - row = new int[]{ -1 }; // close it off - } - if (row[0] != prevCount && fillp2 > fillp1) { - // Close off previous run. - int length = 0; - for (int p = fillp1; p < fillp2; p++) { - int[] row0 = newMatrix[p]; // previously visited row - assert(row0[0] == prevCount); - length += row0.length-1; - } - int[] row1 = new int[1+length]; // cloned & consolidated row - row1[0] = prevCount; - int rfillp = 1; - for (int p = fillp1; p < fillp2; p++) { - int[] row0 = newMatrix[p]; // previously visited row - assert(row0[0] == prevCount); - System.arraycopy(row0, 1, row1, rfillp, row0.length-1); - rfillp += row0.length-1; - } - if (!isSorted(row1, 1, true)) { - Arrays.sort(row1, 1, row1.length); - int jfillp = 2; - // Detect and squeeze out duplicates. - for (int j = 2; j < row1.length; j++) { - if (row1[j] != row1[j-1]) - row1[jfillp++] = row1[j]; - } - if (jfillp < row1.length) { - // Reallocate because of lost duplicates. - int[] newRow1 = new int[jfillp]; - System.arraycopy(row1, 0, newRow1, 0, jfillp); - row1 = newRow1; - } - } - newMatrix[fillp1++] = row1; - fillp2 = fillp1; - } - if (i == matrix.length) - break; - prevCount = row[0]; - newMatrix[fillp2++] = row; - } - assert(fillp1 == fillp2); // no unfinished business - // Now drop missing rows. - matrix = newMatrix; - if (fillp1 < matrix.length) { - newMatrix = new int[fillp1][]; - System.arraycopy(matrix, 0, newMatrix, 0, fillp1); - matrix = newMatrix; - } - return matrix; - } - - public - String[] getRowTitles(String name) { - int totalUnique = getTotalLength(); - int ltotalWeight = getTotalWeight(); - String[] histTitles = new String[matrix.length]; - int cumWeight = 0; - int cumUnique = 0; - for (int i = 0; i < matrix.length; i++) { - int count = getRowFrequency(i); - int unique = getRowLength(i); - int weight = getRowWeight(i); - cumWeight += weight; - cumUnique += unique; - long wpct = ((long)cumWeight * 100 + ltotalWeight/2) / ltotalWeight; - long upct = ((long)cumUnique * 100 + totalUnique/2) / totalUnique; - double len = getRowBitLength(i); - assert(0.1 > Math.abs(len - getBitLength(matrix[i][1]))); - histTitles[i] = name+"["+i+"]" - +" len="+round(len,10) - +" ("+count+"*["+unique+"])" - +" ("+cumWeight+":"+wpct+"%)" - +" ["+cumUnique+":"+upct+"%]"; - } - return histTitles; - } - - /** Print a report of this histogram. - */ - public - void print(PrintStream out) { - print("hist", out); - } - - /** Print a report of this histogram. - */ - public - void print(String name, PrintStream out) { - print(name, getRowTitles(name), out); - } - - /** Print a report of this histogram. - */ - public - void print(String name, String[] histTitles, PrintStream out) { - int totalUnique = getTotalLength(); - int ltotalWeight = getTotalWeight(); - double tlen = getBitLength(); - double avgLen = tlen / ltotalWeight; - double avg = (double) ltotalWeight / totalUnique; - String title = (name - +" len="+round(tlen,10) - +" avgLen="+round(avgLen,10) - +" weight("+ltotalWeight+")" - +" unique["+totalUnique+"]" - +" avgWeight("+round(avg,100)+")"); - if (histTitles == null) { - out.println(title); - } else { - out.println(title+" {"); - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < matrix.length; i++) { - buf.setLength(0); - buf.append(" ").append(histTitles[i]).append(" {"); - for (int j = 1; j < matrix[i].length; j++) { - buf.append(" ").append(matrix[i][j]); - } - buf.append(" }"); - out.println(buf); - } - out.println("}"); - } - } - -/* - public static - int[][] makeHistogramMatrix(int[] values) { - // Make sure they are sorted. - values = maybeSort(values); - long[] hist2col = computeHistogram2Col(values); - int[][] matrix = makeMatrix(hist2col); - return matrix; - } -*/ - - private static - int[][] makeMatrix(long[] hist2col) { - // Sort by increasing count, then by increasing value. - Arrays.sort(hist2col); - int[] counts = new int[hist2col.length]; - for (int i = 0; i < counts.length; i++) { - counts[i] = (int)( hist2col[i] >>> 32 ); - } - long[] countHist = computeHistogram2Col(counts); - int[][] matrix = new int[countHist.length][]; - int histp = 0; // cursor into hist2col (increasing count, value) - int countp = 0; // cursor into countHist (increasing count) - // Do a join between hist2col (resorted) and countHist. - for (int i = matrix.length; --i >= 0; ) { - long countAndRep = countHist[countp++]; - int count = (int) (countAndRep); // what is the value count? - int repeat = (int) (countAndRep >>> 32); // # times repeated? - int[] row = new int[1+repeat]; - row[0] = count; - for (int j = 0; j < repeat; j++) { - long countAndValue = hist2col[histp++]; - assert(countAndValue >>> 32 == count); - row[1+j] = (int) countAndValue; - } - matrix[i] = row; - } - assert(histp == hist2col.length); - return matrix; - } - - private static - int[][] makeTable(long[] hist2col) { - int[][] table = new int[2][hist2col.length]; - // Break apart the entries in hist2col. - // table[0] gets values, table[1] gets entries. - for (int i = 0; i < hist2col.length; i++) { - table[0][i] = (int)( hist2col[i] ); - table[1][i] = (int)( hist2col[i] >>> 32 ); - } - return table; - } - - /** Simple two-column histogram. Contains repeated counts. - * Assumes input is sorted. Does not sort output columns. - *

- * Format of result: - *

-     *  long[] hist = {
-     *    (count1 << 32) | (value1),
-     *    (count2 << 32) | (value2),
-     *    ...
-     *  }
-     *  
- * In addition, the sequence {valuei...} is guaranteed to be sorted. - * Note that resorting this using Arrays.sort() will reorder the - * entries by increasing count. - */ - private static - long[] computeHistogram2Col(int[] sortedValues) { - switch (sortedValues.length) { - case 0: - return new long[]{ }; - case 1: - return new long[]{ ((long)1 << 32) | (LOW32 & sortedValues[0]) }; - } - long[] hist = null; - for (boolean sizeOnly = true; ; sizeOnly = false) { - int prevIndex = -1; - int prevValue = sortedValues[0] ^ -1; // force a difference - int prevCount = 0; - for (int i = 0; i <= sortedValues.length; i++) { - int thisValue; - if (i < sortedValues.length) - thisValue = sortedValues[i]; - else - thisValue = prevValue ^ -1; // force a difference at end - if (thisValue == prevValue) { - prevCount += 1; - } else { - // Found a new value. - if (!sizeOnly && prevCount != 0) { - // Save away previous value. - hist[prevIndex] = ((long)prevCount << 32) - | (LOW32 & prevValue); - } - prevValue = thisValue; - prevCount = 1; - prevIndex += 1; - } - } - if (sizeOnly) { - // Finished the sizing pass. Allocate the histogram. - hist = new long[prevIndex]; - } else { - break; // done - } - } - return hist; - } - - /** Regroup the histogram, so that it becomes an approximate histogram - * whose rows are of the given lengths. - * If matrix rows must be split, the latter parts (larger values) - * are placed earlier in the new matrix. - * If matrix rows are joined, they are resorted into ascending order. - * In the new histogram, the counts are averaged over row entries. - */ - private static - int[][] regroupHistogram(int[][] matrix, int[] groups) { - long oldEntries = 0; - for (int i = 0; i < matrix.length; i++) { - oldEntries += matrix[i].length-1; - } - long newEntries = 0; - for (int ni = 0; ni < groups.length; ni++) { - newEntries += groups[ni]; - } - if (newEntries > oldEntries) { - int newlen = groups.length; - long ok = oldEntries; - for (int ni = 0; ni < groups.length; ni++) { - if (ok < groups[ni]) { - int[] newGroups = new int[ni+1]; - System.arraycopy(groups, 0, newGroups, 0, ni+1); - groups = newGroups; - groups[ni] = (int) ok; - ok = 0; - break; - } - ok -= groups[ni]; - } - } else { - long excess = oldEntries - newEntries; - int[] newGroups = new int[groups.length+1]; - System.arraycopy(groups, 0, newGroups, 0, groups.length); - newGroups[groups.length] = (int) excess; - groups = newGroups; - } - int[][] newMatrix = new int[groups.length][]; - // Fill pointers. - int i = 0; // into matrix - int jMin = 1; - int jMax = matrix[i].length; - for (int ni = 0; ni < groups.length; ni++) { - int groupLength = groups[ni]; - int[] group = new int[1+groupLength]; - long groupWeight = 0; // count of all in new group - newMatrix[ni] = group; - int njFill = 1; - while (njFill < group.length) { - int len = group.length - njFill; - while (jMin == jMax) { - jMin = 1; - jMax = matrix[++i].length; - } - if (len > jMax - jMin) len = jMax - jMin; - groupWeight += (long) matrix[i][0] * len; - System.arraycopy(matrix[i], jMax - len, group, njFill, len); - jMax -= len; - njFill += len; - } - Arrays.sort(group, 1, group.length); - // compute average count of new group: - group[0] = (int) ((groupWeight + groupLength/2) / groupLength); - } - assert(jMin == jMax); - assert(i == matrix.length-1); - return newMatrix; - } - - public static - Histogram makeByteHistogram(InputStream bytes) throws IOException { - byte[] buf = new byte[1<<12]; - int[] tally = new int[1<<8]; - for (int nr; (nr = bytes.read(buf)) > 0; ) { - for (int i = 0; i < nr; i++) { - tally[buf[i] & 0xFF] += 1; - } - } - // Build a matrix. - int[][] matrix = new int[1<<8][2]; - for (int i = 0; i < tally.length; i++) { - matrix[i][0] = tally[i]; - matrix[i][1] = i; - } - return new Histogram(matrix); - } - - /** Slice and sort the given input array. */ - private static - int[] sortedSlice(int[] valueSequence, int start, int end) { - if (start == 0 && end == valueSequence.length && - isSorted(valueSequence, 0, false)) { - return valueSequence; - } else { - int[] slice = new int[end-start]; - System.arraycopy(valueSequence, start, slice, 0, slice.length); - Arrays.sort(slice); - return slice; - } - } - - /** Tell if an array is sorted. */ - private static - boolean isSorted(int[] values, int from, boolean strict) { - for (int i = from+1; i < values.length; i++) { - if (strict ? !(values[i-1] < values[i]) - : !(values[i-1] <= values[i])) { - return false; // found witness to disorder - } - } - return true; // no witness => sorted - } - - /** Clone and sort the array, if not already sorted. */ - private static - int[] maybeSort(int[] values) { - if (!isSorted(values, 0, false)) { - values = values.clone(); - Arrays.sort(values); - } - return values; - } - - - /// Debug stuff follows. - - private boolean assertWellFormed(int[] valueSequence) { -/* - // Sanity check. - int weight = 0; - int vlength = 0; - for (int i = 0; i < matrix.length; i++) { - int vlengthi = (matrix[i].length-1); - int count = matrix[i][0]; - assert(vlengthi > 0); // no empty rows - assert(count > 0); // no impossible rows - vlength += vlengthi; - weight += count * vlengthi; - } - assert(isSorted(values, 0, true)); - // make sure the counts all add up - assert(totalWeight == weight); - assert(vlength == values.length); - assert(vlength == counts.length); - int weight2 = 0; - for (int i = 0; i < counts.length; i++) { - weight2 += counts[i]; - } - assert(weight2 == weight); - int[] revcol1 = new int[matrix.length]; //1st matrix colunm - for (int i = 0; i < matrix.length; i++) { - // spot checking: try a random query on each matrix row - assert(matrix[i].length > 1); - revcol1[matrix.length-i-1] = matrix[i][0]; - assert(isSorted(matrix[i], 1, true)); - int rand = (matrix[i].length+1) / 2; - int val = matrix[i][rand]; - int count = matrix[i][0]; - int pos = Arrays.binarySearch(values, val); - assert(values[pos] == val); - assert(counts[pos] == matrix[i][0]); - if (valueSequence != null) { - int count2 = 0; - for (int j = 0; j < valueSequence.length; j++) { - if (valueSequence[j] == val) count2++; - } - assert(count2 == count); - } - } - assert(isSorted(revcol1, 0, true)); -//*/ - return true; - } - -/* - public static - int[] readValuesFrom(InputStream instr) { - return readValuesFrom(new InputStreamReader(instr)); - } - public static - int[] readValuesFrom(Reader inrdr) { - inrdr = new BufferedReader(inrdr); - final StreamTokenizer in = new StreamTokenizer(inrdr); - final int TT_NOTHING = -99; - in.commentChar('#'); - return readValuesFrom(new Iterator() { - int token = TT_NOTHING; - private int getToken() { - if (token == TT_NOTHING) { - try { - token = in.nextToken(); - assert(token != TT_NOTHING); - } catch (IOException ee) { - throw new RuntimeException(ee); - } - } - return token; - } - public boolean hasNext() { - return getToken() != StreamTokenizer.TT_EOF; - } - public Object next() { - int ntok = getToken(); - token = TT_NOTHING; - switch (ntok) { - case StreamTokenizer.TT_EOF: - throw new NoSuchElementException(); - case StreamTokenizer.TT_NUMBER: - return new Integer((int) in.nval); - default: - assert(false); - return null; - } - } - public void remove() { - throw new UnsupportedOperationException(); - } - }); - } - public static - int[] readValuesFrom(Iterator iter) { - return readValuesFrom(iter, 0); - } - public static - int[] readValuesFrom(Iterator iter, int initSize) { - int[] na = new int[Math.max(10, initSize)]; - int np = 0; - while (iter.hasNext()) { - Integer val = (Integer) iter.next(); - if (np == na.length) { - int[] na2 = new int[np*2]; - System.arraycopy(na, 0, na2, 0, np); - na = na2; - } - na[np++] = val.intValue(); - } - if (np != na.length) { - int[] na2 = new int[np]; - System.arraycopy(na, 0, na2, 0, np); - na = na2; - } - return na; - } - - public static - Histogram makeByteHistogram(byte[] bytes) { - try { - return makeByteHistogram(new ByteArrayInputStream(bytes)); - } catch (IOException ee) { - throw new RuntimeException(ee); - } - } - - public static - void main(String[] av) throws IOException { - if (av.length > 0 && av[0].equals("-r")) { - int[] values = new int[Integer.parseInt(av[1])]; - int limit = values.length; - if (av.length >= 3) { - limit = (int)( limit * Double.parseDouble(av[2]) ); - } - Random rnd = new Random(); - for (int i = 0; i < values.length; i++) { - values[i] = rnd.nextInt(limit);; - } - Histogram rh = new Histogram(values); - rh.print("random", System.out); - return; - } - if (av.length > 0 && av[0].equals("-s")) { - int[] values = readValuesFrom(System.in); - Random rnd = new Random(); - for (int i = values.length; --i > 0; ) { - int j = rnd.nextInt(i+1); - if (j < i) { - int tem = values[i]; - values[i] = values[j]; - values[j] = tem; - } - } - for (int i = 0; i < values.length; i++) - System.out.println(values[i]); - return; - } - if (av.length > 0 && av[0].equals("-e")) { - // edge cases - new Histogram(new int[][] { - {1, 11, 111}, - {0, 123, 456}, - {1, 111, 1111}, - {0, 456, 123}, - {3}, - {}, - {3}, - {2, 22}, - {4} - }).print(System.out); - return; - } - if (av.length > 0 && av[0].equals("-b")) { - // edge cases - Histogram bh = makeByteHistogram(System.in); - bh.print("bytes", System.out); - return; - } - boolean regroup = false; - if (av.length > 0 && av[0].equals("-g")) { - regroup = true; - } - - int[] values = readValuesFrom(System.in); - Histogram h = new Histogram(values); - if (!regroup) - h.print(System.out); - if (regroup) { - int[] groups = new int[12]; - for (int i = 0; i < groups.length; i++) { - groups[i] = 1< 0); - assert(pc+length <= bytes.length); - // Speed hack: Instruction.next reuses self if possible. - if (reuse != null && !reuse.special) { - reuse.reset(bytes, pc, bc, w, length); - return reuse; - } - return new Instruction(bytes, pc, bc, w, length); - } - - // Return the constant pool reference type, or 0 if none. - public byte getCPTag() { - return BC_TAG[w][bc]; - } - - // Return the constant pool index, or -1 if none. - public int getCPIndex() { - int indexLoc = BC_INDEX[w][bc]; - if (indexLoc == 0) return -1; - assert(w == 0); - if (length == 2) - return getByte(bytes, pc+indexLoc); // _ldc opcode only - else - return getShort(bytes, pc+indexLoc); - } - - public void setCPIndex(int cpi) { - int indexLoc = BC_INDEX[w][bc]; - assert(indexLoc != 0); - if (length == 2) - setByte(bytes, pc+indexLoc, cpi); // _ldc opcode only - else - setShort(bytes, pc+indexLoc, cpi); - assert(getCPIndex() == cpi); - } - - public ConstantPool.Entry getCPRef(ConstantPool.Entry[] cpMap) { - int index = getCPIndex(); - return (index < 0) ? null : cpMap[index]; - } - - // Return the slot of the affected local, or -1 if none. - public int getLocalSlot() { - int slotLoc = BC_SLOT[w][bc]; - if (slotLoc == 0) return -1; - if (w == 0) - return getByte(bytes, pc+slotLoc); - else - return getShort(bytes, pc+slotLoc); - } - - // Return the target of the branch, or -1 if none. - public int getBranchLabel() { - int branchLoc = BC_BRANCH[w][bc]; - if (branchLoc == 0) return -1; - assert(w == 0); - assert(length == 3 || length == 5); - int offset; - if (length == 3) - offset = (short)getShort(bytes, pc+branchLoc); - else - offset = getInt(bytes, pc+branchLoc); - assert(offset+pc >= 0); - assert(offset+pc <= bytes.length); - return offset+pc; - } - - public void setBranchLabel(int targetPC) { - int branchLoc = BC_BRANCH[w][bc]; - assert(branchLoc != 0); - if (length == 3) - setShort(bytes, pc+branchLoc, targetPC-pc); - else - setInt(bytes, pc+branchLoc, targetPC-pc); - assert(targetPC == getBranchLabel()); - } - - // Return the trailing constant in the instruction (as a signed value). - // Return 0 if there is none. - public int getConstant() { - int conLoc = BC_CON[w][bc]; - if (conLoc == 0) return 0; - switch (length - conLoc) { - case 1: return (byte) getByte(bytes, pc+conLoc); - case 2: return (short) getShort(bytes, pc+conLoc); - } - assert(false); - return 0; - } - - public void setConstant(int con) { - int conLoc = BC_CON[w][bc]; - assert(conLoc != 0); - switch (length - conLoc) { - case 1: setByte(bytes, pc+conLoc, con); break; - case 2: setShort(bytes, pc+conLoc, con); break; - } - assert(con == getConstant()); - } - - public abstract static class Switch extends Instruction { - // Each case is a (value, label) pair, indexed 0 <= n < caseCount - public abstract int getCaseCount(); - public abstract int getCaseValue(int n); - public abstract int getCaseLabel(int n); - public abstract void setCaseCount(int caseCount); - public abstract void setCaseValue(int n, int value); - public abstract void setCaseLabel(int n, int targetPC); - protected abstract int getLength(int caseCount); - - public int getDefaultLabel() { return intAt(0)+pc; } - public void setDefaultLabel(int targetPC) { setIntAt(0, targetPC-pc); } - - protected int apc; // aligned pc (table base) - protected int intAt(int n) { return getInt(bytes, apc + n*4); } - protected void setIntAt(int n, int x) { setInt(bytes, apc + n*4, x); } - protected Switch(byte[] bytes, int pc, int bc) { - super(bytes, pc, bc, /*w*/0, /*length*/0); - this.apc = alignPC(pc+1); - this.special = true; - length = getLength(getCaseCount()); - } - public int getAlignedPC() { return apc; } - public String toString() { - String s = super.toString(); - s += " Default:"+labstr(getDefaultLabel()); - int caseCount = getCaseCount(); - for (int i = 0; i < caseCount; i++) { - s += "\n\tCase "+getCaseValue(i)+":"+labstr(getCaseLabel(i)); - } - return s; - } - public static int alignPC(int apc) { - while (apc % 4 != 0) ++apc; - return apc; - } - } - - public static class TableSwitch extends Switch { - // apc: (df, lo, hi, (hi-lo+1)*(label)) - public int getLowCase() { return intAt(1); } - public int getHighCase() { return intAt(2); } - public int getCaseCount() { return intAt(2)-intAt(1)+1; } - public int getCaseValue(int n) { return getLowCase()+n; } - public int getCaseLabel(int n) { return intAt(3+n)+pc; } - - public void setLowCase(int val) { setIntAt(1, val); } - public void setHighCase(int val) { setIntAt(2, val); } - public void setCaseLabel(int n, int tpc) { setIntAt(3+n, tpc-pc); } - public void setCaseCount(int caseCount) { - setHighCase(getLowCase() + caseCount - 1); - length = getLength(caseCount); - } - public void setCaseValue(int n, int val) { - if (n != 0) throw new UnsupportedOperationException(); - int caseCount = getCaseCount(); - setLowCase(val); - setCaseCount(caseCount); // keep invariant - } - - TableSwitch(byte[] bytes, int pc) { - super(bytes, pc, _tableswitch); - } - protected int getLength(int caseCount) { - return (apc-pc) + (3 + caseCount) * 4; - } - } - - public static class LookupSwitch extends Switch { - // apc: (df, nc, nc*(case, label)) - public int getCaseCount() { return intAt(1); } - public int getCaseValue(int n) { return intAt(2+n*2+0); } - public int getCaseLabel(int n) { return intAt(2+n*2+1)+pc; } - - public void setCaseCount(int caseCount) { - setIntAt(1, caseCount); - length = getLength(caseCount); - } - public void setCaseValue(int n, int val) { setIntAt(2+n*2+0, val); } - public void setCaseLabel(int n, int tpc) { setIntAt(2+n*2+1, tpc-pc); } - - LookupSwitch(byte[] bytes, int pc) { - super(bytes, pc, _lookupswitch); - } - protected int getLength(int caseCount) { - return (apc-pc) + (2 + caseCount*2) * 4; - } - } - - /** Two instructions are equal if they have the same bytes. */ - public boolean equals(Object o) { - return (o != null) && (o.getClass() == Instruction.class) - && equals((Instruction) o); - } - - public int hashCode() { - int hash = 3; - hash = 11 * hash + Arrays.hashCode(this.bytes); - hash = 11 * hash + this.pc; - hash = 11 * hash + this.bc; - hash = 11 * hash + this.w; - hash = 11 * hash + this.length; - return hash; - } - - public boolean equals(Instruction that) { - if (this.pc != that.pc) return false; - if (this.bc != that.bc) return false; - if (this.w != that.w) return false; - if (this.length != that.length) return false; - for (int i = 1; i < length; i++) { - if (this.bytes[this.pc+i] != that.bytes[that.pc+i]) - return false; - } - return true; - } - - static String labstr(int pc) { - if (pc >= 0 && pc < 100000) - return ((100000+pc)+"").substring(1); - return pc+""; - } - public String toString() { - return toString(null); - } - public String toString(ConstantPool.Entry[] cpMap) { - String s = labstr(pc) + ": "; - if (bc >= _bytecode_limit) { - s += Integer.toHexString(bc); - return s; - } - if (w == 1) s += "wide "; - String bcname = (bc < BC_NAME.length)? BC_NAME[bc]: null; - if (bcname == null) { - return s+"opcode#"+bc; - } - s += bcname; - int tag = getCPTag(); - if (tag != 0) s += " "+ConstantPool.tagName(tag)+":"; - int idx = getCPIndex(); - if (idx >= 0) s += (cpMap == null) ? ""+idx : "="+cpMap[idx].stringValue(); - int slt = getLocalSlot(); - if (slt >= 0) s += " Local:"+slt; - int lab = getBranchLabel(); - if (lab >= 0) s += " To:"+labstr(lab); - int con = getConstant(); - if (con != 0) s += " Con:"+con; - return s; - } - - - //public static byte constantPoolTagFor(int bc) { return BC_TAG[0][bc]; } - - /// Fetching values from byte arrays: - - public int getIntAt(int off) { - return getInt(bytes, pc+off); - } - public int getShortAt(int off) { - return getShort(bytes, pc+off); - } - public int getByteAt(int off) { - return getByte(bytes, pc+off); - } - - - public static int getInt(byte[] bytes, int pc) { - return (getShort(bytes, pc+0) << 16) + (getShort(bytes, pc+2) << 0); - } - public static int getShort(byte[] bytes, int pc) { - return (getByte(bytes, pc+0) << 8) + (getByte(bytes, pc+1) << 0); - } - public static int getByte(byte[] bytes, int pc) { - return bytes[pc] & 0xFF; - } - - - public static void setInt(byte[] bytes, int pc, int x) { - setShort(bytes, pc+0, x >> 16); - setShort(bytes, pc+2, x >> 0); - } - public static void setShort(byte[] bytes, int pc, int x) { - setByte(bytes, pc+0, x >> 8); - setByte(bytes, pc+1, x >> 0); - } - public static void setByte(byte[] bytes, int pc, int x) { - bytes[pc] = (byte)x; - } - - // some bytecode classifiers - - - public static boolean isNonstandard(int bc) { - return BC_LENGTH[0][bc] < 0; - } - - public static int opLength(int bc) { - int l = BC_LENGTH[0][bc]; - assert(l > 0); - return l; - } - public static int opWideLength(int bc) { - int l = BC_LENGTH[1][bc]; - assert(l > 0); - return l; - } - - public static boolean isLocalSlotOp(int bc) { - return (bc < BC_SLOT[0].length && BC_SLOT[0][bc] > 0); - } - - public static boolean isBranchOp(int bc) { - return (bc < BC_BRANCH[0].length && BC_BRANCH[0][bc] > 0); - } - - public static boolean isCPRefOp(int bc) { - if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return true; - if (bc >= _xldc_op && bc < _xldc_limit) return true; - if (bc == _invokespecial_int || bc == _invokestatic_int) return true; - return false; - } - - public static byte getCPRefOpTag(int bc) { - if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return BC_TAG[0][bc]; - if (bc >= _xldc_op && bc < _xldc_limit) return CONSTANT_LoadableValue; - if (bc == _invokestatic_int || bc == _invokespecial_int) return CONSTANT_InterfaceMethodref; - return CONSTANT_None; - } - - public static boolean isFieldOp(int bc) { - return (bc >= _getstatic && bc <= _putfield); - } - - public static boolean isInvokeInitOp(int bc) { - return (bc >= _invokeinit_op && bc < _invokeinit_limit); - } - - public static boolean isSelfLinkerOp(int bc) { - return (bc >= _self_linker_op && bc < _self_linker_limit); - } - - /// Format definitions. - - private static final byte[][] BC_LENGTH = new byte[2][0x100]; - private static final byte[][] BC_INDEX = new byte[2][0x100]; - private static final byte[][] BC_TAG = new byte[2][0x100]; - private static final byte[][] BC_BRANCH = new byte[2][0x100]; - private static final byte[][] BC_SLOT = new byte[2][0x100]; - private static final byte[][] BC_CON = new byte[2][0x100]; - private static final String[] BC_NAME = new String[0x100]; // debug only - private static final String[][] BC_FORMAT = new String[2][_bytecode_limit]; // debug only - static { - for (int i = 0; i < _bytecode_limit; i++) { - BC_LENGTH[0][i] = -1; - BC_LENGTH[1][i] = -1; - } - def("b", _nop, _dconst_1); - def("bx", _bipush); - def("bxx", _sipush); - def("bk", _ldc); // do not pack - def("bkk", _ldc_w, _ldc2_w); // do not pack - def("blwbll", _iload, _aload); - def("b", _iload_0, _saload); - def("blwbll", _istore, _astore); - def("b", _istore_0, _lxor); - def("blxwbllxx", _iinc); - def("b", _i2l, _dcmpg); - def("boo", _ifeq, _jsr); // pack oo - def("blwbll", _ret); - def("", _tableswitch, _lookupswitch); // pack all ints, omit padding - def("b", _ireturn, _return); - def("bkf", _getstatic, _putfield); // pack kf (base=Field) - def("bkm", _invokevirtual, _invokestatic); // pack kn (base=Method) - def("bkixx", _invokeinterface); // pack ki (base=IMethod), omit xx - def("bkyxx", _invokedynamic); // pack ky (base=Any), omit xx - def("bkc", _new); // pack kc - def("bx", _newarray); - def("bkc", _anewarray); // pack kc - def("b", _arraylength, _athrow); - def("bkc", _checkcast, _instanceof); // pack kc - def("b", _monitorenter, _monitorexit); - def("", _wide); - def("bkcx", _multianewarray); // pack kc - def("boo", _ifnull, _ifnonnull); // pack oo - def("boooo", _goto_w, _jsr_w); // pack oooo - for (int i = 0; i < _bytecode_limit; i++) { - //System.out.println(i+": l="+BC_LENGTH[0][i]+" i="+BC_INDEX[0][i]); - //assert(BC_LENGTH[0][i] != -1); - if (BC_LENGTH[0][i] == -1) { - continue; // unknown opcode - } - - // Have a complete mapping, to support spurious _wide prefixes. - if (BC_LENGTH[1][i] == -1) - BC_LENGTH[1][i] = (byte)(1+BC_LENGTH[0][i]); - } - - String names = - "nop aconst_null iconst_m1 iconst_0 iconst_1 iconst_2 iconst_3 iconst_4 "+ - "iconst_5 lconst_0 lconst_1 fconst_0 fconst_1 fconst_2 dconst_0 dconst_1 "+ - "bipush sipush ldc ldc_w ldc2_w iload lload fload dload aload iload_0 "+ - "iload_1 iload_2 iload_3 lload_0 lload_1 lload_2 lload_3 fload_0 fload_1 "+ - "fload_2 fload_3 dload_0 dload_1 dload_2 dload_3 aload_0 aload_1 aload_2 "+ - "aload_3 iaload laload faload daload aaload baload caload saload istore "+ - "lstore fstore dstore astore istore_0 istore_1 istore_2 istore_3 lstore_0 "+ - "lstore_1 lstore_2 lstore_3 fstore_0 fstore_1 fstore_2 fstore_3 dstore_0 "+ - "dstore_1 dstore_2 dstore_3 astore_0 astore_1 astore_2 astore_3 iastore "+ - "lastore fastore dastore aastore bastore castore sastore pop pop2 dup "+ - "dup_x1 dup_x2 dup2 dup2_x1 dup2_x2 swap iadd ladd fadd dadd isub lsub "+ - "fsub dsub imul lmul fmul dmul idiv ldiv fdiv ddiv irem lrem frem drem "+ - "ineg lneg fneg dneg ishl lshl ishr lshr iushr lushr iand land ior lor "+ - "ixor lxor iinc i2l i2f i2d l2i l2f l2d f2i f2l f2d d2i d2l d2f i2b i2c "+ - "i2s lcmp fcmpl fcmpg dcmpl dcmpg ifeq ifne iflt ifge ifgt ifle if_icmpeq "+ - "if_icmpne if_icmplt if_icmpge if_icmpgt if_icmple if_acmpeq if_acmpne "+ - "goto jsr ret tableswitch lookupswitch ireturn lreturn freturn dreturn "+ - "areturn return getstatic putstatic getfield putfield invokevirtual "+ - "invokespecial invokestatic invokeinterface invokedynamic new newarray "+ - "anewarray arraylength athrow checkcast instanceof monitorenter "+ - "monitorexit wide multianewarray ifnull ifnonnull goto_w jsr_w "; - for (int bc = 0; names.length() > 0; bc++) { - int sp = names.indexOf(' '); - BC_NAME[bc] = names.substring(0, sp); - names = names.substring(sp+1); - } - } - public static String byteName(int bc) { - String iname; - if (bc < BC_NAME.length && BC_NAME[bc] != null) { - iname = BC_NAME[bc]; - } else if (isSelfLinkerOp(bc)) { - int idx = (bc - _self_linker_op); - boolean isSuper = (idx >= _self_linker_super_flag); - if (isSuper) idx -= _self_linker_super_flag; - boolean isAload = (idx >= _self_linker_aload_flag); - if (isAload) idx -= _self_linker_aload_flag; - int origBC = _first_linker_op + idx; - assert(origBC >= _first_linker_op && origBC <= _last_linker_op); - iname = BC_NAME[origBC]; - iname += (isSuper ? "_super" : "_this"); - if (isAload) iname = "aload_0&" + iname; - iname = "*"+iname; - } else if (isInvokeInitOp(bc)) { - int idx = (bc - _invokeinit_op); - switch (idx) { - case _invokeinit_self_option: - iname = "*invokespecial_init_this"; break; - case _invokeinit_super_option: - iname = "*invokespecial_init_super"; break; - default: - assert(idx == _invokeinit_new_option); - iname = "*invokespecial_init_new"; break; - } - } else { - switch (bc) { - case _ildc: iname = "*ildc"; break; - case _fldc: iname = "*fldc"; break; - case _ildc_w: iname = "*ildc_w"; break; - case _fldc_w: iname = "*fldc_w"; break; - case _dldc2_w: iname = "*dldc2_w"; break; - case _cldc: iname = "*cldc"; break; - case _cldc_w: iname = "*cldc_w"; break; - case _qldc: iname = "*qldc"; break; - case _qldc_w: iname = "*qldc_w"; break; - case _byte_escape: iname = "*byte_escape"; break; - case _ref_escape: iname = "*ref_escape"; break; - case _end_marker: iname = "*end"; break; - default: iname = "*bc#"+bc; break; - } - } - return iname; - } - private static int BW = 4; // width of classification field - private static void def(String fmt, int bc) { - def(fmt, bc, bc); - } - private static void def(String fmt, int from_bc, int to_bc) { - String[] fmts = { fmt, null }; - if (fmt.indexOf('w') > 0) { - fmts[1] = fmt.substring(fmt.indexOf('w')); - fmts[0] = fmt.substring(0, fmt.indexOf('w')); - } - for (int w = 0; w <= 1; w++) { - fmt = fmts[w]; - if (fmt == null) continue; - int length = fmt.length(); - int index = Math.max(0, fmt.indexOf('k')); - int tag = CONSTANT_None; - int branch = Math.max(0, fmt.indexOf('o')); - int slot = Math.max(0, fmt.indexOf('l')); - int con = Math.max(0, fmt.indexOf('x')); - if (index > 0 && index+1 < length) { - switch (fmt.charAt(index+1)) { - case 'c': tag = CONSTANT_Class; break; - case 'k': tag = CONSTANT_LoadableValue; break; - case 'f': tag = CONSTANT_Fieldref; break; - case 'm': tag = CONSTANT_Methodref; break; - case 'i': tag = CONSTANT_InterfaceMethodref; break; - case 'y': tag = CONSTANT_InvokeDynamic; break; - } - assert(tag != CONSTANT_None); - } else if (index > 0 && length == 2) { - assert(from_bc == _ldc); - tag = CONSTANT_LoadableValue; // _ldc opcode only - } - for (int bc = from_bc; bc <= to_bc; bc++) { - BC_FORMAT[w][bc] = fmt; - assert(BC_LENGTH[w][bc] == -1); - BC_LENGTH[w][bc] = (byte) length; - BC_INDEX[w][bc] = (byte) index; - BC_TAG[w][bc] = (byte) tag; - assert(!(index == 0 && tag != CONSTANT_None)); - BC_BRANCH[w][bc] = (byte) branch; - BC_SLOT[w][bc] = (byte) slot; - assert(branch == 0 || slot == 0); // not both branch & local - assert(branch == 0 || index == 0); // not both branch & cp - assert(slot == 0 || index == 0); // not both local & cp - BC_CON[w][bc] = (byte) con; - } - } - } - - public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap, - Package.Version clsVersion) throws FormatException { - Instruction i = at(code, 0); - while (i != null) { - int opcode = i.getBC(); - if (opcode < _nop || opcode > _jsr_w) { - String message = "illegal opcode: " + opcode + " " + i; - throw new FormatException(message); - } - ConstantPool.Entry e = i.getCPRef(cpMap); - if (e != null) { - byte tag = i.getCPTag(); - boolean match = e.tagMatches(tag); - if (!match && - (i.bc == _invokespecial || i.bc == _invokestatic) && - e.tagMatches(CONSTANT_InterfaceMethodref) && - clsVersion.greaterThan(Constants.JAVA7_MAX_CLASS_VERSION)) { - match = true; - } - if (!match) { - String message = "illegal reference, expected type=" - + ConstantPool.tagName(tag) + ": " - + i.toString(cpMap); - throw new FormatException(message); - } - } - i = i.next(); - } - } - static class FormatException extends IOException { - @java.io.Serial - private static final long serialVersionUID = 3175572275651367015L; - - FormatException(String message) { - super(message); - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java deleted file mode 100644 index 86392160c9e..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package com.sun.java.util.jar.pack; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; -import java.util.zip.CRC32; -import java.util.zip.Deflater; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -@SuppressWarnings({"removal"}) -class NativeUnpack { - // Pointer to the native unpacker obj - private long unpackerPtr; - - // Input stream. - private BufferedInputStream in; - - private static synchronized native void initIDs(); - - // Starts processing at the indicated position in the buffer. - // If the buffer is null, the readInputFn callback is used to get bytes. - // Returns (s<<32|f), the number of following segments and files. - private synchronized native long start(ByteBuffer buf, long offset); - - // Returns true if there's another, and fills in the parts. - private synchronized native boolean getNextFile(Object[] parts); - - private synchronized native ByteBuffer getUnusedInput(); - - // Resets the engine and frees all resources. - // Returns total number of bytes consumed by the engine. - private synchronized native long finish(); - - // Setting state in the unpacker. - protected synchronized native boolean setOption(String opt, String value); - protected synchronized native String getOption(String opt); - - private int _verbose; - - // State for progress bar: - private long _byteCount; // bytes read in current segment - private int _segCount; // number of segs scanned - private int _fileCount; // number of files written - private long _estByteLimit; // estimate of eventual total - private int _estSegLimit; // ditto - private int _estFileLimit; // ditto - private int _prevPercent = -1; // for monotonicity - - private final CRC32 _crc32 = new CRC32(); - private byte[] _buf = new byte[1<<14]; - - private UnpackerImpl _p200; - private PropMap _props; - - static { - // If loading from stand alone build uncomment this. - // System.loadLibrary("unpack"); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { - public Void run() { - System.loadLibrary("unpack"); - return null; - } - }); - initIDs(); - } - - NativeUnpack(UnpackerImpl p200) { - super(); - _p200 = p200; - _props = p200.props; - p200._nunp = this; - } - - // for JNI callbacks - private static Object currentInstance() { - UnpackerImpl p200 = (UnpackerImpl) Utils.getTLGlobals(); - return (p200 == null)? null: p200._nunp; - } - - private synchronized long getUnpackerPtr() { - return unpackerPtr; - } - - // Callback from the unpacker engine to get more data. - private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException { - if (in == null) return 0; // nothing is readable - long maxlen = pbuf.capacity() - pbuf.position(); - assert(minlen <= maxlen); // don't talk nonsense - long numread = 0; - int steps = 0; - while (numread < minlen) { - steps++; - // read available input, up to buf.length or maxlen - int readlen = _buf.length; - if (readlen > (maxlen - numread)) - readlen = (int)(maxlen - numread); - int nr = in.read(_buf, 0, readlen); - if (nr <= 0) break; - numread += nr; - assert(numread <= maxlen); - // %%% get rid of this extra copy by using nio? - pbuf.put(_buf, 0, nr); - } - if (_verbose > 1) - Utils.log.fine("readInputFn("+minlen+","+maxlen+") => "+numread+" steps="+steps); - if (maxlen > 100) { - _estByteLimit = _byteCount + maxlen; - } else { - _estByteLimit = (_byteCount + numread) * 20; - } - _byteCount += numread; - updateProgress(); - return numread; - } - - private void updateProgress() { - // Progress is a combination of segment reading and file writing. - final double READ_WT = 0.33; - final double WRITE_WT = 0.67; - double readProgress = _segCount; - if (_estByteLimit > 0 && _byteCount > 0) - readProgress += (double)_byteCount / _estByteLimit; - double writeProgress = _fileCount; - double scaledProgress - = READ_WT * readProgress / Math.max(_estSegLimit,1) - + WRITE_WT * writeProgress / Math.max(_estFileLimit,1); - int percent = (int) Math.round(100*scaledProgress); - if (percent > 100) percent = 100; - if (percent > _prevPercent) { - _prevPercent = percent; - _props.setInteger(Pack200.Unpacker.PROGRESS, percent); - if (_verbose > 0) - Utils.log.info("progress = "+percent); - } - } - - private void copyInOption(String opt) { - String val = _props.getProperty(opt); - if (_verbose > 0) - Utils.log.info("set "+opt+"="+val); - if (val != null) { - boolean set = setOption(opt, val); - if (!set) - Utils.log.warning("Invalid option "+opt+"="+val); - } - } - - void run(InputStream inRaw, JarOutputStream jstream, - ByteBuffer presetInput) throws IOException { - BufferedInputStream in0 = new BufferedInputStream(inRaw); - this.in = in0; // for readInputFn to see - _verbose = _props.getInteger(Utils.DEBUG_VERBOSE); - // Fix for BugId: 4902477, -unpack.modification.time = 1059010598000 - // TODO eliminate and fix in unpack.cpp - - final int modtime = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, "0")) ? - Constants.NO_MODTIME : _props.getTime(Utils.UNPACK_MODIFICATION_TIME); - - copyInOption(Utils.DEBUG_VERBOSE); - copyInOption(Pack200.Unpacker.DEFLATE_HINT); - if (modtime == Constants.NO_MODTIME) // Don't pass KEEP && NOW - copyInOption(Utils.UNPACK_MODIFICATION_TIME); - updateProgress(); // reset progress bar - for (;;) { - // Read the packed bits. - long counts = start(presetInput, 0); - _byteCount = _estByteLimit = 0; // reset partial scan counts - ++_segCount; // just finished scanning a whole segment... - int nextSeg = (int)( counts >>> 32 ); - int nextFile = (int)( counts >>> 0 ); - - // Estimate eventual total number of segments and files. - _estSegLimit = _segCount + nextSeg; - double filesAfterThisSeg = _fileCount + nextFile; - _estFileLimit = (int)( (filesAfterThisSeg * - _estSegLimit) / _segCount ); - - // Write the files. - int[] intParts = { 0,0, 0, 0 }; - // intParts = {size.hi/lo, mod, defl} - Object[] parts = { intParts, null, null, null }; - // parts = { {intParts}, name, data0/1 } - while (getNextFile(parts)) { - //BandStructure.printArrayTo(System.out, intParts, 0, parts.length); - String name = (String) parts[1]; - long size = ( (long)intParts[0] << 32) - + (((long)intParts[1] << 32) >>> 32); - - long mtime = (modtime != Constants.NO_MODTIME ) ? - modtime : intParts[2] ; - boolean deflateHint = (intParts[3] != 0); - ByteBuffer data0 = (ByteBuffer) parts[2]; - ByteBuffer data1 = (ByteBuffer) parts[3]; - writeEntry(jstream, name, mtime, size, deflateHint, - data0, data1); - ++_fileCount; - updateProgress(); - } - presetInput = getUnusedInput(); - long consumed = finish(); - if (_verbose > 0) - Utils.log.info("bytes consumed = "+consumed); - if (presetInput == null && - !Utils.isPackMagic(Utils.readMagic(in0))) { - break; - } - if (_verbose > 0 ) { - if (presetInput != null) - Utils.log.info("unused input = "+presetInput); - } - } - } - - void run(InputStream in, JarOutputStream jstream) throws IOException { - run(in, jstream, null); - } - - void run(File inFile, JarOutputStream jstream) throws IOException { - // %%% maybe memory-map the file, and pass it straight into unpacker - ByteBuffer mappedFile = null; - try (FileInputStream fis = new FileInputStream(inFile)) { - run(fis, jstream, mappedFile); - } - // Note: caller is responsible to finish with jstream. - } - - private void writeEntry(JarOutputStream j, String name, - long mtime, long lsize, boolean deflateHint, - ByteBuffer data0, ByteBuffer data1) throws IOException { - int size = (int)lsize; - if (size != lsize) - throw new IOException("file too large: "+lsize); - - CRC32 crc32 = _crc32; - - if (_verbose > 1) - Utils.log.fine("Writing entry: "+name+" size="+size - +(deflateHint?" deflated":"")); - - if (_buf.length < size) { - int newSize = size; - while (newSize < _buf.length) { - newSize <<= 1; - if (newSize <= 0) { - newSize = size; - break; - } - } - _buf = new byte[newSize]; - } - assert(_buf.length >= size); - - int fillp = 0; - if (data0 != null) { - int size0 = data0.capacity(); - data0.get(_buf, fillp, size0); - fillp += size0; - } - if (data1 != null) { - int size1 = data1.capacity(); - data1.get(_buf, fillp, size1); - fillp += size1; - } - while (fillp < size) { - // Fill in rest of data from the stream itself. - int nr = in.read(_buf, fillp, size - fillp); - if (nr <= 0) throw new IOException("EOF at end of archive"); - fillp += nr; - } - - ZipEntry z = new ZipEntry(name); - z.setTime(mtime * 1000); - - if (size == 0) { - z.setMethod(ZipOutputStream.STORED); - z.setSize(0); - z.setCrc(0); - z.setCompressedSize(0); - } else if (!deflateHint) { - z.setMethod(ZipOutputStream.STORED); - z.setSize(size); - z.setCompressedSize(size); - crc32.reset(); - crc32.update(_buf, 0, size); - z.setCrc(crc32.getValue()); - } else { - z.setMethod(Deflater.DEFLATED); - z.setSize(size); - } - - j.putNextEntry(z); - - if (size > 0) - j.write(_buf, 0, size); - - j.closeEntry(); - if (_verbose > 0) Utils.log.info("Writing " + Utils.zeString(z)); - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java deleted file mode 100644 index f54626b35f5..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java +++ /dev/null @@ -1,1377 +0,0 @@ -/* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.util.jar.Pack200; -import com.sun.java.util.jar.pack.Attribute.Layout; -import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; -import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; -import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; -import com.sun.java.util.jar.pack.ConstantPool.Index; -import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry; -import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.SequenceInputStream; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; -import java.util.jar.JarFile; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Define the main data structure transmitted by pack/unpack. - * @author John Rose - */ -class Package { - int verbose; - { - PropMap pmap = Utils.currentPropMap(); - if (pmap != null) - verbose = pmap.getInteger(Utils.DEBUG_VERBOSE); - } - - final int magic = JAVA_PACKAGE_MAGIC; - - int default_modtime = NO_MODTIME; - int default_options = 0; // FO_DEFLATE_HINT - - Version defaultClassVersion = null; - - // These fields can be adjusted by driver properties. - final Version minClassVersion; - final Version maxClassVersion; - // null, indicates that consensus rules during package write - final Version packageVersion; - - Version observedHighestClassVersion = null; - - - // What constants are used in this unit? - ConstantPool.IndexGroup cp = new ConstantPool.IndexGroup(); - - /* - * typically used by the PackageReader to set the defaults, in which - * case we take the defaults. - */ - public Package() { - minClassVersion = JAVA_MIN_CLASS_VERSION; - maxClassVersion = JAVA_MAX_CLASS_VERSION; - packageVersion = null; - } - - - /* - * Typically used by the PackerImpl during before packing, the defaults are - * overridden by the users preferences. - */ - public Package(Version minClassVersion, Version maxClassVersion, Version packageVersion) { - // Fill in permitted range of major/minor version numbers. - this.minClassVersion = minClassVersion == null - ? JAVA_MIN_CLASS_VERSION - : minClassVersion; - this.maxClassVersion = maxClassVersion == null - ? JAVA_MAX_CLASS_VERSION - : maxClassVersion; - this.packageVersion = packageVersion; - } - - - public void reset() { - cp = new ConstantPool.IndexGroup(); - classes.clear(); - files.clear(); - BandStructure.nextSeqForDebug = 0; - observedHighestClassVersion = null; - } - - // Special empty versions of Code and InnerClasses, used for markers. - public static final Attribute.Layout attrCodeEmpty; - public static final Attribute.Layout attrBootstrapMethodsEmpty; - public static final Attribute.Layout attrInnerClassesEmpty; - public static final Attribute.Layout attrSourceFileSpecial; - public static final Map attrDefs; - static { - Map ad = new HashMap<>(3); - attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD, - "Code", "").layout(); - attrBootstrapMethodsEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS, - "BootstrapMethods", "").layout(); - attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS, - "InnerClasses", "").layout(); - attrSourceFileSpecial = Attribute.define(ad, ATTR_CONTEXT_CLASS, - "SourceFile", "RUNH").layout(); - attrDefs = Collections.unmodifiableMap(ad); - } - - Version getDefaultClassVersion() { - return defaultClassVersion; - } - - /** Return the highest version number of all classes, - * or 0 if there are no classes. - */ - private void setHighestClassVersion() { - if (observedHighestClassVersion != null) - return; - Version res = JAVA_MIN_CLASS_VERSION; // initial low value - for (Class cls : classes) { - Version ver = cls.getVersion(); - if (res.lessThan(ver)) res = ver; - } - observedHighestClassVersion = res; - } - - Version getHighestClassVersion() { - setHighestClassVersion(); - return observedHighestClassVersion; - } - - // What Java classes are in this unit? - - ArrayList classes = new ArrayList<>(); - - public List getClasses() { - return classes; - } - - public final - class Class extends Attribute.Holder implements Comparable { - public Package getPackage() { return Package.this; } - - // Optional file characteristics and data source (a "class stub") - File file; - - // File header - int magic; - Version version; - - // Local constant pool (one-way mapping of index => package cp). - Entry[] cpMap; - - // Class header - //int flags; // in Attribute.Holder.this.flags - ClassEntry thisClass; - ClassEntry superClass; - ClassEntry[] interfaces; - - // Class parts - ArrayList fields; - ArrayList methods; - //ArrayList attributes; // in Attribute.Holder.this.attributes - // Note that InnerClasses may be collected at the package level. - ArrayList innerClasses; - ArrayList bootstrapMethods; - - Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) { - this.magic = JAVA_MAGIC; - this.version = defaultClassVersion; - this.flags = flags; - this.thisClass = thisClass; - this.superClass = superClass; - this.interfaces = interfaces; - - boolean added = classes.add(this); - assert(added); - } - - Class(String classFile) { - // A blank class; must be read with a ClassReader, etc. - initFile(newStub(classFile)); - } - - List getFields() { return fields == null ? noFields : fields; } - List getMethods() { return methods == null ? noMethods : methods; } - - public String getName() { - return thisClass.stringValue(); - } - - Version getVersion() { - return this.version; - } - - // Note: equals and hashCode are identity-based. - public int compareTo(Class that) { - String n0 = this.getName(); - String n1 = that.getName(); - return n0.compareTo(n1); - } - - String getObviousSourceFile() { - return Package.getObviousSourceFile(getName()); - } - - private void transformSourceFile(boolean minimize) { - // Replace "obvious" SourceFile by null. - Attribute olda = getAttribute(attrSourceFileSpecial); - if (olda == null) - return; // no SourceFile attr. - String obvious = getObviousSourceFile(); - List ref = new ArrayList<>(1); - olda.visitRefs(this, VRM_PACKAGE, ref); - Utf8Entry sfName = (Utf8Entry) ref.get(0); - Attribute a = olda; - if (sfName == null) { - if (minimize) { - // A pair of zero bytes. Cannot use predef. layout. - a = Attribute.find(ATTR_CONTEXT_CLASS, "SourceFile", "H"); - a = a.addContent(new byte[2]); - } else { - // Expand null attribute to the obvious string. - byte[] bytes = new byte[2]; - sfName = getRefString(obvious); - Object f = null; - f = Fixups.addRefWithBytes(f, bytes, sfName); - a = attrSourceFileSpecial.addContent(bytes, f); - } - } else if (obvious.equals(sfName.stringValue())) { - if (minimize) { - // Replace by an all-zero attribute. - a = attrSourceFileSpecial.addContent(new byte[2]); - } else { - assert(false); - } - } - if (a != olda) { - if (verbose > 2) - Utils.log.fine("recoding obvious SourceFile="+obvious); - List newAttrs = new ArrayList<>(getAttributes()); - int where = newAttrs.indexOf(olda); - newAttrs.set(where, a); - setAttributes(newAttrs); - } - } - - void minimizeSourceFile() { - transformSourceFile(true); - } - void expandSourceFile() { - transformSourceFile(false); - } - - protected Entry[] getCPMap() { - return cpMap; - } - - protected void setCPMap(Entry[] cpMap) { - this.cpMap = cpMap; - } - - boolean hasBootstrapMethods() { - return bootstrapMethods != null && !bootstrapMethods.isEmpty(); - } - - List getBootstrapMethods() { - return bootstrapMethods; - } - - BootstrapMethodEntry[] getBootstrapMethodMap() { - return (hasBootstrapMethods()) - ? bootstrapMethods.toArray(new BootstrapMethodEntry[bootstrapMethods.size()]) - : null; - } - - void setBootstrapMethods(Collection bsms) { - assert(bootstrapMethods == null); // do not do this twice - bootstrapMethods = new ArrayList<>(bsms); - } - - boolean hasInnerClasses() { - return innerClasses != null; - } - List getInnerClasses() { - return innerClasses; - } - - public void setInnerClasses(Collection ics) { - innerClasses = (ics == null) ? null : new ArrayList<>(ics); - // Edit the attribute list, if necessary. - Attribute a = getAttribute(attrInnerClassesEmpty); - if (innerClasses != null && a == null) - addAttribute(attrInnerClassesEmpty.canonicalInstance()); - else if (innerClasses == null && a != null) - removeAttribute(a); - } - - /** Given a global map of ICs (keyed by thisClass), - * compute the subset of its Map.values which are - * required to be present in the local InnerClasses - * attribute. Perform this calculation without - * reference to any actual InnerClasses attribute. - *

- * The order of the resulting list is consistent - * with that of Package.this.allInnerClasses. - */ - public List computeGloballyImpliedICs() { - Set cpRefs = new HashSet<>(); - { // This block temporarily displaces this.innerClasses. - ArrayList innerClassesSaved = innerClasses; - innerClasses = null; // ignore for the moment - visitRefs(VRM_CLASSIC, cpRefs); - innerClasses = innerClassesSaved; - } - ConstantPool.completeReferencesIn(cpRefs, true); - - Set icRefs = new HashSet<>(); - for (Entry e : cpRefs) { - // Restrict cpRefs to InnerClasses entries only. - if (!(e instanceof ClassEntry)) continue; - // For every IC reference, add its outers also. - while (e != null) { - InnerClass ic = getGlobalInnerClass(e); - if (ic == null) break; - if (!icRefs.add(e)) break; - e = ic.outerClass; - // If we add A$B$C to the mix, we must also add A$B. - } - } - // This loop is structured this way so as to accumulate - // entries into impliedICs in an order which reflects - // the order of allInnerClasses. - ArrayList impliedICs = new ArrayList<>(); - for (InnerClass ic : allInnerClasses) { - // This one is locally relevant if it describes - // a member of the current class, or if the current - // class uses it somehow. In the particular case - // where thisClass is an inner class, it will already - // be a member of icRefs. - if (icRefs.contains(ic.thisClass) - || ic.outerClass == this.thisClass) { - // Add every relevant class to the IC attribute: - if (verbose > 1) - Utils.log.fine("Relevant IC: "+ic); - impliedICs.add(ic); - } - } - return impliedICs; - } - - // Helper for both minimizing and expanding. - // Computes a symmetric difference. - private List computeICdiff() { - List impliedICs = computeGloballyImpliedICs(); - List actualICs = getInnerClasses(); - if (actualICs == null) - actualICs = Collections.emptyList(); - - // Symmetric difference is calculated from I, A like this: - // diff = (I+A) - (I*A) - // Note that the center C is unordered, but the result - // preserves the original ordering of I and A. - // - // Class file rules require that outers precede inners. - // So, add I before A, in case A$B$Z is local, but A$B - // is implicit. The reverse is never the case. - if (actualICs.isEmpty()) { - return impliedICs; - // Diff is I since A is empty. - } - if (impliedICs.isEmpty()) { - return actualICs; - // Diff is A since I is empty. - } - // (I*A) is non-trivial - Set center = new HashSet<>(actualICs); - center.retainAll(new HashSet<>(impliedICs)); - impliedICs.addAll(actualICs); - impliedICs.removeAll(center); - // Diff is now I^A = (I+A)-(I*A). - return impliedICs; - } - - /** When packing, anticipate the effect of expandLocalICs. - * Replace the local ICs by their symmetric difference - * with the globally implied ICs for this class; if this - * difference is empty, remove the local ICs altogether. - *

- * An empty local IC attribute is reserved to signal - * the unpacker to delete the attribute altogether, - * so a missing local IC attribute signals the unpacker - * to use the globally implied ICs changed. - */ - void minimizeLocalICs() { - List diff = computeICdiff(); - List actualICs = innerClasses; - List localICs; // will be the diff, modulo edge cases - if (diff.isEmpty()) { - // No diff, so transmit no attribute. - localICs = null; - if (actualICs != null && actualICs.isEmpty()) { - // Odd case: No implied ICs, and a zero length attr. - // Do not support it directly. - if (verbose > 0) - Utils.log.info("Warning: Dropping empty InnerClasses attribute from "+this); - } - } else if (actualICs == null) { - // No local IC attribute, even though some are implied. - // Signal with trivial attribute. - localICs = Collections.emptyList(); - } else { - // Transmit a non-empty diff, which will create - // a local ICs attribute. - localICs = diff; - } - // Reduce the set to the symmetric difference. - setInnerClasses(localICs); - if (verbose > 1 && localICs != null) - Utils.log.fine("keeping local ICs in "+this+": "+localICs); - } - - /** When unpacking, undo the effect of minimizeLocalICs. - * Must return negative if any IC tuples may have been deleted. - * Otherwise, return positive if any IC tuples were added. - */ - int expandLocalICs() { - List localICs = innerClasses; - List actualICs; - int changed; - if (localICs == null) { - // Diff was empty. (Common case.) - List impliedICs = computeGloballyImpliedICs(); - if (impliedICs.isEmpty()) { - actualICs = null; - changed = 0; - } else { - actualICs = impliedICs; - changed = 1; // added more tuples - } - } else if (localICs.isEmpty()) { - // It was a non-empty diff, but the local ICs were absent. - actualICs = null; - // [] => null, no tuple change, but attribute deletion. - changed = -1; - } else { - // Non-trivial diff was transmitted. - actualICs = computeICdiff(); - // If we only added more ICs, return +1. - changed = actualICs.containsAll(localICs)? +1: -1; - } - setInnerClasses(actualICs); - return changed; - } - - public abstract - class Member extends Attribute.Holder implements Comparable { - DescriptorEntry descriptor; - - protected Member(int flags, DescriptorEntry descriptor) { - this.flags = flags; - this.descriptor = descriptor; - } - - public Class thisClass() { return Class.this; } - - public DescriptorEntry getDescriptor() { - return descriptor; - } - public String getName() { - return descriptor.nameRef.stringValue(); - } - public String getType() { - return descriptor.typeRef.stringValue(); - } - - protected Entry[] getCPMap() { - return cpMap; - } - protected void visitRefs(int mode, Collection refs) { - if (verbose > 2) Utils.log.fine("visitRefs "+this); - // Careful: The descriptor is used by the package, - // but the classfile breaks it into component refs. - if (mode == VRM_CLASSIC) { - refs.add(descriptor.nameRef); - refs.add(descriptor.typeRef); - } else { - refs.add(descriptor); - } - // Handle attribute list: - super.visitRefs(mode, refs); - } - - public String toString() { - return Class.this + "." + descriptor.prettyString(); - } - } - - public - class Field extends Member { - // Order is significant for fields: It is visible to reflection. - int order; - - public Field(int flags, DescriptorEntry descriptor) { - super(flags, descriptor); - assert(!descriptor.isMethod()); - if (fields == null) - fields = new ArrayList<>(); - boolean added = fields.add(this); - assert(added); - order = fields.size(); - } - - public byte getLiteralTag() { - return descriptor.getLiteralTag(); - } - - public int compareTo(Member o) { - Field that = (Field)o; - return this.order - that.order; - } - } - - public - class Method extends Member { - // Code attribute is specially hardwired. - Code code; - - public Method(int flags, DescriptorEntry descriptor) { - super(flags, descriptor); - assert(descriptor.isMethod()); - if (methods == null) - methods = new ArrayList<>(); - boolean added = methods.add(this); - assert(added); - } - - public void trimToSize() { - super.trimToSize(); - if (code != null) - code.trimToSize(); - } - - public int getArgumentSize() { - int argSize = descriptor.typeRef.computeSize(true); - int thisSize = Modifier.isStatic(flags) ? 0 : 1; - return thisSize + argSize; - } - - // Sort methods in a canonical order (by type, then by name). - public int compareTo(Member o) { - Method that = (Method)o; - return this.getDescriptor().compareTo(that.getDescriptor()); - } - - public void strip(String attrName) { - if ("Code".equals(attrName)) - code = null; - if (code != null) - code.strip(attrName); - super.strip(attrName); - } - protected void visitRefs(int mode, Collection refs) { - super.visitRefs(mode, refs); - if (code != null) { - if (mode == VRM_CLASSIC) { - refs.add(getRefString("Code")); - } - code.visitRefs(mode, refs); - } - } - } - - public void trimToSize() { - super.trimToSize(); - for (int isM = 0; isM <= 1; isM++) { - ArrayList members = (isM == 0) ? fields : methods; - if (members == null) continue; - members.trimToSize(); - for (Member m : members) { - m.trimToSize(); - } - } - if (innerClasses != null) { - innerClasses.trimToSize(); - } - } - - public void strip(String attrName) { - if ("InnerClass".equals(attrName)) - innerClasses = null; - for (int isM = 0; isM <= 1; isM++) { - ArrayList members = (isM == 0) ? fields : methods; - if (members == null) continue; - for (Member m : members) { - m.strip(attrName); - } - } - super.strip(attrName); - } - - protected void visitRefs(int mode, Collection refs) { - if (verbose > 2) Utils.log.fine("visitRefs "+this); - refs.add(thisClass); - refs.add(superClass); - refs.addAll(Arrays.asList(interfaces)); - for (int isM = 0; isM <= 1; isM++) { - ArrayList members = (isM == 0) ? fields : methods; - if (members == null) continue; - for (Member m : members) { - boolean ok = false; - try { - m.visitRefs(mode, refs); - ok = true; - } finally { - if (!ok) - Utils.log.warning("Error scanning "+m); - } - } - } - visitInnerClassRefs(mode, refs); - // Handle attribute list: - super.visitRefs(mode, refs); - } - - protected void visitInnerClassRefs(int mode, Collection refs) { - Package.visitInnerClassRefs(innerClasses, mode, refs); - } - - // Hook called by ClassReader when it's done. - void finishReading() { - trimToSize(); - maybeChooseFileName(); - } - - public void initFile(File file) { - assert(this.file == null); // set-once - if (file == null) { - // Build a trivial stub. - file = newStub(canonicalFileName()); - } - this.file = file; - assert(file.isClassStub()); - file.stubClass = this; - maybeChooseFileName(); - } - - public void maybeChooseFileName() { - if (thisClass == null) { - return; // do not choose yet - } - String canonName = canonicalFileName(); - if (file.nameString.isEmpty()) { - file.nameString = canonName; - } - if (file.nameString.equals(canonName)) { - // The file name is predictable. Transmit "". - file.name = getRefString(""); - return; - } - // If name has not yet been looked up, find it now. - if (file.name == null) { - file.name = getRefString(file.nameString); - } - } - - public String canonicalFileName() { - if (thisClass == null) return null; - return thisClass.stringValue() + ".class"; - } - - public java.io.File getFileName(java.io.File parent) { - String name = file.name.stringValue(); - if (name.isEmpty()) - name = canonicalFileName(); - String fname = name.replace('/', java.io.File.separatorChar); - return new java.io.File(parent, fname); - } - public java.io.File getFileName() { - return getFileName(null); - } - - public String toString() { - return thisClass.stringValue(); - } - } - - void addClass(Class c) { - assert(c.getPackage() == this); - boolean added = classes.add(c); - assert(added); - // Make sure the class is represented in the total file order: - if (c.file == null) c.initFile(null); - addFile(c.file); - } - - // What non-class files are in this unit? - ArrayList files = new ArrayList<>(); - - public List getFiles() { - return files; - } - - public List getClassStubs() { - List classStubs = new ArrayList<>(classes.size()); - for (Class cls : classes) { - assert(cls.file.isClassStub()); - classStubs.add(cls.file); - } - return classStubs; - } - - public final class File implements Comparable { - String nameString; // true name of this file - Utf8Entry name; - int modtime = NO_MODTIME; - int options = 0; // random flag bits, such as deflate_hint - Class stubClass; // if this is a stub, here's the class - ArrayList prepend = new ArrayList<>(); // list of byte[] - java.io.ByteArrayOutputStream append = new ByteArrayOutputStream(); - - File(Utf8Entry name) { - this.name = name; - this.nameString = name.stringValue(); - // caller must fill in contents - } - File(String nameString) { - nameString = fixupFileName(nameString); - this.name = getRefString(nameString); - this.nameString = name.stringValue(); - } - - public boolean isDirectory() { - // JAR directory. Useless. - return nameString.endsWith("/"); - } - public boolean isClassStub() { - return (options & FO_IS_CLASS_STUB) != 0; - } - public Class getStubClass() { - assert(isClassStub()); - assert(stubClass != null); - return stubClass; - } - public boolean isTrivialClassStub() { - return isClassStub() - && name.stringValue().isEmpty() - && (modtime == NO_MODTIME || modtime == default_modtime) - && (options &~ FO_IS_CLASS_STUB) == 0; - } - - // The nameString is the key. Ignore other things. - // (Note: The name might be "", in the case of a trivial class stub.) - public boolean equals(Object o) { - if (o == null || (o.getClass() != File.class)) - return false; - File that = (File)o; - return that.nameString.equals(this.nameString); - } - public int hashCode() { - return nameString.hashCode(); - } - // Simple alphabetic sort. PackageWriter uses a better comparator. - public int compareTo(File that) { - return this.nameString.compareTo(that.nameString); - } - public String toString() { - return nameString+"{" - +(isClassStub()?"*":"") - +(BandStructure.testBit(options,FO_DEFLATE_HINT)?"@":"") - +(modtime==NO_MODTIME?"":"M"+modtime) - +(getFileLength()==0?"":"["+getFileLength()+"]") - +"}"; - } - - public java.io.File getFileName() { - return getFileName(null); - } - public java.io.File getFileName(java.io.File parent) { - String lname = this.nameString; - //if (name.startsWith("./")) name = name.substring(2); - String fname = lname.replace('/', java.io.File.separatorChar); - return new java.io.File(parent, fname); - } - - public void addBytes(byte[] bytes) { - addBytes(bytes, 0, bytes.length); - } - public void addBytes(byte[] bytes, int off, int len) { - if (((append.size() | len) << 2) < 0) { - prepend.add(append.toByteArray()); - append.reset(); - } - append.write(bytes, off, len); - } - public long getFileLength() { - long len = 0; - if (prepend == null || append == null) return 0; - for (byte[] block : prepend) { - len += block.length; - } - len += append.size(); - return len; - } - public void writeTo(OutputStream out) throws IOException { - if (prepend == null || append == null) return; - for (byte[] block : prepend) { - out.write(block); - } - append.writeTo(out); - } - public void readFrom(InputStream in) throws IOException { - byte[] buf = new byte[1 << 16]; - int nr; - while ((nr = in.read(buf)) > 0) { - addBytes(buf, 0, nr); - } - } - public InputStream getInputStream() { - InputStream in = new ByteArrayInputStream(append.toByteArray()); - if (prepend.isEmpty()) return in; - List isa = new ArrayList<>(prepend.size()+1); - for (byte[] bytes : prepend) { - isa.add(new ByteArrayInputStream(bytes)); - } - isa.add(in); - return new SequenceInputStream(Collections.enumeration(isa)); - } - - protected void visitRefs(int mode, Collection refs) { - assert(name != null); - refs.add(name); - } - } - - File newStub(String classFileNameString) { - File stub = new File(classFileNameString); - stub.options |= FO_IS_CLASS_STUB; - stub.prepend = null; - stub.append = null; // do not collect data - return stub; - } - - private static String fixupFileName(String name) { - String fname = name.replace(java.io.File.separatorChar, '/'); - if (fname.startsWith("/")) { - throw new IllegalArgumentException("absolute file name "+fname); - } - return fname; - } - - void addFile(File file) { - boolean added = files.add(file); - assert(added); - } - - // Is there a globally declared table of inner classes? - List allInnerClasses = new ArrayList<>(); - Map allInnerClassesByThis; - - public - List getAllInnerClasses() { - return allInnerClasses; - } - - public - void setAllInnerClasses(Collection ics) { - assert(ics != allInnerClasses); - allInnerClasses.clear(); - allInnerClasses.addAll(ics); - - // Make an index: - allInnerClassesByThis = new HashMap<>(allInnerClasses.size()); - for (InnerClass ic : allInnerClasses) { - Object pic = allInnerClassesByThis.put(ic.thisClass, ic); - assert(pic == null); // caller must ensure key uniqueness! - } - } - - /** Return a global inner class record for the given thisClass. */ - public - InnerClass getGlobalInnerClass(Entry thisClass) { - assert(thisClass instanceof ClassEntry); - return allInnerClassesByThis.get(thisClass); - } - - static - class InnerClass implements Comparable { - final ClassEntry thisClass; - final ClassEntry outerClass; - final Utf8Entry name; - final int flags; - - // Can name and outerClass be derived from thisClass? - final boolean predictable; - - // About 30% of inner classes are anonymous (in rt.jar). - // About 60% are class members; the rest are named locals. - // Nearly all have predictable outers and names. - - InnerClass(ClassEntry thisClass, ClassEntry outerClass, - Utf8Entry name, int flags) { - this.thisClass = thisClass; - this.outerClass = outerClass; - this.name = name; - this.flags = flags; - this.predictable = computePredictable(); - } - - private boolean computePredictable() { - //System.out.println("computePredictable "+outerClass+" "+this.name); - String[] parse = parseInnerClassName(thisClass.stringValue()); - if (parse == null) return false; - String pkgOuter = parse[0]; - //String number = parse[1]; - String lname = parse[2]; - String haveName = (this.name == null) ? null : this.name.stringValue(); - String haveOuter = (outerClass == null) ? null : outerClass.stringValue(); - boolean lpredictable = (lname == haveName && pkgOuter == haveOuter); - //System.out.println("computePredictable => "+predictable); - return lpredictable; - } - - public boolean equals(Object o) { - if (o == null || o.getClass() != InnerClass.class) - return false; - InnerClass that = (InnerClass)o; - return eq(this.thisClass, that.thisClass) - && eq(this.outerClass, that.outerClass) - && eq(this.name, that.name) - && this.flags == that.flags; - } - private static boolean eq(Object x, Object y) { - return (x == null)? y == null: x.equals(y); - } - public int hashCode() { - return thisClass.hashCode(); - } - public int compareTo(InnerClass that) { - return this.thisClass.compareTo(that.thisClass); - } - - protected void visitRefs(int mode, Collection refs) { - refs.add(thisClass); - if (mode == VRM_CLASSIC || !predictable) { - // If the name can be demangled, the package omits - // the products of demangling. Otherwise, include them. - refs.add(outerClass); - refs.add(name); - } - } - - public String toString() { - return thisClass.stringValue(); - } - } - - // Helper for building InnerClasses attributes. - private static - void visitInnerClassRefs(Collection innerClasses, int mode, Collection refs) { - if (innerClasses == null) { - return; // no attribute; nothing to do - } - if (mode == VRM_CLASSIC) { - refs.add(getRefString("InnerClasses")); - } - if (innerClasses.size() > 0) { - // Count the entries themselves: - for (InnerClass c : innerClasses) { - c.visitRefs(mode, refs); - } - } - } - - static String[] parseInnerClassName(String n) { - //System.out.println("parseInnerClassName "+n); - String pkgOuter, number, name; - int dollar1, dollar2; // pointers to $ in the pattern - // parse n = (/)*($)?($)? - int nlen = n.length(); - int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, n.length()) + 1; - dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, n.length()); - if (dollar2 < pkglen) return null; - if (isDigitString(n, dollar2+1, nlen)) { - // n = (/)*$ - number = n.substring(dollar2+1, nlen); - name = null; - dollar1 = dollar2; - } else if ((dollar1 - = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2-1)) - > pkglen - && isDigitString(n, dollar1+1, dollar2)) { - // n = (/)*$$ - number = n.substring(dollar1+1, dollar2); - name = n.substring(dollar2+1, nlen).intern(); - } else { - // n = (/)*$ - dollar1 = dollar2; - number = null; - name = n.substring(dollar2+1, nlen).intern(); - } - if (number == null) - pkgOuter = n.substring(0, dollar1).intern(); - else - pkgOuter = null; - //System.out.println("parseInnerClassName parses "+pkgOuter+" "+number+" "+name); - return new String[] { pkgOuter, number, name }; - } - - private static final int SLASH_MIN = '.'; - private static final int SLASH_MAX = '/'; - private static final int DOLLAR_MIN = 0; - private static final int DOLLAR_MAX = '-'; - static { - assert(lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, "x$$y$", 4) == 2); - assert(lastIndexOf(SLASH_MIN, SLASH_MAX, "x//y/", 4) == 2); - } - - private static int lastIndexOf(int chMin, int chMax, String str, int pos) { - for (int i = pos; --i >= 0; ) { - int ch = str.charAt(i); - if (ch >= chMin && ch <= chMax) { - return i; - } - } - return -1; - } - - private static boolean isDigitString(String x, int beg, int end) { - if (beg == end) return false; // null string - for (int i = beg; i < end; i++) { - char ch = x.charAt(i); - if (!(ch >= '0' && ch <= '9')) return false; - } - return true; - } - - static String getObviousSourceFile(String className) { - String n = className; - int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, n.length()) + 1; - n = n.substring(pkglen); - int cutoff = n.length(); - for (;;) { - // Work backwards, finding all '$', '#', etc. - int dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, cutoff-1); - if (dollar2 < 0) - break; - cutoff = dollar2; - if (cutoff == 0) - break; - } - String obvious = n.substring(0, cutoff)+".java"; - return obvious; - } -/* - static { - assert(getObviousSourceFile("foo").equals("foo.java")); - assert(getObviousSourceFile("foo/bar").equals("bar.java")); - assert(getObviousSourceFile("foo/bar$baz").equals("bar.java")); - assert(getObviousSourceFile("foo/bar#baz#1").equals("bar.java")); - assert(getObviousSourceFile("foo.bar.baz#1").equals("baz.java")); - } -*/ - - static Utf8Entry getRefString(String s) { - return ConstantPool.getUtf8Entry(s); - } - - static LiteralEntry getRefLiteral(Comparable s) { - return ConstantPool.getLiteralEntry(s); - } - - void stripAttributeKind(String what) { - // what is one of { Debug, Compile, Constant, Exceptions, InnerClasses } - if (verbose > 0) - Utils.log.info("Stripping "+what.toLowerCase()+" data and attributes..."); - switch (what) { - case "Debug": - strip("SourceFile"); - strip("LineNumberTable"); - strip("LocalVariableTable"); - strip("LocalVariableTypeTable"); - break; - case "Compile": - // Keep the inner classes normally. - // Although they have no effect on execution, - // the Reflection API exposes them, and JCK checks them. - // NO: // strip("InnerClasses"); - strip("Deprecated"); - strip("Synthetic"); - break; - case "Exceptions": - // Keep the exceptions normally. - // Although they have no effect on execution, - // the Reflection API exposes them, and JCK checks them. - strip("Exceptions"); - break; - case "Constant": - stripConstantFields(); - break; - } - } - - public void trimToSize() { - classes.trimToSize(); - for (Class c : classes) { - c.trimToSize(); - } - files.trimToSize(); - } - - public void strip(String attrName) { - for (Class c : classes) { - c.strip(attrName); - } - } - - public void stripConstantFields() { - for (Class c : classes) { - for (Iterator j = c.fields.iterator(); j.hasNext(); ) { - Class.Field f = j.next(); - if (Modifier.isFinal(f.flags) - // do not strip non-static finals: - && Modifier.isStatic(f.flags) - && f.getAttribute("ConstantValue") != null - && !f.getName().startsWith("serial")) { - if (verbose > 2) { - Utils.log.fine(">> Strip "+this+" ConstantValue"); - j.remove(); - } - } - } - } - } - - protected void visitRefs(int mode, Collection refs) { - for ( Class c : classes) { - c.visitRefs(mode, refs); - } - if (mode != VRM_CLASSIC) { - for (File f : files) { - f.visitRefs(mode, refs); - } - visitInnerClassRefs(allInnerClasses, mode, refs); - } - } - - // Use this before writing the package file. - // It sorts files into a new order which seems likely to - // compress better. It also moves classes to the end of the - // file order. It also removes JAR directory entries, which - // are useless. - void reorderFiles(boolean keepClassOrder, boolean stripDirectories) { - // First reorder the classes, if that is allowed. - if (!keepClassOrder) { - // In one test with rt.jar, this trick gained 0.7% - Collections.sort(classes); - } - - // Remove stubs from resources; maybe we'll add them on at the end, - // if there are some non-trivial ones. The best case is that - // modtimes and options are not transmitted, and the stub files - // for class files do not need to be transmitted at all. - // Also - List stubs = getClassStubs(); - for (Iterator i = files.iterator(); i.hasNext(); ) { - File file = i.next(); - if (file.isClassStub() || - (stripDirectories && file.isDirectory())) { - i.remove(); - } - } - - // Sort the remaining non-class files. - // We sort them by file type. - // This keeps files of similar format near each other. - // Put class files at the end, keeping their fixed order. - // Be sure the JAR file's required manifest stays at the front. (4893051) - Collections.sort(files, new Comparator<>() { - public int compare(File r0, File r1) { - // Get the file name. - String f0 = r0.nameString; - String f1 = r1.nameString; - if (f0.equals(f1)) return 0; - if (JarFile.MANIFEST_NAME.equals(f0)) return 0-1; - if (JarFile.MANIFEST_NAME.equals(f1)) return 1-0; - // Extract file basename. - String n0 = f0.substring(1+f0.lastIndexOf('/')); - String n1 = f1.substring(1+f1.lastIndexOf('/')); - // Extract basename extension. - String x0 = n0.substring(1+n0.lastIndexOf('.')); - String x1 = n1.substring(1+n1.lastIndexOf('.')); - int r; - // Primary sort key is file extension. - r = x0.compareTo(x1); - if (r != 0) return r; - r = f0.compareTo(f1); - return r; - } - }); - - // Add back the class stubs after sorting, before trimStubs. - files.addAll(stubs); - } - - void trimStubs() { - // Restore enough non-trivial stubs to carry the needed class modtimes. - for (ListIterator i = files.listIterator(files.size()); i.hasPrevious(); ) { - File file = i.previous(); - if (!file.isTrivialClassStub()) { - if (verbose > 1) - Utils.log.fine("Keeping last non-trivial "+file); - break; - } - if (verbose > 2) - Utils.log.fine("Removing trivial "+file); - i.remove(); - } - - if (verbose > 0) { - Utils.log.info("Transmitting "+files.size()+" files, including per-file data for "+getClassStubs().size()+" classes out of "+classes.size()); - } - } - - // Use this before writing the package file. - void buildGlobalConstantPool(Set requiredEntries) { - if (verbose > 1) - Utils.log.fine("Checking for unused CP entries"); - requiredEntries.add(getRefString("")); // uconditionally present - visitRefs(VRM_PACKAGE, requiredEntries); - ConstantPool.completeReferencesIn(requiredEntries, false); - if (verbose > 1) - Utils.log.fine("Sorting CP entries"); - Index cpAllU = ConstantPool.makeIndex("unsorted", requiredEntries); - Index[] byTagU = ConstantPool.partitionByTag(cpAllU); - for (int i = 0; i < ConstantPool.TAGS_IN_ORDER.length; i++) { - byte tag = ConstantPool.TAGS_IN_ORDER[i]; - // Work on all entries of a given kind. - Index ix = byTagU[tag]; - if (ix == null) continue; - ConstantPool.sort(ix); - cp.initIndexByTag(tag, ix); - byTagU[tag] = null; // done with it - } - for (int i = 0; i < byTagU.length; i++) { - Index ix = byTagU[i]; - assert(ix == null); // all consumed - } - for (int i = 0; i < ConstantPool.TAGS_IN_ORDER.length; i++) { - byte tag = ConstantPool.TAGS_IN_ORDER[i]; - Index ix = cp.getIndexByTag(tag); - assert(ix.assertIsSorted()); - if (verbose > 2) Utils.log.fine(ix.dumpString()); - } - } - - // Use this before writing the class files. - void ensureAllClassFiles() { - Set fileSet = new HashSet<>(files); - for (Class cls : classes) { - // Add to the end of ths list: - if (!fileSet.contains(cls.file)) - files.add(cls.file); - } - } - - static final List noObjects = Arrays.asList(new Object[0]); - static final List noFields = Arrays.asList(new Class.Field[0]); - static final List noMethods = Arrays.asList(new Class.Method[0]); - static final List noInnerClasses = Arrays.asList(new InnerClass[0]); - - protected static final class Version { - - public final short major; - public final short minor; - - private Version(short major, short minor) { - this.major = major; - this.minor = minor; - } - - public String toString() { - return major + "." + minor; - } - - public boolean equals(Object that) { - return that instanceof Version - && major == ((Version)that).major - && minor == ((Version)that).minor; - } - - public int intValue() { - return (major << 16) + minor; - } - - public int hashCode() { - return (major << 16) + 7 + minor; - } - - public static Version of(int major, int minor) { - return new Version((short)major, (short)minor); - } - - public static Version of(byte[] bytes) { - int minor = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF); - int major = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); - return new Version((short)major, (short)minor); - } - - public static Version of(int major_minor) { - short minor = (short)major_minor; - short major = (short)(major_minor >>> 16); - return new Version(major, minor); - } - - public static Version makeVersion(PropMap props, String partialKey) { - int min = props.getInteger(Utils.COM_PREFIX - + partialKey + ".minver", -1); - int maj = props.getInteger(Utils.COM_PREFIX - + partialKey + ".majver", -1); - return min >= 0 && maj >= 0 ? Version.of(maj, min) : null; - } - public byte[] asBytes() { - byte[] bytes = { - (byte) (minor >> 8), (byte) minor, - (byte) (major >> 8), (byte) major - }; - return bytes; - } - public int compareTo(Version that) { - return this.intValue() - that.intValue(); - } - - public boolean lessThan(Version that) { - return compareTo(that) < 0 ; - } - - public boolean greaterThan(Version that) { - return compareTo(that) > 0 ; - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java deleted file mode 100644 index bcb6cb1eb4d..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java +++ /dev/null @@ -1,2376 +0,0 @@ -/* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.*; -import com.sun.java.util.jar.pack.Package.Class; -import com.sun.java.util.jar.pack.Package.File; -import com.sun.java.util.jar.pack.Package.InnerClass; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.PrintStream; -import java.io.FilterInputStream; -import java.io.BufferedInputStream; -import java.io.InputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Set; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Reader for a package file. - * - * @see PackageWriter - * @author John Rose - */ -class PackageReader extends BandStructure { - Package pkg; - byte[] bytes; - LimitedBuffer in; - Package.Version packageVersion; - - PackageReader(Package pkg, InputStream in) throws IOException { - this.pkg = pkg; - this.in = new LimitedBuffer(in); - } - - /** A buffered input stream which is careful not to - * read its underlying stream ahead of a given mark, - * called the 'readLimit'. This property declares - * the maximum number of characters that future reads - * can consume from the underlying stream. - */ - static - class LimitedBuffer extends BufferedInputStream { - long served; // total number of charburgers served - int servedPos; // ...as of this value of super.pos - long limit; // current declared limit - long buffered; - public boolean atLimit() { - boolean z = (getBytesServed() == limit); - assert(!z || limit == buffered); - return z; - } - public long getBytesServed() { - return served + (pos - servedPos); - } - public void setReadLimit(long newLimit) { - if (newLimit == -1) - limit = -1; - else - limit = getBytesServed() + newLimit; - } - public long getReadLimit() { - if (limit == -1) - return limit; - else - return limit - getBytesServed(); - } - public int read() throws IOException { - if (pos < count) { - // fast path - return buf[pos++] & 0xFF; - } - served += (pos - servedPos); - int ch = super.read(); - servedPos = pos; - if (ch >= 0) served += 1; - assert(served <= limit || limit == -1); - return ch; - } - public int read(byte b[], int off, int len) throws IOException { - served += (pos - servedPos); - int nr = super.read(b, off, len); - servedPos = pos; - if (nr >= 0) served += nr; - //assert(served <= limit || limit == -1); - return nr; - } - public long skip(long n) throws IOException { - throw new RuntimeException("no skipping"); - } - LimitedBuffer(InputStream originalIn) { - super(null, 1<<14); - servedPos = pos; - super.in = new FilterInputStream(originalIn) { - public int read() throws IOException { - if (buffered == limit) - return -1; - ++buffered; - return super.read(); - } - public int read(byte b[], int off, int len) throws IOException { - if (buffered == limit) - return -1; - if (limit != -1) { - long remaining = limit - buffered; - if (len > remaining) - len = (int)remaining; - } - int nr = super.read(b, off, len); - if (nr >= 0) buffered += nr; - return nr; - } - }; - } - } - - void read() throws IOException { - boolean ok = false; - try { - // pack200_archive: - // file_header - // *band_headers :BYTE1 - // cp_bands - // attr_definition_bands - // ic_bands - // class_bands - // bc_bands - // file_bands - readFileHeader(); - readBandHeaders(); - readConstantPool(); // cp_bands - readAttrDefs(); - readInnerClasses(); - Class[] classes = readClasses(); - readByteCodes(); - readFiles(); // file_bands - assert(archiveSize1 == 0 || in.atLimit()); - assert(archiveSize1 == 0 || - in.getBytesServed() == archiveSize0+archiveSize1); - all_bands.doneDisbursing(); - - // As a post-pass, build constant pools and inner classes. - for (int i = 0; i < classes.length; i++) { - reconstructClass(classes[i]); - } - - ok = true; - } catch (Exception ee) { - Utils.log.warning("Error on input: "+ee, ee); - if (verbose > 0) - Utils.log.info("Stream offsets:"+ - " served="+in.getBytesServed()+ - " buffered="+in.buffered+ - " limit="+in.limit); - //if (verbose > 0) ee.printStackTrace(); - if (ee instanceof IOException) throw (IOException)ee; - if (ee instanceof RuntimeException) throw (RuntimeException)ee; - throw new Error("error unpacking", ee); - } - } - - // Temporary count values, until band decoding gets rolling. - int[] tagCount = new int[CONSTANT_Limit]; - int numFiles; - int numAttrDefs; - int numInnerClasses; - int numClasses; - - void readFileHeader() throws IOException { - // file_header: - // archive_magic archive_header - readArchiveMagic(); - readArchiveHeader(); - } - - // Local routine used to parse fixed-format scalars - // in the file_header: - private int getMagicInt32() throws IOException { - int res = 0; - for (int i = 0; i < 4; i++) { - res <<= 8; - res |= (archive_magic.getByte() & 0xFF); - } - return res; - } - - static final int MAGIC_BYTES = 4; - - void readArchiveMagic() throws IOException { - // Read a minimum of bytes in the first gulp. - in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN); - - // archive_magic: - // #archive_magic_word :BYTE1[4] - archive_magic.expectLength(MAGIC_BYTES); - archive_magic.readFrom(in); - - // read and check magic numbers: - int magic = getMagicInt32(); - if (pkg.magic != magic) { - throw new IOException("Unexpected package magic number: got " - + magic + "; expected " + pkg.magic); - } - archive_magic.doneDisbursing(); - } - - // Fixed 6211177, converted to throw IOException - void checkArchiveVersion() throws IOException { - Package.Version versionFound = null; - for (Package.Version v : new Package.Version[] { - JAVA8_PACKAGE_VERSION, - JAVA7_PACKAGE_VERSION, - JAVA6_PACKAGE_VERSION, - JAVA5_PACKAGE_VERSION - }) { - if (packageVersion.equals(v)) { - versionFound = v; - break; - } - } - if (versionFound == null) { - String expVer = JAVA8_PACKAGE_VERSION.toString() - + "OR" - + JAVA7_PACKAGE_VERSION.toString() - + " OR " - + JAVA6_PACKAGE_VERSION.toString() - + " OR " - + JAVA5_PACKAGE_VERSION.toString(); - throw new IOException("Unexpected package minor version: got " - + packageVersion.toString() + "; expected " + expVer); - } - } - - void readArchiveHeader() throws IOException { - // archive_header: - // #archive_minver :UNSIGNED5[1] - // #archive_majver :UNSIGNED5[1] - // #archive_options :UNSIGNED5[1] - // (archive_file_counts) ** (#have_file_headers) - // (archive_special_counts) ** (#have_special_formats) - // cp_counts - // class_counts - // - // archive_file_counts: - // #archive_size_hi :UNSIGNED5[1] - // #archive_size_lo :UNSIGNED5[1] - // #archive_next_count :UNSIGNED5[1] - // #archive_modtime :UNSIGNED5[1] - // #file_count :UNSIGNED5[1] - // - // class_counts: - // #ic_count :UNSIGNED5[1] - // #default_class_minver :UNSIGNED5[1] - // #default_class_majver :UNSIGNED5[1] - // #class_count :UNSIGNED5[1] - // - // archive_special_counts: - // #band_headers_size :UNSIGNED5[1] - // #attr_definition_count :UNSIGNED5[1] - // - archive_header_0.expectLength(AH_LENGTH_0); - archive_header_0.readFrom(in); - - int minver = archive_header_0.getInt(); - int majver = archive_header_0.getInt(); - packageVersion = Package.Version.of(majver, minver); - checkArchiveVersion(); - this.initHighestClassVersion(JAVA7_MAX_CLASS_VERSION); - - archiveOptions = archive_header_0.getInt(); - archive_header_0.doneDisbursing(); - - // detect archive optional fields in archive header - boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS); - boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS); - boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS); - boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS); - initAttrIndexLimit(); - - // now we are ready to use the data: - archive_header_S.expectLength(haveFiles? AH_LENGTH_S: 0); - archive_header_S.readFrom(in); - if (haveFiles) { - long sizeHi = archive_header_S.getInt(); - long sizeLo = archive_header_S.getInt(); - archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32); - // Set the limit, now, up to the file_bits. - in.setReadLimit(archiveSize1); // for debug only - } else { - archiveSize1 = 0; - in.setReadLimit(-1); // remove limitation - } - archive_header_S.doneDisbursing(); - archiveSize0 = in.getBytesServed(); - - int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; - if (haveFiles) remainingHeaders += AH_FILE_HEADER_LEN; - if (haveSpecial) remainingHeaders += AH_SPECIAL_FORMAT_LEN; - if (haveNumbers) remainingHeaders += AH_CP_NUMBER_LEN; - if (haveCPExtra) remainingHeaders += AH_CP_EXTRA_LEN; - archive_header_1.expectLength(remainingHeaders); - archive_header_1.readFrom(in); - - if (haveFiles) { - archiveNextCount = archive_header_1.getInt(); - pkg.default_modtime = archive_header_1.getInt(); - numFiles = archive_header_1.getInt(); - } else { - archiveNextCount = 0; - numFiles = 0; - } - - if (haveSpecial) { - band_headers.expectLength(archive_header_1.getInt()); - numAttrDefs = archive_header_1.getInt(); - } else { - band_headers.expectLength(0); - numAttrDefs = 0; - } - - readConstantPoolCounts(haveNumbers, haveCPExtra); - - numInnerClasses = archive_header_1.getInt(); - - minver = (short) archive_header_1.getInt(); - majver = (short) archive_header_1.getInt(); - pkg.defaultClassVersion = Package.Version.of(majver, minver); - numClasses = archive_header_1.getInt(); - - archive_header_1.doneDisbursing(); - - // set some derived archive bits - if (testBit(archiveOptions, AO_DEFLATE_HINT)) { - pkg.default_options |= FO_DEFLATE_HINT; - } - } - - void readBandHeaders() throws IOException { - band_headers.readFrom(in); - bandHeaderBytePos = 1; // Leave room to pushback the initial XB byte. - bandHeaderBytes = new byte[bandHeaderBytePos + band_headers.length()]; - for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) { - bandHeaderBytes[i] = (byte) band_headers.getByte(); - } - band_headers.doneDisbursing(); - } - - void readConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException { - // size the constant pools: - for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { - // cp_counts: - // #cp_Utf8_count :UNSIGNED5[1] - // (cp_number_counts) ** (#have_cp_numbers) - // #cp_String_count :UNSIGNED5[1] - // #cp_Class_count :UNSIGNED5[1] - // #cp_Signature_count :UNSIGNED5[1] - // #cp_Descr_count :UNSIGNED5[1] - // #cp_Field_count :UNSIGNED5[1] - // #cp_Method_count :UNSIGNED5[1] - // #cp_Imethod_count :UNSIGNED5[1] - // (cp_attr_counts) ** (#have_cp_attr_counts) - // - // cp_number_counts: - // #cp_Int_count :UNSIGNED5[1] - // #cp_Float_count :UNSIGNED5[1] - // #cp_Long_count :UNSIGNED5[1] - // #cp_Double_count :UNSIGNED5[1] - // - // cp_extra_counts: - // #cp_MethodHandle_count :UNSIGNED5[1] - // #cp_MethodType_count :UNSIGNED5[1] - // #cp_InvokeDynamic_count :UNSIGNED5[1] - // #cp_BootstrapMethod_count :UNSIGNED5[1] - // - byte tag = ConstantPool.TAGS_IN_ORDER[k]; - if (!haveNumbers) { - // These four counts are optional. - switch (tag) { - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_Long: - case CONSTANT_Double: - continue; - } - } - if (!haveCPExtra) { - // These four counts are optional. - switch (tag) { - case CONSTANT_MethodHandle: - case CONSTANT_MethodType: - case CONSTANT_InvokeDynamic: - case CONSTANT_BootstrapMethod: - continue; - } - } - tagCount[tag] = archive_header_1.getInt(); - } - } - - protected Index getCPIndex(byte tag) { - return pkg.cp.getIndexByTag(tag); - } - Index initCPIndex(byte tag, Entry[] cpMap) { - if (verbose > 3) { - for (int i = 0; i < cpMap.length; i++) { - Utils.log.fine("cp.add "+cpMap[i]); - } - } - Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag), cpMap); - if (verbose > 1) Utils.log.fine("Read "+index); - pkg.cp.initIndexByTag(tag, index); - return index; - } - - void checkLegacy(String bandname) { - if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) { - throw new RuntimeException("unexpected band " + bandname); - } - } - void readConstantPool() throws IOException { - // cp_bands: - // cp_Utf8 - // *cp_Int :UDELTA5 - // *cp_Float :UDELTA5 - // cp_Long - // cp_Double - // *cp_String :UDELTA5 (cp_Utf8) - // *cp_Class :UDELTA5 (cp_Utf8) - // cp_Signature - // cp_Descr - // cp_Field - // cp_Method - // cp_Imethod - - if (verbose > 0) Utils.log.info("Reading CP"); - - for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { - byte tag = ConstantPool.TAGS_IN_ORDER[k]; - int len = tagCount[tag]; - - Entry[] cpMap = new Entry[len]; - if (verbose > 0) - Utils.log.info("Reading "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries..."); - - switch (tag) { - case CONSTANT_Utf8: - readUtf8Bands(cpMap); - break; - case CONSTANT_Integer: - cp_Int.expectLength(cpMap.length); - cp_Int.readFrom(in); - for (int i = 0; i < cpMap.length; i++) { - int x = cp_Int.getInt(); // coding handles signs OK - cpMap[i] = ConstantPool.getLiteralEntry(x); - } - cp_Int.doneDisbursing(); - break; - case CONSTANT_Float: - cp_Float.expectLength(cpMap.length); - cp_Float.readFrom(in); - for (int i = 0; i < cpMap.length; i++) { - int x = cp_Float.getInt(); - float fx = Float.intBitsToFloat(x); - cpMap[i] = ConstantPool.getLiteralEntry(fx); - } - cp_Float.doneDisbursing(); - break; - case CONSTANT_Long: - // cp_Long: - // *cp_Long_hi :UDELTA5 - // *cp_Long_lo :DELTA5 - cp_Long_hi.expectLength(cpMap.length); - cp_Long_hi.readFrom(in); - cp_Long_lo.expectLength(cpMap.length); - cp_Long_lo.readFrom(in); - for (int i = 0; i < cpMap.length; i++) { - long hi = cp_Long_hi.getInt(); - long lo = cp_Long_lo.getInt(); - long x = (hi << 32) + ((lo << 32) >>> 32); - cpMap[i] = ConstantPool.getLiteralEntry(x); - } - cp_Long_hi.doneDisbursing(); - cp_Long_lo.doneDisbursing(); - break; - case CONSTANT_Double: - // cp_Double: - // *cp_Double_hi :UDELTA5 - // *cp_Double_lo :DELTA5 - cp_Double_hi.expectLength(cpMap.length); - cp_Double_hi.readFrom(in); - cp_Double_lo.expectLength(cpMap.length); - cp_Double_lo.readFrom(in); - for (int i = 0; i < cpMap.length; i++) { - long hi = cp_Double_hi.getInt(); - long lo = cp_Double_lo.getInt(); - long x = (hi << 32) + ((lo << 32) >>> 32); - double dx = Double.longBitsToDouble(x); - cpMap[i] = ConstantPool.getLiteralEntry(dx); - } - cp_Double_hi.doneDisbursing(); - cp_Double_lo.doneDisbursing(); - break; - case CONSTANT_String: - cp_String.expectLength(cpMap.length); - cp_String.readFrom(in); - cp_String.setIndex(getCPIndex(CONSTANT_Utf8)); - for (int i = 0; i < cpMap.length; i++) { - cpMap[i] = ConstantPool.getLiteralEntry(cp_String.getRef().stringValue()); - } - cp_String.doneDisbursing(); - break; - case CONSTANT_Class: - cp_Class.expectLength(cpMap.length); - cp_Class.readFrom(in); - cp_Class.setIndex(getCPIndex(CONSTANT_Utf8)); - for (int i = 0; i < cpMap.length; i++) { - cpMap[i] = ConstantPool.getClassEntry(cp_Class.getRef().stringValue()); - } - cp_Class.doneDisbursing(); - break; - case CONSTANT_Signature: - readSignatureBands(cpMap); - break; - case CONSTANT_NameandType: - // cp_Descr: - // *cp_Descr_type :DELTA5 (cp_Signature) - // *cp_Descr_name :UDELTA5 (cp_Utf8) - cp_Descr_name.expectLength(cpMap.length); - cp_Descr_name.readFrom(in); - cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8)); - cp_Descr_type.expectLength(cpMap.length); - cp_Descr_type.readFrom(in); - cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature)); - for (int i = 0; i < cpMap.length; i++) { - Entry ref = cp_Descr_name.getRef(); - Entry ref2 = cp_Descr_type.getRef(); - cpMap[i] = ConstantPool.getDescriptorEntry((Utf8Entry)ref, - (SignatureEntry)ref2); - } - cp_Descr_name.doneDisbursing(); - cp_Descr_type.doneDisbursing(); - break; - case CONSTANT_Fieldref: - readMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc); - break; - case CONSTANT_Methodref: - readMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc); - break; - case CONSTANT_InterfaceMethodref: - readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc); - break; - case CONSTANT_MethodHandle: - if (cpMap.length > 0) { - checkLegacy(cp_MethodHandle_refkind.name()); - } - cp_MethodHandle_refkind.expectLength(cpMap.length); - cp_MethodHandle_refkind.readFrom(in); - cp_MethodHandle_member.expectLength(cpMap.length); - cp_MethodHandle_member.readFrom(in); - cp_MethodHandle_member.setIndex(getCPIndex(CONSTANT_AnyMember)); - for (int i = 0; i < cpMap.length; i++) { - byte refKind = (byte) cp_MethodHandle_refkind.getInt(); - MemberEntry memRef = (MemberEntry) cp_MethodHandle_member.getRef(); - cpMap[i] = ConstantPool.getMethodHandleEntry(refKind, memRef); - } - cp_MethodHandle_refkind.doneDisbursing(); - cp_MethodHandle_member.doneDisbursing(); - break; - case CONSTANT_MethodType: - if (cpMap.length > 0) { - checkLegacy(cp_MethodType.name()); - } - cp_MethodType.expectLength(cpMap.length); - cp_MethodType.readFrom(in); - cp_MethodType.setIndex(getCPIndex(CONSTANT_Signature)); - for (int i = 0; i < cpMap.length; i++) { - SignatureEntry typeRef = (SignatureEntry) cp_MethodType.getRef(); - cpMap[i] = ConstantPool.getMethodTypeEntry(typeRef); - } - cp_MethodType.doneDisbursing(); - break; - case CONSTANT_InvokeDynamic: - if (cpMap.length > 0) { - checkLegacy(cp_InvokeDynamic_spec.name()); - } - cp_InvokeDynamic_spec.expectLength(cpMap.length); - cp_InvokeDynamic_spec.readFrom(in); - cp_InvokeDynamic_spec.setIndex(getCPIndex(CONSTANT_BootstrapMethod)); - cp_InvokeDynamic_desc.expectLength(cpMap.length); - cp_InvokeDynamic_desc.readFrom(in); - cp_InvokeDynamic_desc.setIndex(getCPIndex(CONSTANT_NameandType)); - for (int i = 0; i < cpMap.length; i++) { - BootstrapMethodEntry bss = (BootstrapMethodEntry) cp_InvokeDynamic_spec.getRef(); - DescriptorEntry descr = (DescriptorEntry) cp_InvokeDynamic_desc.getRef(); - cpMap[i] = ConstantPool.getInvokeDynamicEntry(bss, descr); - } - cp_InvokeDynamic_spec.doneDisbursing(); - cp_InvokeDynamic_desc.doneDisbursing(); - break; - case CONSTANT_BootstrapMethod: - if (cpMap.length > 0) { - checkLegacy(cp_BootstrapMethod_ref.name()); - } - cp_BootstrapMethod_ref.expectLength(cpMap.length); - cp_BootstrapMethod_ref.readFrom(in); - cp_BootstrapMethod_ref.setIndex(getCPIndex(CONSTANT_MethodHandle)); - cp_BootstrapMethod_arg_count.expectLength(cpMap.length); - cp_BootstrapMethod_arg_count.readFrom(in); - int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal(); - cp_BootstrapMethod_arg.expectLength(totalArgCount); - cp_BootstrapMethod_arg.readFrom(in); - cp_BootstrapMethod_arg.setIndex(getCPIndex(CONSTANT_LoadableValue)); - for (int i = 0; i < cpMap.length; i++) { - MethodHandleEntry bsm = (MethodHandleEntry) cp_BootstrapMethod_ref.getRef(); - int argc = cp_BootstrapMethod_arg_count.getInt(); - Entry[] argRefs = new Entry[argc]; - for (int j = 0; j < argc; j++) { - argRefs[j] = cp_BootstrapMethod_arg.getRef(); - } - cpMap[i] = ConstantPool.getBootstrapMethodEntry(bsm, argRefs); - } - cp_BootstrapMethod_ref.doneDisbursing(); - cp_BootstrapMethod_arg_count.doneDisbursing(); - cp_BootstrapMethod_arg.doneDisbursing(); - break; - default: - throw new AssertionError("unexpected CP tag in package"); - } - - Index index = initCPIndex(tag, cpMap); - - if (optDumpBands) { - try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) { - printArrayTo(ps, index.cpMap, 0, index.cpMap.length); - } - } - } - - cp_bands.doneDisbursing(); - - if (optDumpBands || verbose > 1) { - for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) { - Index index = pkg.cp.getIndexByTag(tag); - if (index == null || index.isEmpty()) continue; - Entry[] cpMap = index.cpMap; - if (verbose > 1) - Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries."); - if (optDumpBands) { - try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) { - printArrayTo(ps, cpMap, 0, cpMap.length, true); - } - } - } - } - - setBandIndexes(); - } - - void readUtf8Bands(Entry[] cpMap) throws IOException { - // cp_Utf8: - // *cp_Utf8_prefix :DELTA5 - // *cp_Utf8_suffix :UNSIGNED5 - // *cp_Utf8_chars :CHAR3 - // *cp_Utf8_big_suffix :DELTA5 - // (*cp_Utf8_big_chars :DELTA5) - // ** length(cp_Utf8_big_suffix) - int len = cpMap.length; - if (len == 0) - return; // nothing to read - - // Bands have implicit leading zeroes, for the empty string: - final int SUFFIX_SKIP_1 = 1; - final int PREFIX_SKIP_2 = 2; - - // First band: Read lengths of shared prefixes. - cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2)); - cp_Utf8_prefix.readFrom(in); - - // Second band: Read lengths of unshared suffixes: - cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1)); - cp_Utf8_suffix.readFrom(in); - - char[][] suffixChars = new char[len][]; - int bigSuffixCount = 0; - - // Third band: Read the char values in the unshared suffixes: - cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal()); - cp_Utf8_chars.readFrom(in); - for (int i = 0; i < len; i++) { - int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); - if (suffix == 0 && i >= SUFFIX_SKIP_1) { - // chars are packed in cp_Utf8_big_chars - bigSuffixCount += 1; - continue; - } - suffixChars[i] = new char[suffix]; - for (int j = 0; j < suffix; j++) { - int ch = cp_Utf8_chars.getInt(); - assert(ch == (char)ch); - suffixChars[i][j] = (char)ch; - } - } - cp_Utf8_chars.doneDisbursing(); - - // Fourth band: Go back and size the specially packed strings. - int maxChars = 0; - cp_Utf8_big_suffix.expectLength(bigSuffixCount); - cp_Utf8_big_suffix.readFrom(in); - cp_Utf8_suffix.resetForSecondPass(); - for (int i = 0; i < len; i++) { - int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); - int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); - if (suffix == 0 && i >= SUFFIX_SKIP_1) { - assert(suffixChars[i] == null); - suffix = cp_Utf8_big_suffix.getInt(); - } else { - assert(suffixChars[i] != null); - } - if (maxChars < prefix + suffix) - maxChars = prefix + suffix; - } - char[] buf = new char[maxChars]; - - // Fifth band(s): Get the specially packed characters. - cp_Utf8_suffix.resetForSecondPass(); - cp_Utf8_big_suffix.resetForSecondPass(); - for (int i = 0; i < len; i++) { - if (i < SUFFIX_SKIP_1) continue; - int suffix = cp_Utf8_suffix.getInt(); - if (suffix != 0) continue; // already input - suffix = cp_Utf8_big_suffix.getInt(); - suffixChars[i] = new char[suffix]; - if (suffix == 0) { - // Do not bother to add an empty "(Utf8_big_0)" band. - continue; - } - IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"+i+")"); - packed.expectLength(suffix); - packed.readFrom(in); - for (int j = 0; j < suffix; j++) { - int ch = packed.getInt(); - assert(ch == (char)ch); - suffixChars[i][j] = (char)ch; - } - packed.doneDisbursing(); - } - cp_Utf8_big_chars.doneDisbursing(); - - // Finally, sew together all the prefixes and suffixes. - cp_Utf8_prefix.resetForSecondPass(); - cp_Utf8_suffix.resetForSecondPass(); - cp_Utf8_big_suffix.resetForSecondPass(); - for (int i = 0; i < len; i++) { - int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); - int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); - if (suffix == 0 && i >= SUFFIX_SKIP_1) - suffix = cp_Utf8_big_suffix.getInt(); - - // by induction, the buffer is already filled with the prefix - System.arraycopy(suffixChars[i], 0, buf, prefix, suffix); - - cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0, prefix+suffix)); - } - - cp_Utf8_prefix.doneDisbursing(); - cp_Utf8_suffix.doneDisbursing(); - cp_Utf8_big_suffix.doneDisbursing(); - } - - Map utf8Signatures; - - void readSignatureBands(Entry[] cpMap) throws IOException { - // cp_Signature: - // *cp_Signature_form :DELTA5 (cp_Utf8) - // *cp_Signature_classes :UDELTA5 (cp_Class) - cp_Signature_form.expectLength(cpMap.length); - cp_Signature_form.readFrom(in); - cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8)); - int[] numSigClasses = new int[cpMap.length]; - for (int i = 0; i < cpMap.length; i++) { - Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef(); - numSigClasses[i] = ConstantPool.countClassParts(formRef); - } - cp_Signature_form.resetForSecondPass(); - cp_Signature_classes.expectLength(getIntTotal(numSigClasses)); - cp_Signature_classes.readFrom(in); - cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class)); - utf8Signatures = new HashMap<>(); - for (int i = 0; i < cpMap.length; i++) { - Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef(); - ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]]; - for (int j = 0; j < classRefs.length; j++) { - classRefs[j] = (ClassEntry) cp_Signature_classes.getRef(); - } - SignatureEntry se = ConstantPool.getSignatureEntry(formRef, classRefs); - cpMap[i] = se; - utf8Signatures.put(se.asUtf8Entry(), se); - } - cp_Signature_form.doneDisbursing(); - cp_Signature_classes.doneDisbursing(); - } - - void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException { - // cp_Field: - // *cp_Field_class :DELTA5 (cp_Class) - // *cp_Field_desc :UDELTA5 (cp_Descr) - // cp_Method: - // *cp_Method_class :DELTA5 (cp_Class) - // *cp_Method_desc :UDELTA5 (cp_Descr) - // cp_Imethod: - // *cp_Imethod_class :DELTA5 (cp_Class) - // *cp_Imethod_desc :UDELTA5 (cp_Descr) - cp_class.expectLength(cpMap.length); - cp_class.readFrom(in); - cp_class.setIndex(getCPIndex(CONSTANT_Class)); - cp_desc.expectLength(cpMap.length); - cp_desc.readFrom(in); - cp_desc.setIndex(getCPIndex(CONSTANT_NameandType)); - for (int i = 0; i < cpMap.length; i++) { - ClassEntry mclass = (ClassEntry ) cp_class.getRef(); - DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef(); - cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr); - } - cp_class.doneDisbursing(); - cp_desc.doneDisbursing(); - } - - void readFiles() throws IOException { - // file_bands: - // *file_name :UNSIGNED5 (cp_Utf8) - // *file_size_hi :UNSIGNED5 - // *file_size_lo :UNSIGNED5 - // *file_modtime :DELTA5 - // *file_options :UNSIGNED5 - // *file_bits :BYTE1 - if (verbose > 0) - Utils.log.info(" ...building "+numFiles+" files..."); - file_name.expectLength(numFiles); - file_size_lo.expectLength(numFiles); - int options = archiveOptions; - boolean haveSizeHi = testBit(options, AO_HAVE_FILE_SIZE_HI); - boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME); - boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS); - if (haveSizeHi) - file_size_hi.expectLength(numFiles); - if (haveModtime) - file_modtime.expectLength(numFiles); - if (haveOptions) - file_options.expectLength(numFiles); - - file_name.readFrom(in); - file_size_hi.readFrom(in); - file_size_lo.readFrom(in); - file_modtime.readFrom(in); - file_options.readFrom(in); - file_bits.setInputStreamFrom(in); - - Iterator nextClass = pkg.getClasses().iterator(); - - // Compute file lengths before reading any file bits. - long totalFileLength = 0; - long[] fileLengths = new long[numFiles]; - for (int i = 0; i < numFiles; i++) { - long size = ((long)file_size_lo.getInt() << 32) >>> 32; - if (haveSizeHi) - size += (long)file_size_hi.getInt() << 32; - fileLengths[i] = size; - totalFileLength += size; - } - assert(in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength); - - byte[] buf = new byte[1<<16]; - for (int i = 0; i < numFiles; i++) { - // %%% Use a big temp file for file bits? - Utf8Entry name = (Utf8Entry) file_name.getRef(); - long size = fileLengths[i]; - File file = pkg.new File(name); - file.modtime = pkg.default_modtime; - file.options = pkg.default_options; - if (haveModtime) - file.modtime += file_modtime.getInt(); - if (haveOptions) - file.options |= file_options.getInt(); - if (verbose > 1) - Utils.log.fine("Reading "+size+" bytes of "+name.stringValue()); - long toRead = size; - while (toRead > 0) { - int nr = buf.length; - if (nr > toRead) nr = (int) toRead; - nr = file_bits.getInputStream().read(buf, 0, nr); - if (nr < 0) throw new EOFException(); - file.addBytes(buf, 0, nr); - toRead -= nr; - } - pkg.addFile(file); - if (file.isClassStub()) { - assert(file.getFileLength() == 0); - Class cls = nextClass.next(); - cls.initFile(file); - } - } - - // Do the rest of the classes. - while (nextClass.hasNext()) { - Class cls = nextClass.next(); - cls.initFile(null); // implicitly initialize to a trivial one - cls.file.modtime = pkg.default_modtime; - } - - file_name.doneDisbursing(); - file_size_hi.doneDisbursing(); - file_size_lo.doneDisbursing(); - file_modtime.doneDisbursing(); - file_options.doneDisbursing(); - file_bits.doneDisbursing(); - file_bands.doneDisbursing(); - - if (archiveSize1 != 0 && !in.atLimit()) { - throw new RuntimeException("Predicted archive_size "+ - archiveSize1+" != "+ - (in.getBytesServed()-archiveSize0)); - } - } - - void readAttrDefs() throws IOException { - // attr_definition_bands: - // *attr_definition_headers :BYTE1 - // *attr_definition_name :UNSIGNED5 (cp_Utf8) - // *attr_definition_layout :UNSIGNED5 (cp_Utf8) - attr_definition_headers.expectLength(numAttrDefs); - attr_definition_name.expectLength(numAttrDefs); - attr_definition_layout.expectLength(numAttrDefs); - attr_definition_headers.readFrom(in); - attr_definition_name.readFrom(in); - attr_definition_layout.readFrom(in); - try (PrintStream dump = !optDumpBands ? null - : new PrintStream(getDumpStream(attr_definition_headers, ".def"))) - { - for (int i = 0; i < numAttrDefs; i++) { - int header = attr_definition_headers.getByte(); - Utf8Entry name = (Utf8Entry) attr_definition_name.getRef(); - Utf8Entry layout = (Utf8Entry) attr_definition_layout.getRef(); - int ctype = (header & ADH_CONTEXT_MASK); - int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB; - Attribute.Layout def = new Attribute.Layout(ctype, - name.stringValue(), - layout.stringValue()); - // Check layout string for Java 6 extensions. - String pvLayout = def.layoutForClassVersion(getHighestClassVersion()); - if (!pvLayout.equals(def.layout())) { - throw new IOException("Bad attribute layout in archive: "+def.layout()); - } - this.setAttributeLayoutIndex(def, index); - if (dump != null) dump.println(index+" "+def); - } - } - attr_definition_headers.doneDisbursing(); - attr_definition_name.doneDisbursing(); - attr_definition_layout.doneDisbursing(); - // Attribute layouts define bands, one per layout element. - // Create them now, all at once. - makeNewAttributeBands(); - attr_definition_bands.doneDisbursing(); - } - - void readInnerClasses() throws IOException { - // ic_bands: - // *ic_this_class :UDELTA5 (cp_Class) - // *ic_flags :UNSIGNED5 - // *ic_outer_class :DELTA5 (null or cp_Class) - // *ic_name :DELTA5 (null or cp_Utf8) - ic_this_class.expectLength(numInnerClasses); - ic_this_class.readFrom(in); - ic_flags.expectLength(numInnerClasses); - ic_flags.readFrom(in); - int longICCount = 0; - for (int i = 0; i < numInnerClasses; i++) { - int flags = ic_flags.getInt(); - boolean longForm = (flags & ACC_IC_LONG_FORM) != 0; - if (longForm) { - longICCount += 1; - } - } - ic_outer_class.expectLength(longICCount); - ic_outer_class.readFrom(in); - ic_name.expectLength(longICCount); - ic_name.readFrom(in); - ic_flags.resetForSecondPass(); - List icList = new ArrayList<>(numInnerClasses); - for (int i = 0; i < numInnerClasses; i++) { - int flags = ic_flags.getInt(); - boolean longForm = (flags & ACC_IC_LONG_FORM) != 0; - flags &= ~ACC_IC_LONG_FORM; - ClassEntry thisClass = (ClassEntry) ic_this_class.getRef(); - ClassEntry outerClass; - Utf8Entry thisName; - if (longForm) { - outerClass = (ClassEntry) ic_outer_class.getRef(); - thisName = (Utf8Entry) ic_name.getRef(); - } else { - String n = thisClass.stringValue(); - String[] parse = Package.parseInnerClassName(n); - assert(parse != null); - String pkgOuter = parse[0]; - //String number = parse[1]; - String name = parse[2]; - if (pkgOuter == null) - outerClass = null; - else - outerClass = ConstantPool.getClassEntry(pkgOuter); - if (name == null) - thisName = null; - else - thisName = ConstantPool.getUtf8Entry(name); - } - InnerClass ic = - new InnerClass(thisClass, outerClass, thisName, flags); - assert(longForm || ic.predictable); - icList.add(ic); - } - ic_flags.doneDisbursing(); - ic_this_class.doneDisbursing(); - ic_outer_class.doneDisbursing(); - ic_name.doneDisbursing(); - pkg.setAllInnerClasses(icList); - ic_bands.doneDisbursing(); - } - - void readLocalInnerClasses(Class cls) throws IOException { - int nc = class_InnerClasses_N.getInt(); - List localICs = new ArrayList<>(nc); - for (int i = 0; i < nc; i++) { - ClassEntry thisClass = (ClassEntry) class_InnerClasses_RC.getRef(); - int flags = class_InnerClasses_F.getInt(); - if (flags == 0) { - // A zero flag means copy a global IC here. - InnerClass ic = pkg.getGlobalInnerClass(thisClass); - assert(ic != null); // must be a valid global IC reference - localICs.add(ic); - } else { - if (flags == ACC_IC_LONG_FORM) - flags = 0; // clear the marker bit - ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN.getRef(); - Utf8Entry name = (Utf8Entry) class_InnerClasses_name_RUN.getRef(); - localICs.add(new InnerClass(thisClass, outer, name, flags)); - } - } - cls.setInnerClasses(localICs); - // cls.expandLocalICs may add more tuples to ics also, - // or may even delete tuples. - // We cannot do that now, because we do not know the - // full contents of the local constant pool yet. - } - - static final int NO_FLAGS_YET = 0; // placeholder for later flag read-in - - Class[] readClasses() throws IOException { - // class_bands: - // *class_this :DELTA5 (cp_Class) - // *class_super :DELTA5 (cp_Class) - // *class_interface_count :DELTA5 - // *class_interface :DELTA5 (cp_Class) - // ...(member bands)... - // class_attr_bands - // code_bands - Class[] classes = new Class[numClasses]; - if (verbose > 0) - Utils.log.info(" ...building "+classes.length+" classes..."); - - class_this.expectLength(numClasses); - class_super.expectLength(numClasses); - class_interface_count.expectLength(numClasses); - - class_this.readFrom(in); - class_super.readFrom(in); - class_interface_count.readFrom(in); - class_interface.expectLength(class_interface_count.getIntTotal()); - class_interface.readFrom(in); - for (int i = 0; i < classes.length; i++) { - ClassEntry thisClass = (ClassEntry) class_this.getRef(); - ClassEntry superClass = (ClassEntry) class_super.getRef(); - ClassEntry[] interfaces = new ClassEntry[class_interface_count.getInt()]; - for (int j = 0; j < interfaces.length; j++) { - interfaces[j] = (ClassEntry) class_interface.getRef(); - } - // Packer encoded rare case of null superClass as thisClass: - if (superClass == thisClass) superClass = null; - Class cls = pkg.new Class(NO_FLAGS_YET, - thisClass, superClass, interfaces); - classes[i] = cls; - } - class_this.doneDisbursing(); - class_super.doneDisbursing(); - class_interface_count.doneDisbursing(); - class_interface.doneDisbursing(); - readMembers(classes); - countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes)); - pkg.trimToSize(); - readCodeHeaders(); - //code_bands.doneDisbursing(); // still need to read code attrs - //class_bands.doneDisbursing(); // still need to read code attrs - return classes; - } - - private int getOutputIndex(Entry e) { - // Output CPs do not contain signatures. - assert(e.tag != CONSTANT_Signature); - int k = pkg.cp.untypedIndexOf(e); - // In the output ordering, input signatures can serve - // in place of Utf8s. - if (k >= 0) - return k; - if (e.tag == CONSTANT_Utf8) { - Entry se = utf8Signatures.get(e); - return pkg.cp.untypedIndexOf(se); - } - return -1; - } - - Comparator entryOutputOrder = new Comparator<>() { - public int compare(Entry e0, Entry e1) { - int k0 = getOutputIndex(e0); - int k1 = getOutputIndex(e1); - if (k0 >= 0 && k1 >= 0) - // If both have keys, use the keys. - return k0 - k1; - if (k0 == k1) - // If neither have keys, use their native tags & spellings. - return e0.compareTo(e1); - // Otherwise, the guy with the key comes first. - return (k0 >= 0)? 0-1: 1-0; - } - }; - - void reconstructClass(Class cls) { - if (verbose > 1) Utils.log.fine("reconstruct "+cls); - - // check for local .ClassFile.version - Attribute retroVersion = cls.getAttribute(attrClassFileVersion); - if (retroVersion != null) { - cls.removeAttribute(retroVersion); - cls.version = parseClassFileVersionAttr(retroVersion); - } else { - cls.version = pkg.defaultClassVersion; - } - - // Replace null SourceFile by "obvious" string. - cls.expandSourceFile(); - - // record the local cp: - cls.setCPMap(reconstructLocalCPMap(cls)); - } - - Entry[] reconstructLocalCPMap(Class cls) { - Set ldcRefs = ldcRefMap.get(cls); - Set cpRefs = new HashSet<>(); - - // look for constant pool entries: - cls.visitRefs(VRM_CLASSIC, cpRefs); - - ArrayList bsms = new ArrayList<>(); - // flesh out the local constant pool - ConstantPool.completeReferencesIn(cpRefs, true, bsms); - - // add the bsm and references as required - if (!bsms.isEmpty()) { - cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance()); - cpRefs.add(Package.getRefString("BootstrapMethods")); - Collections.sort(bsms); - cls.setBootstrapMethods(bsms); - } - - // Now that we know all our local class references, - // compute the InnerClasses attribute. - // An InnerClasses attribute usually gets added here, - // although it might already have been present. - int changed = cls.expandLocalICs(); - - if (changed != 0) { - if (changed > 0) { - // Just visit the expanded InnerClasses attr. - cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs); - } else { - // Have to recompute from scratch, because of deletions. - cpRefs.clear(); - cls.visitRefs(VRM_CLASSIC, cpRefs); - } - - // flesh out the local constant pool, again - ConstantPool.completeReferencesIn(cpRefs, true, bsms); - } - - // construct a local constant pool - int numDoubles = 0; - for (Entry e : cpRefs) { - if (e.isDoubleWord()) numDoubles++; - } - Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()]; - int fillp = 1; - - // Add all ldc operands first. - if (ldcRefs != null) { - assert(cpRefs.containsAll(ldcRefs)); - for (Entry e : ldcRefs) { - cpMap[fillp++] = e; - } - assert(fillp == 1+ldcRefs.size()); - cpRefs.removeAll(ldcRefs); - ldcRefs = null; // done with it - } - - // Next add all the two-byte references. - Set wideRefs = cpRefs; - cpRefs = null; // do not use! - int narrowLimit = fillp; - for (Entry e : wideRefs) { - cpMap[fillp++] = e; - } - assert(fillp == narrowLimit+wideRefs.size()); - Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder); - Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder); - - if (verbose > 3) { - Utils.log.fine("CP of "+this+" {"); - for (int i = 0; i < fillp; i++) { - Entry e = cpMap[i]; - Utils.log.fine(" "+((e==null)?-1:getOutputIndex(e)) - +" : "+e); - } - Utils.log.fine("}"); - } - - // Now repack backwards, introducing null elements. - int revp = cpMap.length; - for (int i = fillp; --i >= 1; ) { - Entry e = cpMap[i]; - if (e.isDoubleWord()) - cpMap[--revp] = null; - cpMap[--revp] = e; - } - assert(revp == 1); // do not process the initial null - - return cpMap; - } - - void readMembers(Class[] classes) throws IOException { - // class_bands: - // ... - // *class_field_count :DELTA5 - // *class_method_count :DELTA5 - // - // *field_descr :DELTA5 (cp_Descr) - // field_attr_bands - // - // *method_descr :MDELTA5 (cp_Descr) - // method_attr_bands - // ... - assert(classes.length == numClasses); - class_field_count.expectLength(numClasses); - class_method_count.expectLength(numClasses); - class_field_count.readFrom(in); - class_method_count.readFrom(in); - - // Make a pre-pass over field and method counts to size the descrs: - int totalNF = class_field_count.getIntTotal(); - int totalNM = class_method_count.getIntTotal(); - field_descr.expectLength(totalNF); - method_descr.expectLength(totalNM); - if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+ - " and #methods="+totalNM+" in #classes="+numClasses); - - List fields = new ArrayList<>(totalNF); - field_descr.readFrom(in); - for (int i = 0; i < classes.length; i++) { - Class c = classes[i]; - int nf = class_field_count.getInt(); - for (int j = 0; j < nf; j++) { - Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry) - field_descr.getRef()); - fields.add(f); - } - } - class_field_count.doneDisbursing(); - field_descr.doneDisbursing(); - countAndReadAttrs(ATTR_CONTEXT_FIELD, fields); - fields = null; // release to GC - - List methods = new ArrayList<>(totalNM); - method_descr.readFrom(in); - for (int i = 0; i < classes.length; i++) { - Class c = classes[i]; - int nm = class_method_count.getInt(); - for (int j = 0; j < nm; j++) { - Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry) - method_descr.getRef()); - methods.add(m); - } - } - class_method_count.doneDisbursing(); - method_descr.doneDisbursing(); - countAndReadAttrs(ATTR_CONTEXT_METHOD, methods); - - // Up to this point, Code attributes look like empty attributes. - // Now we start to special-case them. The empty canonical Code - // attributes stay in the method attribute lists, however. - allCodes = buildCodeAttrs(methods); - } - - Code[] allCodes; - List codesWithFlags; - Map> ldcRefMap = new HashMap<>(); - - Code[] buildCodeAttrs(List methods) { - List codes = new ArrayList<>(methods.size()); - for (Class.Method m : methods) { - if (m.getAttribute(attrCodeEmpty) != null) { - m.code = new Code(m); - codes.add(m.code); - } - } - Code[] a = new Code[codes.size()]; - codes.toArray(a); - return a; - } - - void readCodeHeaders() throws IOException { - // code_bands: - // *code_headers :BYTE1 - // - // *code_max_stack :UNSIGNED5 - // *code_max_na_locals :UNSIGNED5 - // *code_handler_count :UNSIGNED5 - // ... - // code_attr_bands - boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS); - code_headers.expectLength(allCodes.length); - code_headers.readFrom(in); - List longCodes = new ArrayList<>(allCodes.length / 10); - for (int i = 0; i < allCodes.length; i++) { - Code c = allCodes[i]; - int sc = code_headers.getByte(); - assert(sc == (sc & 0xFF)); - if (verbose > 2) - Utils.log.fine("codeHeader "+c+" = "+sc); - if (sc == LONG_CODE_HEADER) { - // We will read ms/ml/nh/flags from bands shortly. - longCodes.add(c); - continue; - } - // Short code header is the usual case: - c.setMaxStack( shortCodeHeader_max_stack(sc) ); - c.setMaxNALocals( shortCodeHeader_max_na_locals(sc) ); - c.setHandlerCount( shortCodeHeader_handler_count(sc) ); - assert(shortCodeHeader(c) == sc); - } - code_headers.doneDisbursing(); - code_max_stack.expectLength(longCodes.size()); - code_max_na_locals.expectLength(longCodes.size()); - code_handler_count.expectLength(longCodes.size()); - - // Do the long headers now. - code_max_stack.readFrom(in); - code_max_na_locals.readFrom(in); - code_handler_count.readFrom(in); - for (Code c : longCodes) { - c.setMaxStack( code_max_stack.getInt() ); - c.setMaxNALocals( code_max_na_locals.getInt() ); - c.setHandlerCount( code_handler_count.getInt() ); - } - code_max_stack.doneDisbursing(); - code_max_na_locals.doneDisbursing(); - code_handler_count.doneDisbursing(); - - readCodeHandlers(); - - if (attrsOK) { - // Code attributes are common (debug info not stripped). - codesWithFlags = Arrays.asList(allCodes); - } else { - // Code attributes are very sparse (debug info is stripped). - codesWithFlags = longCodes; - } - countAttrs(ATTR_CONTEXT_CODE, codesWithFlags); - // do readAttrs later, after BCs are scanned - } - - void readCodeHandlers() throws IOException { - // code_bands: - // ... - // *code_handler_start_P :BCI5 - // *code_handler_end_PO :BRANCH5 - // *code_handler_catch_PO :BRANCH5 - // *code_handler_class_RCN :UNSIGNED5 (null or cp_Class) - // ... - int nh = 0; - for (int i = 0; i < allCodes.length; i++) { - Code c = allCodes[i]; - nh += c.getHandlerCount(); - } - - ValueBand[] code_handler_bands = { - code_handler_start_P, - code_handler_end_PO, - code_handler_catch_PO, - code_handler_class_RCN - }; - - for (int i = 0; i < code_handler_bands.length; i++) { - code_handler_bands[i].expectLength(nh); - code_handler_bands[i].readFrom(in); - } - - for (int i = 0; i < allCodes.length; i++) { - Code c = allCodes[i]; - for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { - c.handler_class[j] = code_handler_class_RCN.getRef(); - // For now, just record the raw BCI codes. - // We must wait until we have instruction boundaries. - c.handler_start[j] = code_handler_start_P.getInt(); - c.handler_end[j] = code_handler_end_PO.getInt(); - c.handler_catch[j] = code_handler_catch_PO.getInt(); - } - } - for (int i = 0; i < code_handler_bands.length; i++) { - code_handler_bands[i].doneDisbursing(); - } - } - - void fixupCodeHandlers() { - // Actually decode (renumber) the BCIs now. - for (int i = 0; i < allCodes.length; i++) { - Code c = allCodes[i]; - for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { - int sum = c.handler_start[j]; - c.handler_start[j] = c.decodeBCI(sum); - sum += c.handler_end[j]; - c.handler_end[j] = c.decodeBCI(sum); - sum += c.handler_catch[j]; - c.handler_catch[j] = c.decodeBCI(sum); - } - } - } - - // Generic routines for reading attributes of - // classes, fields, methods, and codes. - // The holders is a global list, already collected, - // of attribute "customers". - void countAndReadAttrs(int ctype, Collection holders) - throws IOException { - // class_attr_bands: - // *class_flags :UNSIGNED5 - // *class_attr_count :UNSIGNED5 - // *class_attr_indexes :UNSIGNED5 - // *class_attr_calls :UNSIGNED5 - // *class_Signature_RS :UNSIGNED5 (cp_Signature) - // class_metadata_bands - // *class_SourceFile_RU :UNSIGNED5 (cp_Utf8) - // *class_EnclosingMethod_RM :UNSIGNED5 (cp_Method) - // ic_local_bands - // *class_ClassFile_version_minor_H :UNSIGNED5 - // *class_ClassFile_version_major_H :UNSIGNED5 - // class_type_metadata_bands - // - // field_attr_bands: - // *field_flags :UNSIGNED5 - // *field_attr_count :UNSIGNED5 - // *field_attr_indexes :UNSIGNED5 - // *field_attr_calls :UNSIGNED5 - // *field_Signature_RS :UNSIGNED5 (cp_Signature) - // field_metadata_bands - // *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note) - // field_type_metadata_bands - // - // method_attr_bands: - // *method_flags :UNSIGNED5 - // *method_attr_count :UNSIGNED5 - // *method_attr_indexes :UNSIGNED5 - // *method_attr_calls :UNSIGNED5 - // *method_Signature_RS :UNSIGNED5 (cp_Signature) - // method_metadata_bands - // *method_Exceptions_N :UNSIGNED5 - // *method_Exceptions_RC :UNSIGNED5 (cp_Class) - // *method_MethodParameters_NB: BYTE1 - // *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8) - // *method_MethodParameters_FH: UNSIGNED5 (flag) - // method_type_metadata_bands - // - // code_attr_bands: - // *code_flags :UNSIGNED5 - // *code_attr_count :UNSIGNED5 - // *code_attr_indexes :UNSIGNED5 - // *code_attr_calls :UNSIGNED5 - // *code_LineNumberTable_N :UNSIGNED5 - // *code_LineNumberTable_bci_P :BCI5 - // *code_LineNumberTable_line :UNSIGNED5 - // *code_LocalVariableTable_N :UNSIGNED5 - // *code_LocalVariableTable_bci_P :BCI5 - // *code_LocalVariableTable_span_O :BRANCH5 - // *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8) - // *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature) - // *code_LocalVariableTable_slot :UNSIGNED5 - // code_type_metadata_bands - - countAttrs(ctype, holders); - readAttrs(ctype, holders); - } - - // Read flags and count the attributes that are to be placed - // on the given holders. - void countAttrs(int ctype, Collection holders) - throws IOException { - // Here, xxx stands for one of class, field, method, code. - MultiBand xxx_attr_bands = attrBands[ctype]; - long flagMask = attrFlagMask[ctype]; - if (verbose > 1) { - Utils.log.fine("scanning flags and attrs for "+ - Attribute.contextName(ctype)+"["+holders.size()+"]"); - } - - // Fetch the attribute layout definitions which govern the bands - // we are about to read. - List defList = attrDefs.get(ctype); - Attribute.Layout[] defs = new Attribute.Layout[defList.size()]; - defList.toArray(defs); - IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI); - IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO); - IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT); - IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES); - IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS); - - // Count up the number of holders which have overflow attrs. - int overflowMask = attrOverflowMask[ctype]; - int overflowHolderCount = 0; - boolean haveLongFlags = haveFlagsHi(ctype); - xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0); - xxx_flags_hi.readFrom(in); - xxx_flags_lo.expectLength(holders.size()); - xxx_flags_lo.readFrom(in); - assert((flagMask & overflowMask) == overflowMask); - for (Attribute.Holder h : holders) { - int flags = xxx_flags_lo.getInt(); - h.flags = flags; - if ((flags & overflowMask) != 0) - overflowHolderCount += 1; - } - - // For each holder with overflow attrs, read a count. - xxx_attr_count.expectLength(overflowHolderCount); - xxx_attr_count.readFrom(in); - xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal()); - xxx_attr_indexes.readFrom(in); - - // Now it's time to check flag bits that indicate attributes. - // We accumulate (a) a list of attribute types for each holder - // (class/field/method/code), and also we accumulate (b) a total - // count for each attribute type. - int[] totalCounts = new int[defs.length]; - for (Attribute.Holder h : holders) { - assert(h.attributes == null); - // System.out.println("flags="+h.flags+" using fm="+flagMask); - long attrBits = ((h.flags & flagMask) << 32) >>> 32; - // Clean up the flags now. - h.flags -= (int)attrBits; // strip attr bits - assert(h.flags == (char)h.flags); // 16 bits only now - assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0); - if (haveLongFlags) - attrBits += (long)xxx_flags_hi.getInt() << 32; - if (attrBits == 0) continue; // no attrs on this guy - - int noa = 0; // number of overflow attrs - long overflowBit = (attrBits & overflowMask); - assert(overflowBit >= 0); - attrBits -= overflowBit; - if (overflowBit != 0) { - noa = xxx_attr_count.getInt(); - } - - int nfa = 0; // number of flag attrs - long bits = attrBits; - for (int ai = 0; bits != 0; ai++) { - if ((bits & (1L< ha = new ArrayList<>(nfa + noa); - h.attributes = ha; - bits = attrBits; // iterate again - for (int ai = 0; bits != 0; ai++) { - if ((bits & (1L< 0; noa--) { - int ai = xxx_attr_indexes.getInt(); - totalCounts[ai] += 1; - // This definition index is live in this holder. - if (defs[ai] == null) badAttrIndex(ai, ctype); - Attribute canonical = defs[ai].canonicalInstance(); - ha.add(canonical); - } - } - - xxx_flags_hi.doneDisbursing(); - xxx_flags_lo.doneDisbursing(); - xxx_attr_count.doneDisbursing(); - xxx_attr_indexes.doneDisbursing(); - - // Now each holder has a list of canonical attribute instances. - // For layouts with no elements, we are done. However, for - // layouts with bands, we must replace each canonical (empty) - // instance with a value-bearing one, initialized from the - // appropriate bands. - - // Make a small pass to detect and read backward call counts. - int callCounts = 0; - for (boolean predef = true; ; predef = false) { - for (int ai = 0; ai < defs.length; ai++) { - Attribute.Layout def = defs[ai]; - if (def == null) continue; // unused index - if (predef != isPredefinedAttr(ctype, ai)) - continue; // wrong pass - int totalCount = totalCounts[ai]; - if (totalCount == 0) - continue; // irrelevant - Attribute.Layout.Element[] cbles = def.getCallables(); - for (int j = 0; j < cbles.length; j++) { - assert(cbles[j].kind == Attribute.EK_CBLE); - if (cbles[j].flagTest(Attribute.EF_BACK)) - callCounts += 1; - } - } - if (!predef) break; - } - xxx_attr_calls.expectLength(callCounts); - xxx_attr_calls.readFrom(in); - - // Finally, size all the attribute bands. - for (boolean predef = true; ; predef = false) { - for (int ai = 0; ai < defs.length; ai++) { - Attribute.Layout def = defs[ai]; - if (def == null) continue; // unused index - if (predef != isPredefinedAttr(ctype, ai)) - continue; // wrong pass - int totalCount = totalCounts[ai]; - Band[] ab = attrBandTable.get(def); - if (def == attrInnerClassesEmpty) { - // Special case. - // Size the bands as if using the following layout: - // [RCH TI[ (0)[] ()[RCNH RUNH] ]]. - class_InnerClasses_N.expectLength(totalCount); - class_InnerClasses_N.readFrom(in); - int tupleCount = class_InnerClasses_N.getIntTotal(); - class_InnerClasses_RC.expectLength(tupleCount); - class_InnerClasses_RC.readFrom(in); - class_InnerClasses_F.expectLength(tupleCount); - class_InnerClasses_F.readFrom(in); - // Drop remaining columns wherever flags are zero: - tupleCount -= class_InnerClasses_F.getIntCount(0); - class_InnerClasses_outer_RCN.expectLength(tupleCount); - class_InnerClasses_outer_RCN.readFrom(in); - class_InnerClasses_name_RUN.expectLength(tupleCount); - class_InnerClasses_name_RUN.readFrom(in); - } else if (!optDebugBands && totalCount == 0) { - // Expect no elements at all. Skip quickly. however if we - // are debugging bands, read all bands regardless - for (int j = 0; j < ab.length; j++) { - ab[j].doneWithUnusedBand(); - } - } else { - // Read these bands in sequence. - boolean hasCallables = def.hasCallables(); - if (!hasCallables) { - readAttrBands(def.elems, totalCount, new int[0], ab); - } else { - Attribute.Layout.Element[] cbles = def.getCallables(); - // At first, record initial calls. - // Later, forward calls may also accumulate here: - int[] forwardCounts = new int[cbles.length]; - forwardCounts[0] = totalCount; - for (int j = 0; j < cbles.length; j++) { - assert(cbles[j].kind == Attribute.EK_CBLE); - int entryCount = forwardCounts[j]; - forwardCounts[j] = -1; // No more, please! - if (totalCount > 0 && cbles[j].flagTest(Attribute.EF_BACK)) - entryCount += xxx_attr_calls.getInt(); - readAttrBands(cbles[j].body, entryCount, forwardCounts, ab); - } - } - // mark them read, to satisfy asserts - if (optDebugBands && totalCount == 0) { - for (int j = 0; j < ab.length; j++) { - ab[j].doneDisbursing(); - } - } - } - } - if (!predef) break; - } - xxx_attr_calls.doneDisbursing(); - } - - void badAttrIndex(int ai, int ctype) throws IOException { - throw new IOException("Unknown attribute index "+ai+" for "+ - ATTR_CONTEXT_NAME[ctype]+" attribute"); - } - - void readAttrs(int ctype, Collection holders) - throws IOException { - // Decode band values into attributes. - Set sawDefs = new HashSet<>(); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - for (final Attribute.Holder h : holders) { - if (h.attributes == null) continue; - for (ListIterator j = h.attributes.listIterator(); j.hasNext(); ) { - Attribute a = j.next(); - Attribute.Layout def = a.layout(); - if (def.bandCount == 0) { - if (def == attrInnerClassesEmpty) { - // Special logic to read this attr. - readLocalInnerClasses((Class) h); - continue; - } - // Canonical empty attr works fine (e.g., Synthetic). - continue; - } - sawDefs.add(def); - boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue); - if (isCV) setConstantValueIndex((Class.Field)h); - if (verbose > 2) - Utils.log.fine("read "+a+" in "+h); - final Band[] ab = attrBandTable.get(def); - // Read one attribute of type def from ab into a byte array. - buf.reset(); - Object fixups = a.unparse(new Attribute.ValueStream() { - public int getInt(int bandIndex) { - return ((IntBand) ab[bandIndex]).getInt(); - } - public Entry getRef(int bandIndex) { - return ((CPRefBand) ab[bandIndex]).getRef(); - } - public int decodeBCI(int bciCode) { - Code code = (Code) h; - return code.decodeBCI(bciCode); - } - }, buf); - // Replace the canonical attr with the one just read. - j.set(a.addContent(buf.toByteArray(), fixups)); - if (isCV) setConstantValueIndex(null); // clean up - } - } - - // Mark the bands we just used as done disbursing. - for (Attribute.Layout def : sawDefs) { - if (def == null) continue; // unused index - Band[] ab = attrBandTable.get(def); - for (int j = 0; j < ab.length; j++) { - ab[j].doneDisbursing(); - } - } - - if (ctype == ATTR_CONTEXT_CLASS) { - class_InnerClasses_N.doneDisbursing(); - class_InnerClasses_RC.doneDisbursing(); - class_InnerClasses_F.doneDisbursing(); - class_InnerClasses_outer_RCN.doneDisbursing(); - class_InnerClasses_name_RUN.doneDisbursing(); - } - - MultiBand xxx_attr_bands = attrBands[ctype]; - for (int i = 0; i < xxx_attr_bands.size(); i++) { - Band b = xxx_attr_bands.get(i); - if (b instanceof MultiBand) - b.doneDisbursing(); - } - xxx_attr_bands.doneDisbursing(); - } - - private - void readAttrBands(Attribute.Layout.Element[] elems, - int count, int[] forwardCounts, - Band[] ab) - throws IOException { - for (int i = 0; i < elems.length; i++) { - Attribute.Layout.Element e = elems[i]; - Band eBand = null; - if (e.hasBand()) { - eBand = ab[e.bandIndex]; - eBand.expectLength(count); - eBand.readFrom(in); - } - switch (e.kind) { - case Attribute.EK_REPL: - // Recursive call. - int repCount = ((IntBand)eBand).getIntTotal(); - // Note: getIntTotal makes an extra pass over this band. - readAttrBands(e.body, repCount, forwardCounts, ab); - break; - case Attribute.EK_UN: - int remainingCount = count; - for (int j = 0; j < e.body.length; j++) { - int caseCount; - if (j == e.body.length-1) { - caseCount = remainingCount; - } else { - caseCount = 0; - for (int j0 = j; - (j == j0) - || (j < e.body.length - && e.body[j].flagTest(Attribute.EF_BACK)); - j++) { - caseCount += ((IntBand)eBand).getIntCount(e.body[j].value); - } - --j; // back up to last occurrence of this body - } - remainingCount -= caseCount; - readAttrBands(e.body[j].body, caseCount, forwardCounts, ab); - } - assert(remainingCount == 0); - break; - case Attribute.EK_CALL: - assert(e.body.length == 1); - assert(e.body[0].kind == Attribute.EK_CBLE); - if (!e.flagTest(Attribute.EF_BACK)) { - // Backward calls are pre-counted, but forwards are not. - // Push the present count forward. - assert(forwardCounts[e.value] >= 0); - forwardCounts[e.value] += count; - } - break; - case Attribute.EK_CBLE: - assert(false); - break; - } - } - } - - void readByteCodes() throws IOException { - // bc_bands: - // *bc_codes :BYTE1 - // *bc_case_count :UNSIGNED5 - // *bc_case_value :DELTA5 - // *bc_byte :BYTE1 - // *bc_short :DELTA5 - // *bc_local :UNSIGNED5 - // *bc_label :BRANCH5 - // *bc_intref :DELTA5 (cp_Int) - // *bc_floatref :DELTA5 (cp_Float) - // *bc_longref :DELTA5 (cp_Long) - // *bc_doubleref :DELTA5 (cp_Double) - // *bc_stringref :DELTA5 (cp_String) - // *bc_classref :UNSIGNED5 (current class or cp_Class) - // *bc_fieldref :DELTA5 (cp_Field) - // *bc_methodref :UNSIGNED5 (cp_Method) - // *bc_imethodref :DELTA5 (cp_Imethod) - // *bc_thisfield :UNSIGNED5 (cp_Field, only for current class) - // *bc_superfield :UNSIGNED5 (cp_Field, only for current super) - // *bc_thismethod :UNSIGNED5 (cp_Method, only for current class) - // *bc_supermethod :UNSIGNED5 (cp_Method, only for current super) - // *bc_initref :UNSIGNED5 (cp_Field, only for most recent new) - // *bc_escref :UNSIGNED5 (cp_All) - // *bc_escrefsize :UNSIGNED5 - // *bc_escsize :UNSIGNED5 - // *bc_escbyte :BYTE1 - bc_codes.elementCountForDebug = allCodes.length; - bc_codes.setInputStreamFrom(in); - readByteCodeOps(); // reads from bc_codes and bc_case_count - bc_codes.doneDisbursing(); - - // All the operand bands have now been sized. Read them all in turn. - Band[] operand_bands = { - bc_case_value, - bc_byte, bc_short, - bc_local, bc_label, - bc_intref, bc_floatref, - bc_longref, bc_doubleref, bc_stringref, - bc_loadablevalueref, - bc_classref, bc_fieldref, - bc_methodref, bc_imethodref, - bc_indyref, - bc_thisfield, bc_superfield, - bc_thismethod, bc_supermethod, - bc_initref, - bc_escref, bc_escrefsize, bc_escsize - }; - for (int i = 0; i < operand_bands.length; i++) { - operand_bands[i].readFrom(in); - } - bc_escbyte.expectLength(bc_escsize.getIntTotal()); - bc_escbyte.readFrom(in); - - expandByteCodeOps(); - - // Done fetching values from operand bands: - bc_case_count.doneDisbursing(); - for (int i = 0; i < operand_bands.length; i++) { - operand_bands[i].doneDisbursing(); - } - bc_escbyte.doneDisbursing(); - bc_bands.doneDisbursing(); - - // We must delay the parsing of Code attributes until we - // have a complete model of bytecodes, for BCI encodings. - readAttrs(ATTR_CONTEXT_CODE, codesWithFlags); - // Ditto for exception handlers in codes. - fixupCodeHandlers(); - // Now we can finish with class_bands; cf. readClasses(). - code_bands.doneDisbursing(); - class_bands.doneDisbursing(); - } - - private void readByteCodeOps() throws IOException { - // scratch buffer for collecting code:: - byte[] buf = new byte[1<<12]; - // record of all switch opcodes (these are variable-length) - List allSwitchOps = new ArrayList<>(); - for (int k = 0; k < allCodes.length; k++) { - Code c = allCodes[k]; - scanOneMethod: - for (int i = 0; ; i++) { - int bc = bc_codes.getByte(); - if (i + 10 > buf.length) buf = realloc(buf); - buf[i] = (byte)bc; - boolean isWide = false; - if (bc == _wide) { - bc = bc_codes.getByte(); - buf[++i] = (byte)bc; - isWide = true; - } - assert(bc == (0xFF & bc)); - // Adjust expectations of various band sizes. - switch (bc) { - case _tableswitch: - case _lookupswitch: - bc_case_count.expectMoreLength(1); - allSwitchOps.add(bc); - break; - case _iinc: - bc_local.expectMoreLength(1); - if (isWide) - bc_short.expectMoreLength(1); - else - bc_byte.expectMoreLength(1); - break; - case _sipush: - bc_short.expectMoreLength(1); - break; - case _bipush: - bc_byte.expectMoreLength(1); - break; - case _newarray: - bc_byte.expectMoreLength(1); - break; - case _multianewarray: - assert(getCPRefOpBand(bc) == bc_classref); - bc_classref.expectMoreLength(1); - bc_byte.expectMoreLength(1); - break; - case _ref_escape: - bc_escrefsize.expectMoreLength(1); - bc_escref.expectMoreLength(1); - break; - case _byte_escape: - bc_escsize.expectMoreLength(1); - // bc_escbyte will have to be counted too - break; - default: - if (Instruction.isInvokeInitOp(bc)) { - bc_initref.expectMoreLength(1); - break; - } - if (Instruction.isSelfLinkerOp(bc)) { - CPRefBand bc_which = selfOpRefBand(bc); - bc_which.expectMoreLength(1); - break; - } - if (Instruction.isBranchOp(bc)) { - bc_label.expectMoreLength(1); - break; - } - if (Instruction.isCPRefOp(bc)) { - CPRefBand bc_which = getCPRefOpBand(bc); - bc_which.expectMoreLength(1); - assert(bc != _multianewarray); // handled elsewhere - break; - } - if (Instruction.isLocalSlotOp(bc)) { - bc_local.expectMoreLength(1); - break; - } - break; - case _end_marker: - { - // Transfer from buf to a more permanent place: - c.bytes = realloc(buf, i); - break scanOneMethod; - } - } - } - } - - // To size instruction bands correctly, we need info on switches: - bc_case_count.readFrom(in); - for (Integer i : allSwitchOps) { - int bc = i.intValue(); - int caseCount = bc_case_count.getInt(); - bc_label.expectMoreLength(1+caseCount); // default label + cases - bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount); - } - bc_case_count.resetForSecondPass(); - } - - private void expandByteCodeOps() throws IOException { - // scratch buffer for collecting code: - byte[] buf = new byte[1<<12]; - // scratch buffer for collecting instruction boundaries: - int[] insnMap = new int[1<<12]; - // list of label carriers, for label decoding post-pass: - int[] labels = new int[1<<10]; - // scratch buffer for registering CP refs: - Fixups fixupBuf = new Fixups(); - - for (int k = 0; k < allCodes.length; k++) { - Code code = allCodes[k]; - byte[] codeOps = code.bytes; - code.bytes = null; // just for now, while we accumulate bits - - Class curClass = code.thisClass(); - - Set ldcRefSet = ldcRefMap.get(curClass); - if (ldcRefSet == null) - ldcRefMap.put(curClass, ldcRefSet = new HashSet<>()); - - ClassEntry thisClass = curClass.thisClass; - ClassEntry superClass = curClass.superClass; - ClassEntry newClass = null; // class of last _new opcode - - int pc = 0; // fill pointer in buf; actual bytecode PC - int numInsns = 0; - int numLabels = 0; - boolean hasEscs = false; - fixupBuf.clear(); - for (int i = 0; i < codeOps.length; i++) { - int bc = Instruction.getByte(codeOps, i); - int curPC = pc; - insnMap[numInsns++] = curPC; - if (pc + 10 > buf.length) buf = realloc(buf); - if (numInsns+10 > insnMap.length) insnMap = realloc(insnMap); - if (numLabels+10 > labels.length) labels = realloc(labels); - boolean isWide = false; - if (bc == _wide) { - buf[pc++] = (byte) bc; - bc = Instruction.getByte(codeOps, ++i); - isWide = true; - } - switch (bc) { - case _tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) - case _lookupswitch: // apc: (df, nc, nc*(case, label)) - { - int caseCount = bc_case_count.getInt(); - while ((pc + 30 + caseCount*8) > buf.length) - buf = realloc(buf); - buf[pc++] = (byte) bc; - //initialize apc, df, lo, hi bytes to reasonable bits: - Arrays.fill(buf, pc, pc+30, (byte)0); - Instruction.Switch isw = (Instruction.Switch) - Instruction.at(buf, curPC); - //isw.setDefaultLabel(getLabel(bc_label, code, curPC)); - isw.setCaseCount(caseCount); - if (bc == _tableswitch) { - isw.setCaseValue(0, bc_case_value.getInt()); - } else { - for (int j = 0; j < caseCount; j++) { - isw.setCaseValue(j, bc_case_value.getInt()); - } - } - // Make our getLabel calls later. - labels[numLabels++] = curPC; - pc = isw.getNextPC(); - continue; - } - case _iinc: - { - buf[pc++] = (byte) bc; - int local = bc_local.getInt(); - int delta; - if (isWide) { - delta = bc_short.getInt(); - Instruction.setShort(buf, pc, local); pc += 2; - Instruction.setShort(buf, pc, delta); pc += 2; - } else { - delta = (byte) bc_byte.getByte(); - buf[pc++] = (byte)local; - buf[pc++] = (byte)delta; - } - continue; - } - case _sipush: - { - int val = bc_short.getInt(); - buf[pc++] = (byte) bc; - Instruction.setShort(buf, pc, val); pc += 2; - continue; - } - case _bipush: - case _newarray: - { - int val = bc_byte.getByte(); - buf[pc++] = (byte) bc; - buf[pc++] = (byte) val; - continue; - } - case _ref_escape: - { - // Note that insnMap has one entry for this. - hasEscs = true; - int size = bc_escrefsize.getInt(); - Entry ref = bc_escref.getRef(); - if (size == 1) ldcRefSet.add(ref); - int fmt; - switch (size) { - case 1: fixupBuf.addU1(pc, ref); break; - case 2: fixupBuf.addU2(pc, ref); break; - default: assert(false); fmt = 0; - } - buf[pc+0] = buf[pc+1] = 0; - pc += size; - } - continue; - case _byte_escape: - { - // Note that insnMap has one entry for all these bytes. - hasEscs = true; - int size = bc_escsize.getInt(); - while ((pc + size) > buf.length) - buf = realloc(buf); - while (size-- > 0) { - buf[pc++] = (byte) bc_escbyte.getByte(); - } - } - continue; - default: - if (Instruction.isInvokeInitOp(bc)) { - int idx = (bc - _invokeinit_op); - int origBC = _invokespecial; - ClassEntry classRef; - switch (idx) { - case _invokeinit_self_option: - classRef = thisClass; break; - case _invokeinit_super_option: - classRef = superClass; break; - default: - assert(idx == _invokeinit_new_option); - classRef = newClass; break; - } - buf[pc++] = (byte) origBC; - int coding = bc_initref.getInt(); - // Find the nth overloading of in classRef. - MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "", coding); - fixupBuf.addU2(pc, ref); - buf[pc+0] = buf[pc+1] = 0; - pc += 2; - assert(Instruction.opLength(origBC) == (pc - curPC)); - continue; - } - if (Instruction.isSelfLinkerOp(bc)) { - int idx = (bc - _self_linker_op); - boolean isSuper = (idx >= _self_linker_super_flag); - if (isSuper) idx -= _self_linker_super_flag; - boolean isAload = (idx >= _self_linker_aload_flag); - if (isAload) idx -= _self_linker_aload_flag; - int origBC = _first_linker_op + idx; - boolean isField = Instruction.isFieldOp(origBC); - CPRefBand bc_which; - ClassEntry which_cls = isSuper ? superClass : thisClass; - Index which_ix; - if (isField) { - bc_which = isSuper ? bc_superfield : bc_thisfield; - which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls); - } else { - bc_which = isSuper ? bc_supermethod : bc_thismethod; - which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls); - } - assert(bc_which == selfOpRefBand(bc)); - MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix); - if (isAload) { - buf[pc++] = (byte) _aload_0; - curPC = pc; - // Note: insnMap keeps the _aload_0 separate. - insnMap[numInsns++] = curPC; - } - buf[pc++] = (byte) origBC; - fixupBuf.addU2(pc, ref); - buf[pc+0] = buf[pc+1] = 0; - pc += 2; - assert(Instruction.opLength(origBC) == (pc - curPC)); - continue; - } - if (Instruction.isBranchOp(bc)) { - buf[pc++] = (byte) bc; - assert(!isWide); // no wide prefix for branches - int nextPC = curPC + Instruction.opLength(bc); - // Make our getLabel calls later. - labels[numLabels++] = curPC; - //Instruction.at(buf, curPC).setBranchLabel(getLabel(bc_label, code, curPC)); - while (pc < nextPC) buf[pc++] = 0; - continue; - } - if (Instruction.isCPRefOp(bc)) { - CPRefBand bc_which = getCPRefOpBand(bc); - Entry ref = bc_which.getRef(); - if (ref == null) { - if (bc_which == bc_classref) { - // Shorthand for class self-references. - ref = thisClass; - } else { - assert(false); - } - } - int origBC = bc; - int size = 2; - switch (bc) { - case _invokestatic_int: - origBC = _invokestatic; - break; - case _invokespecial_int: - origBC = _invokespecial; - break; - case _ildc: - case _cldc: - case _fldc: - case _sldc: - case _qldc: - origBC = _ldc; - size = 1; - ldcRefSet.add(ref); - break; - case _ildc_w: - case _cldc_w: - case _fldc_w: - case _sldc_w: - case _qldc_w: - origBC = _ldc_w; - break; - case _lldc2_w: - case _dldc2_w: - origBC = _ldc2_w; - break; - case _new: - newClass = (ClassEntry) ref; - break; - } - buf[pc++] = (byte) origBC; - int fmt; - switch (size) { - case 1: fixupBuf.addU1(pc, ref); break; - case 2: fixupBuf.addU2(pc, ref); break; - default: assert(false); fmt = 0; - } - buf[pc+0] = buf[pc+1] = 0; - pc += size; - if (origBC == _multianewarray) { - // Copy the trailing byte also. - int val = bc_byte.getByte(); - buf[pc++] = (byte) val; - } else if (origBC == _invokeinterface) { - int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true); - buf[pc++] = (byte)( 1 + argSize ); - buf[pc++] = 0; - } else if (origBC == _invokedynamic) { - buf[pc++] = 0; - buf[pc++] = 0; - } - assert(Instruction.opLength(origBC) == (pc - curPC)); - continue; - } - if (Instruction.isLocalSlotOp(bc)) { - buf[pc++] = (byte) bc; - int local = bc_local.getInt(); - if (isWide) { - Instruction.setShort(buf, pc, local); - pc += 2; - if (bc == _iinc) { - int iVal = bc_short.getInt(); - Instruction.setShort(buf, pc, iVal); - pc += 2; - } - } else { - Instruction.setByte(buf, pc, local); - pc += 1; - if (bc == _iinc) { - int iVal = bc_byte.getByte(); - Instruction.setByte(buf, pc, iVal); - pc += 1; - } - } - assert(Instruction.opLength(bc) == (pc - curPC)); - continue; - } - // Random bytecode. Just copy it. - if (bc >= _bytecode_limit) - Utils.log.warning("unrecognized bytescode "+bc - +" "+Instruction.byteName(bc)); - assert(bc < _bytecode_limit); - buf[pc++] = (byte) bc; - assert(Instruction.opLength(bc) == (pc - curPC)); - continue; - } - } - // now make a permanent copy of the bytecodes - code.setBytes(realloc(buf, pc)); - code.setInstructionMap(insnMap, numInsns); - // fix up labels, now that code has its insnMap - Instruction ibr = null; // temporary branch instruction - for (int i = 0; i < numLabels; i++) { - int curPC = labels[i]; - // (Note: Passing ibr in allows reuse, a speed hack.) - ibr = Instruction.at(code.bytes, curPC, ibr); - if (ibr instanceof Instruction.Switch) { - Instruction.Switch isw = (Instruction.Switch) ibr; - isw.setDefaultLabel(getLabel(bc_label, code, curPC)); - int caseCount = isw.getCaseCount(); - for (int j = 0; j < caseCount; j++) { - isw.setCaseLabel(j, getLabel(bc_label, code, curPC)); - } - } else { - ibr.setBranchLabel(getLabel(bc_label, code, curPC)); - } - } - if (fixupBuf.size() > 0) { - if (verbose > 2) - Utils.log.fine("Fixups in code: "+fixupBuf); - code.addFixups(fixupBuf); - } - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageWriter.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageWriter.java deleted file mode 100644 index 2447fa45e8b..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +++ /dev/null @@ -1,1743 +0,0 @@ -/* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.*; -import com.sun.java.util.jar.pack.Package.Class; -import com.sun.java.util.jar.pack.Package.File; -import com.sun.java.util.jar.pack.Package.InnerClass; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Writer for a package file. - * @author John Rose - */ -class PackageWriter extends BandStructure { - Package pkg; - OutputStream finalOut; - Package.Version packageVersion; - - PackageWriter(Package pkg, OutputStream out) throws IOException { - this.pkg = pkg; - this.finalOut = out; - // Caller has specified maximum class file version in the package: - initHighestClassVersion(pkg.getHighestClassVersion()); - } - - void write() throws IOException { - boolean ok = false; - try { - if (verbose > 0) { - Utils.log.info("Setting up constant pool..."); - } - setup(); - - if (verbose > 0) { - Utils.log.info("Packing..."); - } - - // writeFileHeader() is done last, since it has ultimate counts - // writeBandHeaders() is called after all other bands are done - writeConstantPool(); - writeFiles(); - writeAttrDefs(); - writeInnerClasses(); - writeClassesAndByteCodes(); - writeAttrCounts(); - - if (verbose > 1) printCodeHist(); - - // choose codings (fill band_headers if needed) - if (verbose > 0) { - Utils.log.info("Coding..."); - } - all_bands.chooseBandCodings(); - - // now we can write the headers: - writeFileHeader(); - - writeAllBandsTo(finalOut); - - ok = true; - } catch (Exception ee) { - Utils.log.warning("Error on output: "+ee, ee); - //if (verbose > 0) ee.printStackTrace(); - // Write partial output only if we are verbose. - if (verbose > 0) finalOut.close(); - if (ee instanceof IOException) throw (IOException)ee; - if (ee instanceof RuntimeException) throw (RuntimeException)ee; - throw new Error("error packing", ee); - } - } - - Set requiredEntries; // for the CP - Map backCountTable; // for layout callables - int[][] attrCounts; // count attr. occurrences - - void setup() { - requiredEntries = new HashSet<>(); - setArchiveOptions(); - trimClassAttributes(); - collectAttributeLayouts(); - pkg.buildGlobalConstantPool(requiredEntries); - setBandIndexes(); - makeNewAttributeBands(); - collectInnerClasses(); - } - - /* - * Convenience function to choose an archive version based - * on the class file versions observed within the archive - * or set the user defined version preset via properties. - */ - void chooseDefaultPackageVersion() throws IOException { - if (pkg.packageVersion != null) { - packageVersion = pkg.packageVersion; - if (verbose > 0) { - Utils.log.info("package version overridden with: " - + packageVersion); - } - return; - } - - Package.Version highV = getHighestClassVersion(); - // set the package version now - if (highV.lessThan(JAVA6_MAX_CLASS_VERSION)) { - // There are only old classfiles in this segment or resources - packageVersion = JAVA5_PACKAGE_VERSION; - } else if (highV.equals(JAVA6_MAX_CLASS_VERSION) || - (highV.equals(JAVA7_MAX_CLASS_VERSION) && !pkg.cp.haveExtraTags())) { - // force down the package version if we have jdk7 classes without - // any Indy references, this is because jdk7 class file (51.0) without - // Indy is identical to jdk6 class file (50.0). - packageVersion = JAVA6_PACKAGE_VERSION; - } else if (highV.equals(JAVA7_MAX_CLASS_VERSION)) { - packageVersion = JAVA7_PACKAGE_VERSION; - } else { - // Normal case. Use the newest archive format, when available - packageVersion = JAVA8_PACKAGE_VERSION; - } - - if (verbose > 0) { - Utils.log.info("Highest version class file: " + highV - + " package version: " + packageVersion); - } - } - - void checkVersion() throws IOException { - assert(packageVersion != null); - - if (packageVersion.lessThan(JAVA7_PACKAGE_VERSION)) { - // this bit was reserved for future use in previous versions - if (testBit(archiveOptions, AO_HAVE_CP_EXTRAS)) { - throw new IOException("Format bits for Java 7 must be zero in previous releases"); - } - } - if (testBit(archiveOptions, AO_UNUSED_MBZ)) { - throw new IOException("High archive option bits are reserved and must be zero: " + Integer.toHexString(archiveOptions)); - } - } - - void setArchiveOptions() { - // Decide on some archive options early. - // Does not decide on: AO_HAVE_SPECIAL_FORMATS, - // AO_HAVE_CP_NUMBERS, AO_HAVE_FILE_HEADERS. - // Also, AO_HAVE_FILE_OPTIONS may be forced on later. - int minModtime = pkg.default_modtime; - int maxModtime = pkg.default_modtime; - int minOptions = -1; - int maxOptions = 0; - - // Import defaults from package (deflate hint, etc.). - archiveOptions |= pkg.default_options; - - for (File file : pkg.files) { - int modtime = file.modtime; - int options = file.options; - - if (minModtime == NO_MODTIME) { - minModtime = maxModtime = modtime; - } else { - if (minModtime > modtime) minModtime = modtime; - if (maxModtime < modtime) maxModtime = modtime; - } - minOptions &= options; - maxOptions |= options; - } - if (pkg.default_modtime == NO_MODTIME) { - // Make everything else be a positive offset from here. - pkg.default_modtime = minModtime; - } - if (minModtime != NO_MODTIME && minModtime != maxModtime) { - // Put them into a band. - archiveOptions |= AO_HAVE_FILE_MODTIME; - } - // If the archive deflation is set do not bother with each file. - if (!testBit(archiveOptions,AO_DEFLATE_HINT) && minOptions != -1) { - if (testBit(minOptions, FO_DEFLATE_HINT)) { - // Every file has the deflate_hint set. - // Set it for the whole archive, and omit options. - archiveOptions |= AO_DEFLATE_HINT; - minOptions -= FO_DEFLATE_HINT; - maxOptions -= FO_DEFLATE_HINT; - } - pkg.default_options |= minOptions; - if (minOptions != maxOptions - || minOptions != pkg.default_options) { - archiveOptions |= AO_HAVE_FILE_OPTIONS; - } - } - // Decide on default version number (majority rule). - Map verCounts = new HashMap<>(); - int bestCount = 0; - Package.Version bestVersion = null; - for (Class cls : pkg.classes) { - Package.Version version = cls.getVersion(); - int[] var = verCounts.get(version); - if (var == null) { - var = new int[1]; - verCounts.put(version, var); - } - int count = (var[0] += 1); - //System.out.println("version="+version+" count="+count); - if (bestCount < count) { - bestCount = count; - bestVersion = version; - } - } - verCounts.clear(); - if (bestVersion == null) bestVersion = JAVA_MIN_CLASS_VERSION; // degenerate case - pkg.defaultClassVersion = bestVersion; - if (verbose > 0) - Utils.log.info("Consensus version number in segment is " + bestVersion); - if (verbose > 0) - Utils.log.info("Highest version number in segment is " - + pkg.getHighestClassVersion()); - - // Now add explicit pseudo-attrs. to classes with odd versions. - for (Class cls : pkg.classes) { - if (!cls.getVersion().equals(bestVersion)) { - Attribute a = makeClassFileVersionAttr(cls.getVersion()); - if (verbose > 1) { - Utils.log.fine("Version "+cls.getVersion() + " of " + cls - + " doesn't match package version " - + bestVersion); - } - // Note: Does not add in "natural" order. (Who cares?) - cls.addAttribute(a); - } - } - - // Decide if we are transmitting a huge resource file: - for (File file : pkg.files) { - long len = file.getFileLength(); - if (len != (int)len) { - archiveOptions |= AO_HAVE_FILE_SIZE_HI; - if (verbose > 0) - Utils.log.info("Note: Huge resource file "+file.getFileName()+" forces 64-bit sizing"); - break; - } - } - - // Decide if code attributes typically have sub-attributes. - // In that case, to preserve compact 1-byte code headers, - // we must declare unconditional presence of code flags. - int cost0 = 0; - int cost1 = 0; - for (Class cls : pkg.classes) { - for (Class.Method m : cls.getMethods()) { - if (m.code != null) { - if (m.code.attributeSize() == 0) { - // cost of a useless unconditional flags byte - cost1 += 1; - } else if (shortCodeHeader(m.code) != LONG_CODE_HEADER) { - // cost of inflating a short header - cost0 += 3; - } - } - } - } - if (cost0 > cost1) { - archiveOptions |= AO_HAVE_ALL_CODE_FLAGS; - } - if (verbose > 0) - Utils.log.info("archiveOptions = " - +"0b"+Integer.toBinaryString(archiveOptions)); - } - - void writeFileHeader() throws IOException { - chooseDefaultPackageVersion(); - writeArchiveMagic(); - writeArchiveHeader(); - } - - // Local routine used to format fixed-format scalars - // in the file_header: - private void putMagicInt32(int val) throws IOException { - int res = val; - for (int i = 0; i < 4; i++) { - archive_magic.putByte(0xFF & (res >>> 24)); - res <<= 8; - } - } - - void writeArchiveMagic() throws IOException { - putMagicInt32(pkg.magic); - } - - void writeArchiveHeader() throws IOException { - // for debug only: number of words optimized away - int headerSizeForDebug = AH_LENGTH_MIN; - - // AO_HAVE_SPECIAL_FORMATS is set if non-default - // coding techniques are used, or if there are - // compressor-defined attributes transmitted. - boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS); - if (!haveSpecial) { - haveSpecial |= (band_headers.length() != 0); - haveSpecial |= (attrDefsWritten.length != 0); - if (haveSpecial) - archiveOptions |= AO_HAVE_SPECIAL_FORMATS; - } - if (haveSpecial) - headerSizeForDebug += AH_SPECIAL_FORMAT_LEN; - - // AO_HAVE_FILE_HEADERS is set if there is any - // file or segment envelope information present. - boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS); - if (!haveFiles) { - haveFiles |= (archiveNextCount > 0); - haveFiles |= (pkg.default_modtime != NO_MODTIME); - if (haveFiles) - archiveOptions |= AO_HAVE_FILE_HEADERS; - } - if (haveFiles) - headerSizeForDebug += AH_FILE_HEADER_LEN; - - // AO_HAVE_CP_NUMBERS is set if there are any numbers - // in the global constant pool. (Numbers are in 15% of classes.) - boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS); - if (!haveNumbers) { - haveNumbers |= pkg.cp.haveNumbers(); - if (haveNumbers) - archiveOptions |= AO_HAVE_CP_NUMBERS; - } - if (haveNumbers) - headerSizeForDebug += AH_CP_NUMBER_LEN; - - // AO_HAVE_CP_EXTRAS is set if there are constant pool entries - // beyond the Java 6 version of the class file format. - boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS); - if (!haveCPExtra) { - haveCPExtra |= pkg.cp.haveExtraTags(); - if (haveCPExtra) - archiveOptions |= AO_HAVE_CP_EXTRAS; - } - if (haveCPExtra) - headerSizeForDebug += AH_CP_EXTRA_LEN; - - // the archiveOptions are all initialized, sanity check now!. - checkVersion(); - - archive_header_0.putInt(packageVersion.minor); - archive_header_0.putInt(packageVersion.major); - if (verbose > 0) - Utils.log.info("Package Version for this segment:" + packageVersion); - archive_header_0.putInt(archiveOptions); // controls header format - assert(archive_header_0.length() == AH_LENGTH_0); - - final int DUMMY = 0; - if (haveFiles) { - assert(archive_header_S.length() == AH_ARCHIVE_SIZE_HI); - archive_header_S.putInt(DUMMY); // (archiveSize1 >>> 32) - assert(archive_header_S.length() == AH_ARCHIVE_SIZE_LO); - archive_header_S.putInt(DUMMY); // (archiveSize1 >>> 0) - assert(archive_header_S.length() == AH_LENGTH_S); - } - - // Done with unsized part of header.... - - if (haveFiles) { - archive_header_1.putInt(archiveNextCount); // usually zero - archive_header_1.putInt(pkg.default_modtime); - archive_header_1.putInt(pkg.files.size()); - } else { - assert(pkg.files.isEmpty()); - } - - if (haveSpecial) { - archive_header_1.putInt(band_headers.length()); - archive_header_1.putInt(attrDefsWritten.length); - } else { - assert(band_headers.length() == 0); - assert(attrDefsWritten.length == 0); - } - - writeConstantPoolCounts(haveNumbers, haveCPExtra); - - archive_header_1.putInt(pkg.getAllInnerClasses().size()); - archive_header_1.putInt(pkg.defaultClassVersion.minor); - archive_header_1.putInt(pkg.defaultClassVersion.major); - archive_header_1.putInt(pkg.classes.size()); - - // Sanity: Make sure we came out to 29 (less optional fields): - assert(archive_header_0.length() + - archive_header_S.length() + - archive_header_1.length() - == headerSizeForDebug); - - // Figure out all the sizes now, first cut: - archiveSize0 = 0; - archiveSize1 = all_bands.outputSize(); - // Second cut: - archiveSize0 += archive_magic.outputSize(); - archiveSize0 += archive_header_0.outputSize(); - archiveSize0 += archive_header_S.outputSize(); - // Make the adjustments: - archiveSize1 -= archiveSize0; - - // Patch the header: - if (haveFiles) { - int archiveSizeHi = (int)(archiveSize1 >>> 32); - int archiveSizeLo = (int)(archiveSize1 >>> 0); - archive_header_S.patchValue(AH_ARCHIVE_SIZE_HI, archiveSizeHi); - archive_header_S.patchValue(AH_ARCHIVE_SIZE_LO, archiveSizeLo); - int zeroLen = UNSIGNED5.getLength(DUMMY); - archiveSize0 += UNSIGNED5.getLength(archiveSizeHi) - zeroLen; - archiveSize0 += UNSIGNED5.getLength(archiveSizeLo) - zeroLen; - } - if (verbose > 1) - Utils.log.fine("archive sizes: "+ - archiveSize0+"+"+archiveSize1); - assert(all_bands.outputSize() == archiveSize0+archiveSize1); - } - - void writeConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException { - for (byte tag : ConstantPool.TAGS_IN_ORDER) { - int count = pkg.cp.getIndexByTag(tag).size(); - switch (tag) { - case CONSTANT_Utf8: - // The null string is always first. - if (count > 0) - assert(pkg.cp.getIndexByTag(tag).get(0) - == ConstantPool.getUtf8Entry("")); - break; - - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_Long: - case CONSTANT_Double: - // Omit counts for numbers if possible. - if (!haveNumbers) { - assert(count == 0); - continue; - } - break; - - case CONSTANT_MethodHandle: - case CONSTANT_MethodType: - case CONSTANT_InvokeDynamic: - case CONSTANT_BootstrapMethod: - // Omit counts for newer entities if possible. - if (!haveCPExtra) { - assert(count == 0); - continue; - } - break; - } - archive_header_1.putInt(count); - } - } - - protected Index getCPIndex(byte tag) { - return pkg.cp.getIndexByTag(tag); - } - -// (The following observations are out of date; they apply only to -// "banding" the constant pool itself. Later revisions of this algorithm -// applied the banding technique to every part of the package file, -// applying the benefits more broadly.) - -// Note: Keeping the data separate in passes (or "bands") allows the -// compressor to issue significantly shorter indexes for repeated data. -// The difference in zipped size is 4%, which is remarkable since the -// unzipped sizes are the same (only the byte order differs). - -// After moving similar data into bands, it becomes natural to delta-encode -// each band. (This is especially useful if we sort the constant pool first.) -// Delta encoding saves an extra 5% in the output size (13% of the CP itself). -// Because a typical delta usees much less data than a byte, the savings after -// zipping is even better: A zipped delta-encoded package is 8% smaller than -// a zipped non-delta-encoded package. Thus, in the zipped file, a banded, -// delta-encoded constant pool saves over 11% (of the total file size) compared -// with a zipped unbanded file. - - void writeConstantPool() throws IOException { - IndexGroup cp = pkg.cp; - - if (verbose > 0) Utils.log.info("Writing CP"); - - for (byte tag : ConstantPool.TAGS_IN_ORDER) { - Index index = cp.getIndexByTag(tag); - - Entry[] cpMap = index.cpMap; - if (verbose > 0) - Utils.log.info("Writing "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries..."); - - if (optDumpBands) { - try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) { - printArrayTo(ps, cpMap, 0, cpMap.length); - } - } - - switch (tag) { - case CONSTANT_Utf8: - writeUtf8Bands(cpMap); - break; - case CONSTANT_Integer: - for (int i = 0; i < cpMap.length; i++) { - NumberEntry e = (NumberEntry) cpMap[i]; - int x = ((Integer)e.numberValue()).intValue(); - cp_Int.putInt(x); - } - break; - case CONSTANT_Float: - for (int i = 0; i < cpMap.length; i++) { - NumberEntry e = (NumberEntry) cpMap[i]; - float fx = ((Float)e.numberValue()).floatValue(); - int x = Float.floatToIntBits(fx); - cp_Float.putInt(x); - } - break; - case CONSTANT_Long: - for (int i = 0; i < cpMap.length; i++) { - NumberEntry e = (NumberEntry) cpMap[i]; - long x = ((Long)e.numberValue()).longValue(); - cp_Long_hi.putInt((int)(x >>> 32)); - cp_Long_lo.putInt((int)(x >>> 0)); - } - break; - case CONSTANT_Double: - for (int i = 0; i < cpMap.length; i++) { - NumberEntry e = (NumberEntry) cpMap[i]; - double dx = ((Double)e.numberValue()).doubleValue(); - long x = Double.doubleToLongBits(dx); - cp_Double_hi.putInt((int)(x >>> 32)); - cp_Double_lo.putInt((int)(x >>> 0)); - } - break; - case CONSTANT_String: - for (int i = 0; i < cpMap.length; i++) { - StringEntry e = (StringEntry) cpMap[i]; - cp_String.putRef(e.ref); - } - break; - case CONSTANT_Class: - for (int i = 0; i < cpMap.length; i++) { - ClassEntry e = (ClassEntry) cpMap[i]; - cp_Class.putRef(e.ref); - } - break; - case CONSTANT_Signature: - writeSignatureBands(cpMap); - break; - case CONSTANT_NameandType: - for (int i = 0; i < cpMap.length; i++) { - DescriptorEntry e = (DescriptorEntry) cpMap[i]; - cp_Descr_name.putRef(e.nameRef); - cp_Descr_type.putRef(e.typeRef); - } - break; - case CONSTANT_Fieldref: - writeMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc); - break; - case CONSTANT_Methodref: - writeMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc); - break; - case CONSTANT_InterfaceMethodref: - writeMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc); - break; - case CONSTANT_MethodHandle: - for (int i = 0; i < cpMap.length; i++) { - MethodHandleEntry e = (MethodHandleEntry) cpMap[i]; - cp_MethodHandle_refkind.putInt(e.refKind); - cp_MethodHandle_member.putRef(e.memRef); - } - break; - case CONSTANT_MethodType: - for (int i = 0; i < cpMap.length; i++) { - MethodTypeEntry e = (MethodTypeEntry) cpMap[i]; - cp_MethodType.putRef(e.typeRef); - } - break; - case CONSTANT_InvokeDynamic: - for (int i = 0; i < cpMap.length; i++) { - InvokeDynamicEntry e = (InvokeDynamicEntry) cpMap[i]; - cp_InvokeDynamic_spec.putRef(e.bssRef); - cp_InvokeDynamic_desc.putRef(e.descRef); - } - break; - case CONSTANT_BootstrapMethod: - for (int i = 0; i < cpMap.length; i++) { - BootstrapMethodEntry e = (BootstrapMethodEntry) cpMap[i]; - cp_BootstrapMethod_ref.putRef(e.bsmRef); - cp_BootstrapMethod_arg_count.putInt(e.argRefs.length); - for (Entry argRef : e.argRefs) { - cp_BootstrapMethod_arg.putRef(argRef); - } - } - break; - default: - throw new AssertionError("unexpected CP tag in package"); - } - } - if (optDumpBands || verbose > 1) { - for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) { - Index index = cp.getIndexByTag(tag); - if (index == null || index.isEmpty()) continue; - Entry[] cpMap = index.cpMap; - if (verbose > 1) - Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries."); - if (optDumpBands) { - try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) { - printArrayTo(ps, cpMap, 0, cpMap.length, true); - } - } - } - } - } - - void writeUtf8Bands(Entry[] cpMap) throws IOException { - if (cpMap.length == 0) - return; // nothing to write - - // The first element must always be the empty string. - assert(cpMap[0].stringValue().isEmpty()); - final int SUFFIX_SKIP_1 = 1; - final int PREFIX_SKIP_2 = 2; - - // Fetch the char arrays, first of all. - char[][] chars = new char[cpMap.length][]; - for (int i = 0; i < chars.length; i++) { - chars[i] = cpMap[i].stringValue().toCharArray(); - } - - // First band: Write lengths of shared prefixes. - int[] prefixes = new int[cpMap.length]; // includes 2 skipped zeroes - char[] prevChars = {}; - for (int i = 0; i < chars.length; i++) { - int prefix = 0; - char[] curChars = chars[i]; - int limit = Math.min(curChars.length, prevChars.length); - while (prefix < limit && curChars[prefix] == prevChars[prefix]) - prefix++; - prefixes[i] = prefix; - if (i >= PREFIX_SKIP_2) - cp_Utf8_prefix.putInt(prefix); - else - assert(prefix == 0); - prevChars = curChars; - } - - // Second band: Write lengths of unshared suffixes. - // Third band: Write the char values in the unshared suffixes. - for (int i = 0; i < chars.length; i++) { - char[] str = chars[i]; - int prefix = prefixes[i]; - int suffix = str.length - prefixes[i]; - boolean isPacked = false; - if (suffix == 0) { - // Zero suffix length is special flag to indicate - // separate treatment in cp_Utf8_big bands. - // This suffix length never occurs naturally, - // except in the one case of a zero-length string. - // (If it occurs, it is the first, due to sorting.) - // The zero length string must, paradoxically, be - // encoded as a zero-length cp_Utf8_big band. - // This wastes exactly (& tolerably) one null byte. - isPacked = (i >= SUFFIX_SKIP_1); - // Do not bother to add an empty "(Utf8_big_0)" band. - // Also, the initial empty string does not require a band. - } else if (optBigStrings && effort > 1 && suffix > 100) { - int numWide = 0; - for (int n = 0; n < suffix; n++) { - if (str[prefix+n] > 127) { - numWide++; - } - } - if (numWide > 100) { - // Try packing the chars with an alternate encoding. - isPacked = tryAlternateEncoding(i, numWide, str, prefix); - } - } - if (i < SUFFIX_SKIP_1) { - // No output. - assert(!isPacked); - assert(suffix == 0); - } else if (isPacked) { - // Mark packed string with zero-length suffix count. - // This tells the unpacker to go elsewhere for the suffix bits. - // Fourth band: Write unshared suffix with alternate coding. - cp_Utf8_suffix.putInt(0); - cp_Utf8_big_suffix.putInt(suffix); - } else { - assert(suffix != 0); // would be ambiguous - // Normal string. Save suffix in third and fourth bands. - cp_Utf8_suffix.putInt(suffix); - for (int n = 0; n < suffix; n++) { - int ch = str[prefix+n]; - cp_Utf8_chars.putInt(ch); - } - } - } - if (verbose > 0) { - int normCharCount = cp_Utf8_chars.length(); - int packCharCount = cp_Utf8_big_chars.length(); - int charCount = normCharCount + packCharCount; - Utils.log.info("Utf8string #CHARS="+charCount+" #PACKEDCHARS="+packCharCount); - } - } - - private boolean tryAlternateEncoding(int i, int numWide, - char[] str, int prefix) { - int suffix = str.length - prefix; - int[] cvals = new int[suffix]; - for (int n = 0; n < suffix; n++) { - cvals[n] = str[prefix+n]; - } - CodingChooser cc = getCodingChooser(); - Coding bigRegular = cp_Utf8_big_chars.regularCoding; - String bandName = "(Utf8_big_"+i+")"; - int[] sizes = { 0, 0 }; - final int BYTE_SIZE = CodingChooser.BYTE_SIZE; - final int ZIP_SIZE = CodingChooser.ZIP_SIZE; - if (verbose > 1 || cc.verbose > 1) { - Utils.log.fine("--- chooseCoding "+bandName); - } - CodingMethod special = cc.choose(cvals, bigRegular, sizes); - Coding charRegular = cp_Utf8_chars.regularCoding; - if (verbose > 1) - Utils.log.fine("big string["+i+"] len="+suffix+" #wide="+numWide+" size="+sizes[BYTE_SIZE]+"/z="+sizes[ZIP_SIZE]+" coding "+special); - if (special != charRegular) { - int specialZipSize = sizes[ZIP_SIZE]; - int[] normalSizes = cc.computeSize(charRegular, cvals); - int normalZipSize = normalSizes[ZIP_SIZE]; - int minWin = Math.max(5, normalZipSize/1000); - if (verbose > 1) - Utils.log.fine("big string["+i+"] normalSize="+normalSizes[BYTE_SIZE]+"/z="+normalSizes[ZIP_SIZE]+" win="+(specialZipSize>> 32)); - if (haveModtime) - file_modtime.putInt(file.modtime - pkg.default_modtime); - if (haveOptions) - file_options.putInt(file.options); - file.writeTo(file_bits.collectorStream()); - if (verbose > 1) - Utils.log.fine("Wrote "+len+" bytes of "+file.name.stringValue()); - } - if (verbose > 0) - Utils.log.info("Wrote "+numFiles+" resource files"); - } - - void collectAttributeLayouts() { - maxFlags = new int[ATTR_CONTEXT_LIMIT]; - allLayouts = new FixedList<>(ATTR_CONTEXT_LIMIT); - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - allLayouts.set(i, new HashMap<>()); - } - // Collect maxFlags and allLayouts. - for (Class cls : pkg.classes) { - visitAttributeLayoutsIn(ATTR_CONTEXT_CLASS, cls); - for (Class.Field f : cls.getFields()) { - visitAttributeLayoutsIn(ATTR_CONTEXT_FIELD, f); - } - for (Class.Method m : cls.getMethods()) { - visitAttributeLayoutsIn(ATTR_CONTEXT_METHOD, m); - if (m.code != null) { - visitAttributeLayoutsIn(ATTR_CONTEXT_CODE, m.code); - } - } - } - // If there are many species of attributes, use 63-bit flags. - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - int nl = allLayouts.get(i).size(); - boolean haveLongFlags = haveFlagsHi(i); - final int TOO_MANY_ATTRS = 32 /*int flag size*/ - - 12 /*typical flag bits in use*/ - + 4 /*typical number of OK overflows*/; - if (nl >= TOO_MANY_ATTRS) { // heuristic - int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+i); - archiveOptions |= mask; - haveLongFlags = true; - if (verbose > 0) - Utils.log.info("Note: Many "+Attribute.contextName(i)+" attributes forces 63-bit flags"); - } - if (verbose > 1) { - Utils.log.fine(Attribute.contextName(i)+".maxFlags = 0x"+Integer.toHexString(maxFlags[i])); - Utils.log.fine(Attribute.contextName(i)+".#layouts = "+nl); - } - assert(haveFlagsHi(i) == haveLongFlags); - } - initAttrIndexLimit(); - - // Standard indexes can never conflict with flag bits. Assert it. - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - assert((attrFlagMask[i] & maxFlags[i]) == 0); - } - // Collect counts for both predefs. and custom defs. - // Decide on custom, local attribute definitions. - backCountTable = new HashMap<>(); - attrCounts = new int[ATTR_CONTEXT_LIMIT][]; - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - // Now the remaining defs in allLayouts[i] need attr. indexes. - // Fill up unused flag bits with new defs. - // Unused bits are those which are not used by predefined attrs, - // and which are always clear in the classfiles. - long avHiBits = ~(maxFlags[i] | attrFlagMask[i]); - assert(attrIndexLimit[i] > 0); - assert(attrIndexLimit[i] < 64); // all bits fit into a Java long - avHiBits &= (1L< defMap = allLayouts.get(i); - @SuppressWarnings({"unchecked", "rawtypes"}) - Map.Entry[] layoutsAndCounts = - new Map.Entry[defMap.size()]; - defMap.entrySet().toArray(layoutsAndCounts); - // Sort by count, most frequent first. - // Predefs. participate in this sort, though it does not matter. - Arrays.sort(layoutsAndCounts, - new Comparator<>() { - public int compare(Map.Entry e0, - Map.Entry e1) { - // Primary sort key is count, reversed. - int r = -(e0.getValue()[0] - e1.getValue()[0]); - if (r != 0) return r; - return e0.getKey().compareTo(e1.getKey()); - } - }); - attrCounts[i] = new int[attrIndexLimit[i]+layoutsAndCounts.length]; - for (int j = 0; j < layoutsAndCounts.length; j++) { - Map.Entry e = layoutsAndCounts[j]; - Attribute.Layout def = e.getKey(); - int count = e.getValue()[0]; - int index; - Integer predefIndex = attrIndexTable.get(def); - if (predefIndex != null) { - // The index is already set. - index = predefIndex.intValue(); - } else if (avHiBits != 0) { - while ((avHiBits & 1) == 0) { - avHiBits >>>= 1; - nextLoBit += 1; - } - avHiBits -= 1; // clear low bit; we are using it now - // Update attrIndexTable: - index = setAttributeLayoutIndex(def, nextLoBit); - } else { - // Update attrIndexTable: - index = setAttributeLayoutIndex(def, ATTR_INDEX_OVERFLOW); - } - - // Now that we know the index, record the count of this def. - attrCounts[i][index] = count; - - // For all callables in the def, keep a tally of back-calls. - Attribute.Layout.Element[] cbles = def.getCallables(); - final int[] bc = new int[cbles.length]; - for (int k = 0; k < cbles.length; k++) { - assert(cbles[k].kind == Attribute.EK_CBLE); - if (!cbles[k].flagTest(Attribute.EF_BACK)) { - bc[k] = -1; // no count to accumulate here - } - } - backCountTable.put(def, bc); - - if (predefIndex == null) { - // Make sure the package CP can name the local attribute. - Entry ne = ConstantPool.getUtf8Entry(def.name()); - String layout = def.layoutForClassVersion(getHighestClassVersion()); - Entry le = ConstantPool.getUtf8Entry(layout); - requiredEntries.add(ne); - requiredEntries.add(le); - if (verbose > 0) { - if (index < attrIndexLimit[i]) - Utils.log.info("Using free flag bit 1<<"+index+" for "+count+" occurrences of "+def); - else - Utils.log.info("Using overflow index "+index+" for "+count+" occurrences of "+def); - } - } - } - } - // Later, when emitting attr_definition_bands, we will look at - // attrDefSeen and attrDefs at position 32/63 and beyond. - // The attrIndexTable will provide elements of xxx_attr_indexes bands. - - // Done with scratch variables: - maxFlags = null; - allLayouts = null; - } - - // Scratch variables for processing attributes and flags. - int[] maxFlags; - List> allLayouts; - - void visitAttributeLayoutsIn(int ctype, Attribute.Holder h) { - // Make note of which flags appear in the class file. - // Set them in maxFlags. - maxFlags[ctype] |= h.flags; - for (Attribute a : h.getAttributes()) { - Attribute.Layout def = a.layout(); - Map defMap = allLayouts.get(ctype); - int[] count = defMap.get(def); - if (count == null) { - defMap.put(def, count = new int[1]); - } - if (count[0] < Integer.MAX_VALUE) { - count[0] += 1; - } - } - } - - Attribute.Layout[] attrDefsWritten; - - void writeAttrDefs() throws IOException { - List defList = new ArrayList<>(); - for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - int limit = attrDefs.get(i).size(); - for (int j = 0; j < limit; j++) { - int header = i; // ctype - if (j < attrIndexLimit[i]) { - header |= ((j + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT); - assert(header < 0x100); // must fit into a byte - // (...else header is simply ctype, with zero high bits.) - if (!testBit(attrDefSeen[i], 1L<() { - public int compare(Object[] a0, Object[] a1) { - // Primary sort key is attr def header. - @SuppressWarnings("unchecked") - int r = ((Comparable)a0[0]).compareTo(a1[0]); - if (r != 0) return r; - Integer ind0 = attrIndexTable.get(a0[1]); - Integer ind1 = attrIndexTable.get(a1[1]); - // Secondary sort key is attribute index. - // (This must be so, in order to keep overflow attr order.) - assert(ind0 != null); - assert(ind1 != null); - return ind0.compareTo(ind1); - } - }); - attrDefsWritten = new Attribute.Layout[numAttrDefs]; - try (PrintStream dump = !optDumpBands ? null - : new PrintStream(getDumpStream(attr_definition_headers, ".def"))) - { - int[] indexForDebug = Arrays.copyOf(attrIndexLimit, ATTR_CONTEXT_LIMIT); - for (int i = 0; i < defs.length; i++) { - int header = ((Integer)defs[i][0]).intValue(); - Attribute.Layout def = (Attribute.Layout) defs[i][1]; - attrDefsWritten[i] = def; - assert((header & ADH_CONTEXT_MASK) == def.ctype()); - attr_definition_headers.putByte(header); - attr_definition_name.putRef(ConstantPool.getUtf8Entry(def.name())); - String layout = def.layoutForClassVersion(getHighestClassVersion()); - attr_definition_layout.putRef(ConstantPool.getUtf8Entry(layout)); - // Check that we are transmitting that correct attribute index: - boolean debug = false; - assert(debug = true); - if (debug) { - int hdrIndex = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB; - if (hdrIndex < 0) hdrIndex = indexForDebug[def.ctype()]++; - int realIndex = (attrIndexTable.get(def)).intValue(); - assert(hdrIndex == realIndex); - } - if (dump != null) { - int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB; - dump.println(index+" "+def); - } - } - } - } - - void writeAttrCounts() throws IOException { - // Write the four xxx_attr_calls bands. - for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { - MultiBand xxx_attr_bands = attrBands[ctype]; - IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS); - Attribute.Layout[] defs = new Attribute.Layout[attrDefs.get(ctype).size()]; - attrDefs.get(ctype).toArray(defs); - for (boolean predef = true; ; predef = false) { - for (int ai = 0; ai < defs.length; ai++) { - Attribute.Layout def = defs[ai]; - if (def == null) continue; // unused index - if (predef != isPredefinedAttr(ctype, ai)) - continue; // wrong pass - int totalCount = attrCounts[ctype][ai]; - if (totalCount == 0) - continue; // irrelevant - int[] bc = backCountTable.get(def); - for (int j = 0; j < bc.length; j++) { - if (bc[j] >= 0) { - int backCount = bc[j]; - bc[j] = -1; // close out; do not collect further counts - xxx_attr_calls.putInt(backCount); - assert(def.getCallables()[j].flagTest(Attribute.EF_BACK)); - } else { - assert(!def.getCallables()[j].flagTest(Attribute.EF_BACK)); - } - } - } - if (!predef) break; - } - } - } - - void trimClassAttributes() { - for (Class cls : pkg.classes) { - // Replace "obvious" SourceFile attrs by null. - cls.minimizeSourceFile(); - // BootstrapMethods should never have been inserted. - assert(cls.getAttribute(Package.attrBootstrapMethodsEmpty) == null); - } - } - - void collectInnerClasses() { - // Capture inner classes, removing them from individual classes. - // Irregular inner classes must stay local, though. - Map allICMap = new HashMap<>(); - // First, collect a consistent global set. - for (Class cls : pkg.classes) { - if (!cls.hasInnerClasses()) continue; - for (InnerClass ic : cls.getInnerClasses()) { - InnerClass pic = allICMap.put(ic.thisClass, ic); - if (pic != null && !pic.equals(ic) && pic.predictable) { - // Different ICs. Choose the better to make global. - allICMap.put(pic.thisClass, pic); - } - } - } - - InnerClass[] allICs = new InnerClass[allICMap.size()]; - allICMap.values().toArray(allICs); - allICMap = null; // done with it - - // Note: The InnerClasses attribute must be in a valid order, - // so that A$B always occurs earlier than A$B$C. This is an - // important side-effect of sorting lexically by class name. - Arrays.sort(allICs); // put in canonical order - pkg.setAllInnerClasses(Arrays.asList(allICs)); - - // Next, empty out of every local set the consistent entries. - // Calculate whether there is any remaining need to have a local - // set, and whether it needs to be locked. - for (Class cls : pkg.classes) { - cls.minimizeLocalICs(); - } - } - - void writeInnerClasses() throws IOException { - for (InnerClass ic : pkg.getAllInnerClasses()) { - int flags = ic.flags; - assert((flags & ACC_IC_LONG_FORM) == 0); - if (!ic.predictable) { - flags |= ACC_IC_LONG_FORM; - } - ic_this_class.putRef(ic.thisClass); - ic_flags.putInt(flags); - if (!ic.predictable) { - ic_outer_class.putRef(ic.outerClass); - ic_name.putRef(ic.name); - } - } - } - - /** If there are any extra InnerClasses entries to write which are - * not already implied by the global table, put them into a - * local attribute. This is expected to be rare. - */ - void writeLocalInnerClasses(Class cls) throws IOException { - List localICs = cls.getInnerClasses(); - class_InnerClasses_N.putInt(localICs.size()); - for(InnerClass ic : localICs) { - class_InnerClasses_RC.putRef(ic.thisClass); - // Is it redundant with the global version? - if (ic.equals(pkg.getGlobalInnerClass(ic.thisClass))) { - // A zero flag means copy a global IC here. - class_InnerClasses_F.putInt(0); - } else { - int flags = ic.flags; - if (flags == 0) - flags = ACC_IC_LONG_FORM; // force it to be non-zero - class_InnerClasses_F.putInt(flags); - class_InnerClasses_outer_RCN.putRef(ic.outerClass); - class_InnerClasses_name_RUN.putRef(ic.name); - } - } - } - - void writeClassesAndByteCodes() throws IOException { - Class[] classes = new Class[pkg.classes.size()]; - pkg.classes.toArray(classes); - // Note: This code respects the order in which caller put classes. - if (verbose > 0) - Utils.log.info(" ...scanning "+classes.length+" classes..."); - - int nwritten = 0; - for (int i = 0; i < classes.length; i++) { - // Collect the class body, sans bytecodes. - Class cls = classes[i]; - if (verbose > 1) - Utils.log.fine("Scanning "+cls); - - ClassEntry thisClass = cls.thisClass; - ClassEntry superClass = cls.superClass; - ClassEntry[] interfaces = cls.interfaces; - // Encode rare case of null superClass as thisClass: - assert(superClass != thisClass); // bad class file!? - if (superClass == null) superClass = thisClass; - class_this.putRef(thisClass); - class_super.putRef(superClass); - class_interface_count.putInt(cls.interfaces.length); - for (int j = 0; j < interfaces.length; j++) { - class_interface.putRef(interfaces[j]); - } - - writeMembers(cls); - writeAttrs(ATTR_CONTEXT_CLASS, cls, cls); - - nwritten++; - if (verbose > 0 && (nwritten % 1000) == 0) - Utils.log.info("Have scanned "+nwritten+" classes..."); - } - } - - void writeMembers(Class cls) throws IOException { - List fields = cls.getFields(); - class_field_count.putInt(fields.size()); - for (Class.Field f : fields) { - field_descr.putRef(f.getDescriptor()); - writeAttrs(ATTR_CONTEXT_FIELD, f, cls); - } - - List methods = cls.getMethods(); - class_method_count.putInt(methods.size()); - for (Class.Method m : methods) { - method_descr.putRef(m.getDescriptor()); - writeAttrs(ATTR_CONTEXT_METHOD, m, cls); - assert((m.code != null) == (m.getAttribute(attrCodeEmpty) != null)); - if (m.code != null) { - writeCodeHeader(m.code); - writeByteCodes(m.code); - } - } - } - - void writeCodeHeader(Code c) throws IOException { - boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS); - int na = c.attributeSize(); - int sc = shortCodeHeader(c); - if (!attrsOK && na > 0) - // We must write flags, and can only do so for long headers. - sc = LONG_CODE_HEADER; - if (verbose > 2) { - int siglen = c.getMethod().getArgumentSize(); - Utils.log.fine("Code sizes info "+c.max_stack+" "+c.max_locals+" "+c.getHandlerCount()+" "+siglen+" "+na+(sc > 0 ? " SHORT="+sc : "")); - } - code_headers.putByte(sc); - if (sc == LONG_CODE_HEADER) { - code_max_stack.putInt(c.getMaxStack()); - code_max_na_locals.putInt(c.getMaxNALocals()); - code_handler_count.putInt(c.getHandlerCount()); - } else { - assert(attrsOK || na == 0); - assert(c.getHandlerCount() < shortCodeHeader_h_limit); - } - writeCodeHandlers(c); - if (sc == LONG_CODE_HEADER || attrsOK) - writeAttrs(ATTR_CONTEXT_CODE, c, c.thisClass()); - } - - void writeCodeHandlers(Code c) throws IOException { - int sum, del; - for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { - code_handler_class_RCN.putRef(c.handler_class[j]); // null OK - // Encode end as offset from start, and catch as offset from end, - // because they are strongly correlated. - sum = c.encodeBCI(c.handler_start[j]); - code_handler_start_P.putInt(sum); - del = c.encodeBCI(c.handler_end[j]) - sum; - code_handler_end_PO.putInt(del); - sum += del; - del = c.encodeBCI(c.handler_catch[j]) - sum; - code_handler_catch_PO.putInt(del); - } - } - - // Generic routines for writing attributes and flags of - // classes, fields, methods, and codes. - void writeAttrs(int ctype, - final Attribute.Holder h, - Class cls) throws IOException { - MultiBand xxx_attr_bands = attrBands[ctype]; - IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI); - IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO); - boolean haveLongFlags = haveFlagsHi(ctype); - assert(attrIndexLimit[ctype] == (haveLongFlags? 63: 32)); - if (h.attributes == null) { - xxx_flags_lo.putInt(h.flags); // no extra bits to set here - if (haveLongFlags) - xxx_flags_hi.putInt(0); - return; - } - if (verbose > 3) - Utils.log.fine("Transmitting attrs for "+h+" flags="+Integer.toHexString(h.flags)); - - long flagMask = attrFlagMask[ctype]; // which flags are attr bits? - long flagsToAdd = 0; - int overflowCount = 0; - for (Attribute a : h.attributes) { - Attribute.Layout def = a.layout(); - int index = (attrIndexTable.get(def)).intValue(); - assert(attrDefs.get(ctype).get(index) == def); - if (verbose > 3) - Utils.log.fine("add attr @"+index+" "+a+" in "+h); - if (index < attrIndexLimit[ctype] && testBit(flagMask, 1L< 3) - Utils.log.fine("Adding flag bit 1<<"+index+" in "+Long.toHexString(flagMask)); - assert(!testBit(h.flags, 1L< 3) - Utils.log.fine("Adding overflow attr #"+overflowCount); - IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES); - xxx_attr_indexes.putInt(index); - // System.out.println("overflow @"+index); - } - if (def.bandCount == 0) { - if (def == attrInnerClassesEmpty) { - // Special logic to write this attr. - writeLocalInnerClasses((Class) h); - continue; - } - // Empty attr; nothing more to write here. - continue; - } - assert(a.fixups == null); - final Band[] ab = attrBandTable.get(def); - assert(ab != null); - assert(ab.length == def.bandCount); - final int[] bc = backCountTable.get(def); - assert(bc != null); - assert(bc.length == def.getCallables().length); - // Write one attribute of type def into ab. - if (verbose > 2) Utils.log.fine("writing "+a+" in "+h); - boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue); - if (isCV) setConstantValueIndex((Class.Field)h); - a.parse(cls, a.bytes(), 0, a.size(), - new Attribute.ValueStream() { - public void putInt(int bandIndex, int value) { - ((IntBand) ab[bandIndex]).putInt(value); - } - public void putRef(int bandIndex, Entry ref) { - ((CPRefBand) ab[bandIndex]).putRef(ref); - } - public int encodeBCI(int bci) { - Code code = (Code) h; - return code.encodeBCI(bci); - } - public void noteBackCall(int whichCallable) { - assert(bc[whichCallable] >= 0); - bc[whichCallable] += 1; - } - }); - if (isCV) setConstantValueIndex(null); // clean up - } - - if (overflowCount > 0) { - IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT); - xxx_attr_count.putInt(overflowCount); - } - - xxx_flags_lo.putInt(h.flags | (int)flagsToAdd); - if (haveLongFlags) - xxx_flags_hi.putInt((int)(flagsToAdd >>> 32)); - else - assert((flagsToAdd >>> 32) == 0); - assert((h.flags & flagsToAdd) == 0) - : (h+".flags=" - +Integer.toHexString(h.flags)+"^" - +Long.toHexString(flagsToAdd)); - } - - // temporary scratch variables for processing code blocks - private Code curCode; - private Class curClass; - private Entry[] curCPMap; - private void beginCode(Code c) { - assert(curCode == null); - curCode = c; - curClass = c.m.thisClass(); - curCPMap = c.getCPMap(); - } - private void endCode() { - curCode = null; - curClass = null; - curCPMap = null; - } - - // Return an _invokeinit_op variant, if the instruction matches one, - // else -1. - private int initOpVariant(Instruction i, Entry newClass) { - if (i.getBC() != _invokespecial) return -1; - MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap); - if ("".equals(ref.descRef.nameRef.stringValue()) == false) - return -1; - ClassEntry refClass = ref.classRef; - if (refClass == curClass.thisClass) - return _invokeinit_op+_invokeinit_self_option; - if (refClass == curClass.superClass) - return _invokeinit_op+_invokeinit_super_option; - if (refClass == newClass) - return _invokeinit_op+_invokeinit_new_option; - return -1; - } - - // Return a _self_linker_op variant, if the instruction matches one, - // else -1. - private int selfOpVariant(Instruction i) { - int bc = i.getBC(); - if (!(bc >= _first_linker_op && bc <= _last_linker_op)) return -1; - MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap); - // do not optimize this case, simply fall back to regular coding - if ((bc == _invokespecial || bc == _invokestatic) && - ref.tagEquals(CONSTANT_InterfaceMethodref)) - return -1; - ClassEntry refClass = ref.classRef; - int self_bc = _self_linker_op + (bc - _first_linker_op); - if (refClass == curClass.thisClass) - return self_bc; - if (refClass == curClass.superClass) - return self_bc + _self_linker_super_flag; - return -1; - } - - void writeByteCodes(Code code) throws IOException { - beginCode(code); - IndexGroup cp = pkg.cp; - - // true if the previous instruction is an aload to absorb - boolean prevAload = false; - - // class of most recent new; helps compress calls - Entry newClass = null; - - for (Instruction i = code.instructionAt(0); i != null; i = i.next()) { - // %%% Add a stress mode which issues _ref/_byte_escape. - if (verbose > 3) Utils.log.fine(i.toString()); - - if (i.isNonstandard()) { - // Crash and burn with a complaint if there are funny - // bytecodes in this class file. - String complaint = code.getMethod() - +" contains an unrecognized bytecode "+i - +"; please use the pass-file option on this class."; - Utils.log.warning(complaint); - throw new IOException(complaint); - } - - if (i.isWide()) { - if (verbose > 1) { - Utils.log.fine("_wide opcode in "+code); - Utils.log.fine(i.toString()); - } - bc_codes.putByte(_wide); - codeHist[_wide]++; - } - - int bc = i.getBC(); - - // Begin "bc_linker" compression. - if (bc == _aload_0) { - // Try to group aload_0 with a following operation. - Instruction ni = code.instructionAt(i.getNextPC()); - if (selfOpVariant(ni) >= 0) { - prevAload = true; - continue; - } - } - - // Test for invocations: - int init_bc = initOpVariant(i, newClass); - if (init_bc >= 0) { - if (prevAload) { - // get rid of it - bc_codes.putByte(_aload_0); - codeHist[_aload_0]++; - prevAload = false; //used up - } - // Write special bytecode. - bc_codes.putByte(init_bc); - codeHist[init_bc]++; - MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap); - // Write operand to a separate band. - int coding = cp.getOverloadingIndex(ref); - bc_initref.putInt(coding); - continue; - } - - int self_bc = selfOpVariant(i); - if (self_bc >= 0) { - boolean isField = Instruction.isFieldOp(bc); - boolean isSuper = (self_bc >= _self_linker_op+_self_linker_super_flag); - boolean isAload = prevAload; - prevAload = false; //used up - if (isAload) - self_bc += _self_linker_aload_flag; - // Write special bytecode. - bc_codes.putByte(self_bc); - codeHist[self_bc]++; - // Write field or method ref to a separate band. - MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap); - CPRefBand bc_which = selfOpRefBand(self_bc); - Index which_ix = cp.getMemberIndex(ref.tag, ref.classRef); - bc_which.putRef(ref, which_ix); - continue; - } - assert(!prevAload); - // End "bc_linker" compression. - - // Normal bytecode. - codeHist[bc]++; - switch (bc) { - case _tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) - case _lookupswitch: // apc: (df, nc, nc*(case, label)) - bc_codes.putByte(bc); - Instruction.Switch isw = (Instruction.Switch) i; - // Note that we do not write the alignment bytes. - int apc = isw.getAlignedPC(); - int npc = isw.getNextPC(); - // write a length specification into the bytecode stream - int caseCount = isw.getCaseCount(); - bc_case_count.putInt(caseCount); - putLabel(bc_label, code, i.getPC(), isw.getDefaultLabel()); - for (int j = 0; j < caseCount; j++) { - putLabel(bc_label, code, i.getPC(), isw.getCaseLabel(j)); - } - // Transmit case values in their own band. - if (bc == _tableswitch) { - bc_case_value.putInt(isw.getCaseValue(0)); - } else { - for (int j = 0; j < caseCount; j++) { - bc_case_value.putInt(isw.getCaseValue(j)); - } - } - // Done with the switch. - continue; - } - - int branch = i.getBranchLabel(); - if (branch >= 0) { - bc_codes.putByte(bc); - putLabel(bc_label, code, i.getPC(), branch); - continue; - } - Entry ref = i.getCPRef(curCPMap); - if (ref != null) { - if (bc == _new) newClass = ref; - if (bc == _ldc) ldcHist[ref.tag]++; - CPRefBand bc_which; - int vbc = bc; - switch (i.getCPTag()) { - case CONSTANT_LoadableValue: - switch (ref.tag) { - case CONSTANT_Integer: - bc_which = bc_intref; - switch (bc) { - case _ldc: vbc = _ildc; break; - case _ldc_w: vbc = _ildc_w; break; - default: assert(false); - } - break; - case CONSTANT_Float: - bc_which = bc_floatref; - switch (bc) { - case _ldc: vbc = _fldc; break; - case _ldc_w: vbc = _fldc_w; break; - default: assert(false); - } - break; - case CONSTANT_Long: - bc_which = bc_longref; - assert(bc == _ldc2_w); - vbc = _lldc2_w; - break; - case CONSTANT_Double: - bc_which = bc_doubleref; - assert(bc == _ldc2_w); - vbc = _dldc2_w; - break; - case CONSTANT_String: - bc_which = bc_stringref; - switch (bc) { - case _ldc: vbc = _sldc; break; - case _ldc_w: vbc = _sldc_w; break; - default: assert(false); - } - break; - case CONSTANT_Class: - bc_which = bc_classref; - switch (bc) { - case _ldc: vbc = _cldc; break; - case _ldc_w: vbc = _cldc_w; break; - default: assert(false); - } - break; - default: - // CONSTANT_MethodHandle, etc. - if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) { - throw new IOException("bad class file major version for Java 7 ldc"); - } - bc_which = bc_loadablevalueref; - switch (bc) { - case _ldc: vbc = _qldc; break; - case _ldc_w: vbc = _qldc_w; break; - default: assert(false); - } - } - break; - case CONSTANT_Class: - // Use a special shorthand for the current class: - if (ref == curClass.thisClass) ref = null; - bc_which = bc_classref; break; - case CONSTANT_Fieldref: - bc_which = bc_fieldref; break; - case CONSTANT_Methodref: - if (ref.tagEquals(CONSTANT_InterfaceMethodref)) { - if (bc == _invokespecial) - vbc = _invokespecial_int; - if (bc == _invokestatic) - vbc = _invokestatic_int; - bc_which = bc_imethodref; - } else { - bc_which = bc_methodref; - } - break; - case CONSTANT_InterfaceMethodref: - bc_which = bc_imethodref; break; - case CONSTANT_InvokeDynamic: - bc_which = bc_indyref; break; - default: - bc_which = null; - assert(false); - } - if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) { - // Crash and burn with a complaint if there are funny - // references for this bytecode instruction. - // Example: invokestatic of a CONSTANT_InterfaceMethodref. - String complaint = code.getMethod() + - " contains a bytecode " + i + - " with an unsupported constant reference; please use the pass-file option on this class."; - Utils.log.warning(complaint); - throw new IOException(complaint); - } - bc_codes.putByte(vbc); - bc_which.putRef(ref); - // handle trailing junk - if (bc == _multianewarray) { - assert(i.getConstant() == code.getByte(i.getPC()+3)); - // Just dump the byte into the bipush pile - bc_byte.putByte(0xFF & i.getConstant()); - } else if (bc == _invokeinterface) { - assert(i.getLength() == 5); - // Make sure the discarded bytes are sane: - assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8); - } else if (bc == _invokedynamic) { - if (getHighestClassVersion().lessThan(JAVA7_MAX_CLASS_VERSION)) { - throw new IOException("bad class major version for Java 7 invokedynamic"); - } - assert(i.getLength() == 5); - assert(i.getConstant() == 0); // last 2 bytes MBZ - } else { - // Make sure there is nothing else to write. - assert(i.getLength() == ((bc == _ldc)?2:3)); - } - continue; - } - int slot = i.getLocalSlot(); - if (slot >= 0) { - bc_codes.putByte(bc); - bc_local.putInt(slot); - int con = i.getConstant(); - if (bc == _iinc) { - if (!i.isWide()) { - bc_byte.putByte(0xFF & con); - } else { - bc_short.putInt(0xFFFF & con); - } - } else { - assert(con == 0); - } - continue; - } - // Generic instruction. Copy the body. - bc_codes.putByte(bc); - int pc = i.getPC()+1; - int npc = i.getNextPC(); - if (pc < npc) { - // Do a few remaining multi-byte instructions. - switch (bc) { - case _sipush: - bc_short.putInt(0xFFFF & i.getConstant()); - break; - case _bipush: - bc_byte.putByte(0xFF & i.getConstant()); - break; - case _newarray: - bc_byte.putByte(0xFF & i.getConstant()); - break; - default: - assert(false); // that's it - } - } - } - bc_codes.putByte(_end_marker); - bc_codes.elementCountForDebug++; - codeHist[_end_marker]++; - endCode(); - } - - int[] codeHist = new int[1<<8]; - int[] ldcHist = new int[20]; - void printCodeHist() { - assert(verbose > 0); - String[] hist = new String[codeHist.length]; - int totalBytes = 0; - for (int bc = 0; bc < codeHist.length; bc++) { - totalBytes += codeHist[bc]; - } - for (int bc = 0; bc < codeHist.length; bc++) { - if (codeHist[bc] == 0) { hist[bc] = ""; continue; } - String iname = Instruction.byteName(bc); - String count = "" + codeHist[bc]; - count = " ".substring(count.length()) + count; - String pct = "" + (codeHist[bc] * 10000 / totalBytes); - while (pct.length() < 4) { - pct = "0" + pct; - } - pct = pct.substring(0, pct.length()-2) + "." + pct.substring(pct.length()-2); - hist[bc] = count + " " + pct + "% " + iname; - } - Arrays.sort(hist); - System.out.println("Bytecode histogram ["+totalBytes+"]"); - for (int i = hist.length; --i >= 0; ) { - if ("".equals(hist[i])) continue; - System.out.println(hist[i]); - } - for (int tag = 0; tag < ldcHist.length; tag++) { - int count = ldcHist[tag]; - if (count == 0) continue; - System.out.println("ldc "+ConstantPool.tagName(tag)+" "+count); - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java deleted file mode 100644 index 5c64915e6f8..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.Attribute.Layout; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.SortedMap; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; -import java.util.jar.Pack200; - - -/* - * Implementation of the Pack provider. - * - * @author John Rose - * @author Kumar Srinivasan - */ - -@SuppressWarnings({"removal"}) -public class PackerImpl extends TLGlobals implements Pack200.Packer { - - /** - * Constructs a Packer object and sets the initial state of - * the packer engines. - */ - public PackerImpl() {} - - /** - * Get the set of options for the pack and unpack engines. - * @return A sorted association of option key strings to option values. - */ - public SortedMap properties() { - return props; - } - - //Driver routines - - /** - * Takes a JarFile and converts into a pack-stream. - *

- * Closes its input but not its output. (Pack200 archives are appendable.) - * @param in a JarFile - * @param out an OutputStream - * @exception IOException if an error is encountered. - */ - public synchronized void pack(JarFile in, OutputStream out) throws IOException { - assert(Utils.currentInstance.get() == null); - try { - Utils.currentInstance.set(this); - if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) { - Utils.copyJarFile(in, out); - } else { - (new DoPack()).run(in, out); - } - } finally { - Utils.currentInstance.set(null); - in.close(); - } - } - - /** - * Takes a JarInputStream and converts into a pack-stream. - *

- * Closes its input but not its output. (Pack200 archives are appendable.) - *

- * The modification time and deflation hint attributes are not available, - * for the jar-manifest file and the directory containing the file. - * - * @see #MODIFICATION_TIME - * @see #DEFLATION_HINT - * @param in a JarInputStream - * @param out an OutputStream - * @exception IOException if an error is encountered. - */ - public synchronized void pack(JarInputStream in, OutputStream out) throws IOException { - assert(Utils.currentInstance.get() == null); - try { - Utils.currentInstance.set(this); - if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) { - Utils.copyJarFile(in, out); - } else { - (new DoPack()).run(in, out); - } - } finally { - Utils.currentInstance.set(null); - in.close(); - } - } - - // All the worker bees..... - // The packer worker. - private class DoPack { - final int verbose = props.getInteger(Utils.DEBUG_VERBOSE); - - { - props.setInteger(Pack200.Packer.PROGRESS, 0); - if (verbose > 0) Utils.log.info(props.toString()); - } - - // Here's where the bits are collected before getting packed, we also - // initialize the version numbers now. - final Package pkg = new Package(Package.Version.makeVersion(props, "min.class"), - Package.Version.makeVersion(props, "max.class"), - Package.Version.makeVersion(props, "package")); - - final String unknownAttrCommand; - { - String uaMode = props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); - if (!(Pack200.Packer.STRIP.equals(uaMode) || - Pack200.Packer.PASS.equals(uaMode) || - Pack200.Packer.ERROR.equals(uaMode))) { - throw new RuntimeException("Bad option: " + Pack200.Packer.UNKNOWN_ATTRIBUTE + " = " + uaMode); - } - unknownAttrCommand = uaMode.intern(); - } - final String classFormatCommand; - { - String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS); - if (!(Pack200.Packer.PASS.equals(fmtMode) || - Pack200.Packer.ERROR.equals(fmtMode))) { - throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode); - } - classFormatCommand = fmtMode.intern(); - } - - final Map attrDefs; - final Map attrCommands; - { - Map lattrDefs = new HashMap<>(); - Map lattrCommands = new HashMap<>(); - String[] keys = { - Pack200.Packer.CLASS_ATTRIBUTE_PFX, - Pack200.Packer.FIELD_ATTRIBUTE_PFX, - Pack200.Packer.METHOD_ATTRIBUTE_PFX, - Pack200.Packer.CODE_ATTRIBUTE_PFX - }; - int[] ctypes = { - Constants.ATTR_CONTEXT_CLASS, - Constants.ATTR_CONTEXT_FIELD, - Constants.ATTR_CONTEXT_METHOD, - Constants.ATTR_CONTEXT_CODE - }; - for (int i = 0; i < ctypes.length; i++) { - String pfx = keys[i]; - Map map = props.prefixMap(pfx); - for (String key : map.keySet()) { - assert(key.startsWith(pfx)); - String name = key.substring(pfx.length()); - String layout = props.getProperty(key); - Layout lkey = Attribute.keyForLookup(ctypes[i], name); - if (Pack200.Packer.STRIP.equals(layout) || - Pack200.Packer.PASS.equals(layout) || - Pack200.Packer.ERROR.equals(layout)) { - lattrCommands.put(lkey, layout.intern()); - } else { - Attribute.define(lattrDefs, ctypes[i], name, layout); - if (verbose > 1) { - Utils.log.fine("Added layout for "+Constants.ATTR_CONTEXT_NAME[i]+" attribute "+name+" = "+layout); - } - assert(lattrDefs.containsKey(lkey)); - } - } - } - this.attrDefs = (lattrDefs.isEmpty()) ? null : lattrDefs; - this.attrCommands = (lattrCommands.isEmpty()) ? null : lattrCommands; - } - - final boolean keepFileOrder - = props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER); - final boolean keepClassOrder - = props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER); - - final boolean keepModtime - = Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME)); - final boolean latestModtime - = Pack200.Packer.LATEST.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME)); - final boolean keepDeflateHint - = Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.DEFLATE_HINT)); - { - if (!keepModtime && !latestModtime) { - int modtime = props.getTime(Pack200.Packer.MODIFICATION_TIME); - if (modtime != Constants.NO_MODTIME) { - pkg.default_modtime = modtime; - } - } - if (!keepDeflateHint) { - boolean deflate_hint = props.getBoolean(Pack200.Packer.DEFLATE_HINT); - if (deflate_hint) { - pkg.default_options |= Constants.AO_DEFLATE_HINT; - } - } - } - - long totalOutputSize = 0; - int segmentCount = 0; - long segmentTotalSize = 0; - long segmentSize = 0; // running counter - final long segmentLimit; - { - long limit; - if (props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").isEmpty()) - limit = -1; - else - limit = props.getLong(Pack200.Packer.SEGMENT_LIMIT); - limit = Math.min(Integer.MAX_VALUE, limit); - limit = Math.max(-1, limit); - if (limit == -1) - limit = Long.MAX_VALUE; - segmentLimit = limit; - } - - final List passFiles; // parsed pack.pass.file options - { - // Which class files will be passed through? - passFiles = props.getProperties(Pack200.Packer.PASS_FILE_PFX); - for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) { - String file = i.next(); - if (file == null) { i.remove(); continue; } - file = Utils.getJarEntryName(file); // normalize '\\' to '/' - if (file.endsWith("/")) - file = file.substring(0, file.length()-1); - i.set(file); - } - if (verbose > 0) Utils.log.info("passFiles = " + passFiles); - } - - { - // Hook for testing: Forces use of special archive modes. - int opt = props.getInteger(Utils.COM_PREFIX+"archive.options"); - if (opt != 0) - pkg.default_options |= opt; - } - - // (Done collecting options from props.) - - // Get a new package, based on the old one. - private void makeNextPackage() { - pkg.reset(); - } - - final class InFile { - final String name; - final JarFile jf; - final JarEntry je; - final File f; - int modtime = Constants.NO_MODTIME; - int options; - InFile(String name) { - this.name = Utils.getJarEntryName(name); - this.f = new File(name); - this.jf = null; - this.je = null; - int timeSecs = getModtime(f.lastModified()); - if (keepModtime && timeSecs != Constants.NO_MODTIME) { - this.modtime = timeSecs; - } else if (latestModtime && timeSecs > pkg.default_modtime) { - pkg.default_modtime = timeSecs; - } - } - InFile(JarFile jf, JarEntry je) { - this.name = Utils.getJarEntryName(je.getName()); - this.f = null; - this.jf = jf; - this.je = je; - int timeSecs = (int) je.getTimeLocal() - .atOffset(ZoneOffset.UTC) - .toEpochSecond(); - if (keepModtime && timeSecs != Constants.NO_MODTIME) { - this.modtime = timeSecs; - } else if (latestModtime && timeSecs > pkg.default_modtime) { - pkg.default_modtime = timeSecs; - } - if (keepDeflateHint && je.getMethod() == JarEntry.DEFLATED) { - options |= Constants.FO_DEFLATE_HINT; - } - } - InFile(JarEntry je) { - this(null, je); - } - boolean isClassFile() { - if (!name.endsWith(".class") || name.endsWith("module-info.class")) { - return false; - } - for (String prefix = name;;) { - if (passFiles.contains(prefix)) { - return false; - } - int chop = prefix.lastIndexOf('/'); - if (chop < 0) { - break; - } - prefix = prefix.substring(0, chop); - } - return true; - } - boolean isMetaInfFile() { - return name.startsWith("/" + Utils.METAINF) - || name.startsWith(Utils.METAINF); - } - boolean mustProcess() { - return !isMetaInfFile() && isClassFile(); - } - long getInputLength() { - long len = (je != null)? je.getSize(): f.length(); - assert(len >= 0) : this+".len="+len; - // Bump size by pathname length and modtime/def-hint bytes. - return Math.max(0, len) + name.length() + 5; - } - int getModtime(long timeMillis) { - // Convert milliseconds to seconds. - long seconds = (timeMillis+500) / 1000; - if ((int)seconds == seconds) { - return (int)seconds; - } else { - Utils.log.warning("overflow in modtime for "+f); - return Constants.NO_MODTIME; - } - } - void copyTo(Package.File file) { - if (modtime != Constants.NO_MODTIME) - file.modtime = modtime; - file.options |= options; - } - InputStream getInputStream() throws IOException { - if (jf != null) - return jf.getInputStream(je); - else - return new FileInputStream(f); - } - - public String toString() { - return name; - } - } - - private int nread = 0; // used only if (verbose > 0) - private void noteRead(InFile f) { - nread++; - if (verbose > 2) - Utils.log.fine("...read "+f.name); - if (verbose > 0 && (nread % 1000) == 0) - Utils.log.info("Have read "+nread+" files..."); - } - - void run(JarInputStream in, OutputStream out) throws IOException { - // First thing we do is get the manifest, as JIS does - // not provide the Manifest as an entry. - if (in.getManifest() != null) { - ByteArrayOutputStream tmp = new ByteArrayOutputStream(); - in.getManifest().write(tmp); - InputStream tmpIn = new ByteArrayInputStream(tmp.toByteArray()); - pkg.addFile(readFile(JarFile.MANIFEST_NAME, tmpIn)); - } - for (JarEntry je; (je = in.getNextJarEntry()) != null; ) { - InFile inFile = new InFile(je); - - String name = inFile.name; - Package.File bits = readFile(name, in); - Package.File file = null; - // (5078608) : discount the resource files in META-INF - // from segment computation. - long inflen = (inFile.isMetaInfFile()) - ? 0L - : inFile.getInputLength(); - - if ((segmentSize += inflen) > segmentLimit) { - segmentSize -= inflen; - int nextCount = -1; // don't know; it's a stream - flushPartial(out, nextCount); - } - if (verbose > 1) { - Utils.log.fine("Reading " + name); - } - - assert(je.isDirectory() == name.endsWith("/")); - - if (inFile.mustProcess()) { - file = readClass(name, bits.getInputStream()); - } - if (file == null) { - file = bits; - pkg.addFile(file); - } - inFile.copyTo(file); - noteRead(inFile); - } - flushAll(out); - } - - void run(JarFile in, OutputStream out) throws IOException { - List inFiles = scanJar(in); - - if (verbose > 0) - Utils.log.info("Reading " + inFiles.size() + " files..."); - - int numDone = 0; - for (InFile inFile : inFiles) { - String name = inFile.name; - // (5078608) : discount the resource files completely from segmenting - long inflen = (inFile.isMetaInfFile()) - ? 0L - : inFile.getInputLength() ; - if ((segmentSize += inflen) > segmentLimit) { - segmentSize -= inflen; - // Estimate number of remaining segments: - float filesDone = numDone+1; - float segsDone = segmentCount+1; - float filesToDo = inFiles.size() - filesDone; - float segsToDo = filesToDo * (segsDone/filesDone); - if (verbose > 1) - Utils.log.fine("Estimated segments to do: "+segsToDo); - flushPartial(out, (int) Math.ceil(segsToDo)); - } - InputStream strm = inFile.getInputStream(); - if (verbose > 1) - Utils.log.fine("Reading " + name); - Package.File file = null; - if (inFile.mustProcess()) { - file = readClass(name, strm); - if (file == null) { - strm.close(); - strm = inFile.getInputStream(); - } - } - if (file == null) { - file = readFile(name, strm); - pkg.addFile(file); - } - inFile.copyTo(file); - strm.close(); // tidy up - noteRead(inFile); - numDone += 1; - } - flushAll(out); - } - - Package.File readClass(String fname, InputStream in) throws IOException { - Package.Class cls = pkg.new Class(fname); - in = new BufferedInputStream(in); - ClassReader reader = new ClassReader(cls, in); - reader.setAttrDefs(attrDefs); - reader.setAttrCommands(attrCommands); - reader.unknownAttrCommand = unknownAttrCommand; - try { - reader.read(); - } catch (IOException ioe) { - String message = "Passing class file uncompressed due to"; - if (ioe instanceof Attribute.FormatException) { - Attribute.FormatException ee = (Attribute.FormatException) ioe; - // He passed up the category to us in layout. - if (ee.layout.equals(Pack200.Packer.PASS)) { - Utils.log.info(ee.toString()); - Utils.log.warning(message + " unrecognized attribute: " + - fname); - return null; - } - } else if (ioe instanceof ClassReader.ClassFormatException) { - ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe; - if (classFormatCommand.equals(Pack200.Packer.PASS)) { - Utils.log.info(ce.toString()); - Utils.log.warning(message + " unknown class format: " + - fname); - return null; - } - } - // Otherwise, it must be an error. - throw ioe; - } - pkg.addClass(cls); - return cls.file; - } - - // Read raw data. - Package.File readFile(String fname, InputStream in) throws IOException { - - Package.File file = pkg.new File(fname); - file.readFrom(in); - if (file.isDirectory() && file.getFileLength() != 0) - throw new IllegalArgumentException("Non-empty directory: "+file.getFileName()); - return file; - } - - void flushPartial(OutputStream out, int nextCount) throws IOException { - if (pkg.files.isEmpty() && pkg.classes.isEmpty()) { - return; // do not flush an empty segment - } - flushPackage(out, Math.max(1, nextCount)); - props.setInteger(Pack200.Packer.PROGRESS, 25); - // In case there will be another segment: - makeNextPackage(); - segmentCount += 1; - segmentTotalSize += segmentSize; - segmentSize = 0; - } - - void flushAll(OutputStream out) throws IOException { - props.setInteger(Pack200.Packer.PROGRESS, 50); - flushPackage(out, 0); - out.flush(); - props.setInteger(Pack200.Packer.PROGRESS, 100); - segmentCount += 1; - segmentTotalSize += segmentSize; - segmentSize = 0; - if (verbose > 0 && segmentCount > 1) { - Utils.log.info("Transmitted " - +segmentTotalSize+" input bytes in " - +segmentCount+" segments totaling " - +totalOutputSize+" bytes"); - } - } - - - /** Write all information in the current package segment - * to the output stream. - */ - void flushPackage(OutputStream out, int nextCount) throws IOException { - int nfiles = pkg.files.size(); - if (!keepFileOrder) { - // Keeping the order of classes costs about 1% - // Keeping the order of all files costs something more. - if (verbose > 1) Utils.log.fine("Reordering files."); - boolean stripDirectories = true; - pkg.reorderFiles(keepClassOrder, stripDirectories); - } else { - // Package builder must have created a stub for each class. - assert(pkg.files.containsAll(pkg.getClassStubs())); - // Order of stubs in file list must agree with classes. - List res = pkg.files; - assert((res = new ArrayList<>(pkg.files)) - .retainAll(pkg.getClassStubs()) || true); - assert(res.equals(pkg.getClassStubs())); - } - pkg.trimStubs(); - - // Do some stripping, maybe. - if (props.getBoolean(Utils.COM_PREFIX+"strip.debug")) pkg.stripAttributeKind("Debug"); - if (props.getBoolean(Utils.COM_PREFIX+"strip.compile")) pkg.stripAttributeKind("Compile"); - if (props.getBoolean(Utils.COM_PREFIX+"strip.constants")) pkg.stripAttributeKind("Constant"); - if (props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions"); - if (props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses"); - - PackageWriter pw = new PackageWriter(pkg, out); - pw.archiveNextCount = nextCount; - pw.write(); - out.flush(); - if (verbose > 0) { - long outSize = pw.archiveSize0+pw.archiveSize1; - totalOutputSize += outSize; - long inSize = segmentSize; - Utils.log.info("Transmitted " - +nfiles+" files of " - +inSize+" input bytes in a segment of " - +outSize+" bytes"); - } - } - - List scanJar(JarFile jf) throws IOException { - // Collect jar entries, preserving order. - List inFiles = new ArrayList<>(); - try { - for (JarEntry je : Collections.list(jf.entries())) { - InFile inFile = new InFile(jf, je); - assert(je.isDirectory() == inFile.name.endsWith("/")); - inFiles.add(inFile); - } - } catch (IllegalStateException ise) { - throw new IOException(ise.getLocalizedMessage(), ise); - } - return inFiles; - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java deleted file mode 100644 index d20f5e40806..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PopulationCoding.java +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import static com.sun.java.util.jar.pack.Constants.*; - -/** - * Population-based coding. - * See the section "Encodings of Uncorrelated Values" in the Pack200 spec. - * @author John Rose - */ -// This tactic alone reduces the final zipped rt.jar by about a percent. -class PopulationCoding implements CodingMethod { - Histogram vHist; // histogram of all values - int[] fValues; // list of favored values - int fVlen; // inclusive max index - long[] symtab; // int map of favored value -> token [1..#fValues] - - CodingMethod favoredCoding; - CodingMethod tokenCoding; - CodingMethod unfavoredCoding; - - int L = -1; //preferred L value for tokenCoding - - public void setFavoredValues(int[] fValues, int fVlen) { - // Note: {f} is allFavoredValues[1..fvlen], not [0..fvlen-1]. - // This is because zero is an exceptional favored value index. - assert(fValues[0] == 0); // must be empty - assert(this.fValues == null); // do not do this twice - this.fValues = fValues; - this.fVlen = fVlen; - if (L >= 0) { - setL(L); // reassert - } - } - public void setFavoredValues(int[] fValues) { - int lfVlen = fValues.length-1; - setFavoredValues(fValues, lfVlen); - } - public void setHistogram(Histogram vHist) { - this.vHist = vHist; - } - public void setL(int L) { - this.L = L; - if (L >= 0 && fValues != null && tokenCoding == null) { - tokenCoding = fitTokenCoding(fVlen, L); - assert(tokenCoding != null); - } - } - - public static Coding fitTokenCoding(int fVlen, int L) { - // Find the smallest B s.t. (B,H,0) covers fVlen. - if (fVlen < 256) - // H/L do not matter when B==1 - return BandStructure.BYTE1; - Coding longest = BandStructure.UNSIGNED5.setL(L); - if (!longest.canRepresentUnsigned(fVlen)) - return null; // failure; L is too sharp and fVlen too large - Coding tc = longest; - for (Coding shorter = longest; ; ) { - shorter = shorter.setB(shorter.B()-1); - if (shorter.umax() < fVlen) - break; - tc = shorter; // shorten it by reducing B - } - return tc; - } - - public void setFavoredCoding(CodingMethod favoredCoding) { - this.favoredCoding = favoredCoding; - } - public void setTokenCoding(CodingMethod tokenCoding) { - this.tokenCoding = tokenCoding; - this.L = -1; - if (tokenCoding instanceof Coding && fValues != null) { - Coding tc = (Coding) tokenCoding; - if (tc == fitTokenCoding(fVlen, tc.L())) - this.L = tc.L(); - // Otherwise, it's a non-default coding. - } - } - public void setUnfavoredCoding(CodingMethod unfavoredCoding) { - this.unfavoredCoding = unfavoredCoding; - } - - public int favoredValueMaxLength() { - if (L == 0) - return Integer.MAX_VALUE; - else - return BandStructure.UNSIGNED5.setL(L).umax(); - } - - public void resortFavoredValues() { - Coding tc = (Coding) tokenCoding; - // Make a local copy before reordering. - fValues = BandStructure.realloc(fValues, 1+fVlen); - // Resort favoredValues within each byte-size cadre. - int fillp = 1; // skip initial zero - for (int n = 1; n <= tc.B(); n++) { - int nmax = tc.byteMax(n); - if (nmax > fVlen) - nmax = fVlen; - if (nmax < tc.byteMin(n)) - break; - int low = fillp; - int high = nmax+1; - if (high == low) continue; - assert(high > low) - : high+"!>"+low; - assert(tc.getLength(low) == n) - : n+" != len("+(low)+") == "+ - tc.getLength(low); - assert(tc.getLength(high-1) == n) - : n+" != len("+(high-1)+") == "+ - tc.getLength(high-1); - int midTarget = low + (high-low)/2; - int mid = low; - // Divide the values into cadres, and sort within each. - int prevCount = -1; - int prevLimit = low; - for (int i = low; i < high; i++) { - int val = fValues[i]; - int count = vHist.getFrequency(val); - if (prevCount != count) { - if (n == 1) { - // For the single-byte encoding, keep strict order - // among frequency groups. - Arrays.sort(fValues, prevLimit, i); - } else if (Math.abs(mid - midTarget) > - Math.abs(i - midTarget)) { - // Find a single inflection point - // close to the middle of the byte-size cadre. - mid = i; - } - prevCount = count; - prevLimit = i; - } - } - if (n == 1) { - Arrays.sort(fValues, prevLimit, high); - } else { - // Sort up to the midpoint, if any. - Arrays.sort(fValues, low, mid); - Arrays.sort(fValues, mid, high); - } - assert(tc.getLength(low) == tc.getLength(mid)); - assert(tc.getLength(low) == tc.getLength(high-1)); - fillp = nmax+1; - } - assert(fillp == fValues.length); - - // Reset symtab. - symtab = null; - } - - public int getToken(int value) { - if (symtab == null) - symtab = makeSymtab(); - int pos = Arrays.binarySearch(symtab, (long)value << 32); - if (pos < 0) pos = -pos-1; - if (pos < symtab.length && value == (int)(symtab[pos] >>> 32)) - return (int)symtab[pos]; - else - return 0; - } - - public int[][] encodeValues(int[] values, int start, int end) { - // Compute token sequence. - int[] tokens = new int[end-start]; - int nuv = 0; - for (int i = 0; i < tokens.length; i++) { - int val = values[start+i]; - int tok = getToken(val); - if (tok != 0) - tokens[i] = tok; - else - nuv += 1; - } - // Compute unfavored value sequence. - int[] unfavoredValues = new int[nuv]; - nuv = 0; // reset - for (int i = 0; i < tokens.length; i++) { - if (tokens[i] != 0) continue; // already covered - int val = values[start+i]; - unfavoredValues[nuv++] = val; - } - assert(nuv == unfavoredValues.length); - return new int[][]{ tokens, unfavoredValues }; - } - - private long[] makeSymtab() { - long[] lsymtab = new long[fVlen]; - for (int token = 1; token <= fVlen; token++) { - lsymtab[token-1] = ((long)fValues[token] << 32) | token; - } - // Index by value: - Arrays.sort(lsymtab); - return lsymtab; - } - - private Coding getTailCoding(CodingMethod c) { - while (c instanceof AdaptiveCoding) - c = ((AdaptiveCoding)c).tailCoding; - return (Coding) c; - } - - // CodingMethod methods. - public void writeArrayTo(OutputStream out, int[] a, int start, int end) throws IOException { - int[][] vals = encodeValues(a, start, end); - writeSequencesTo(out, vals[0], vals[1]); - } - void writeSequencesTo(OutputStream out, int[] tokens, int[] uValues) throws IOException { - favoredCoding.writeArrayTo(out, fValues, 1, 1+fVlen); - getTailCoding(favoredCoding).writeTo(out, computeSentinelValue()); - tokenCoding.writeArrayTo(out, tokens, 0, tokens.length); - if (uValues.length > 0) - unfavoredCoding.writeArrayTo(out, uValues, 0, uValues.length); - } - - int computeSentinelValue() { - Coding fc = getTailCoding(favoredCoding); - if (fc.isDelta()) { - // repeat the last favored value, using delta=0 - return 0; - } else { - // else repeat the shorter of the min or last value - int min = fValues[1]; - int last = min; - // (remember that fVlen is an inclusive limit in fValues) - for (int i = 2; i <= fVlen; i++) { - last = fValues[i]; - min = moreCentral(min, last); - } - int endVal; - if (fc.getLength(min) <= fc.getLength(last)) - return min; - else - return last; - } - } - - public void readArrayFrom(InputStream in, int[] a, int start, int end) throws IOException { - // Parameters are fCode, L, uCode. - setFavoredValues(readFavoredValuesFrom(in, end-start)); - // Read the tokens. Read them into the final array, for the moment. - tokenCoding.readArrayFrom(in, a, start, end); - // Decode the favored tokens. - int headp = 0, tailp = -1; - int uVlen = 0; - for (int i = start; i < end; i++) { - int tok = a[i]; - if (tok == 0) { - // Make a linked list, and decode in a second pass. - if (tailp < 0) { - headp = i; - } else { - a[tailp] = i; - } - tailp = i; - uVlen += 1; - } else { - a[i] = fValues[tok]; - } - } - // Walk the linked list of "zero" locations, decoding unfavored vals. - int[] uValues = new int[uVlen]; - if (uVlen > 0) - unfavoredCoding.readArrayFrom(in, uValues, 0, uVlen); - for (int i = 0; i < uVlen; i++) { - int nextp = a[headp]; - a[headp] = uValues[i]; - headp = nextp; - } - } - - int[] readFavoredValuesFrom(InputStream in, int maxForDebug) throws IOException { - int[] lfValues = new int[1000]; // realloc as needed - // The set uniqueValuesForDebug records all favored values. - // As each new value is added, we assert that the value - // was not already in the set. - Set uniqueValuesForDebug = null; - assert((uniqueValuesForDebug = new HashSet<>()) != null); - int fillp = 1; - maxForDebug += fillp; - int min = Integer.MIN_VALUE; // farthest from the center - //int min2 = Integer.MIN_VALUE; // emulate buggy 150.7 spec. - int last = 0; - CodingMethod fcm = favoredCoding; - while (fcm instanceof AdaptiveCoding) { - AdaptiveCoding ac = (AdaptiveCoding) fcm; - int len = ac.headLength; - while (fillp + len > lfValues.length) { - lfValues = BandStructure.realloc(lfValues); - } - int newFillp = fillp + len; - ac.headCoding.readArrayFrom(in, lfValues, fillp, newFillp); - while (fillp < newFillp) { - int val = lfValues[fillp++]; - assert(uniqueValuesForDebug.add(val)); - assert(fillp <= maxForDebug); - last = val; - min = moreCentral(min, val); - //min2 = moreCentral2(min2, val, min); - } - fcm = ac.tailCoding; - } - Coding fc = (Coding) fcm; - if (fc.isDelta()) { - for (long state = 0;;) { - // Read a new value: - state += fc.readFrom(in); - int val; - if (fc.isSubrange()) - val = fc.reduceToUnsignedRange(state); - else - val = (int)state; - state = val; - if (fillp > 1 && (val == last || val == min)) //|| val == min2 - break; - if (fillp == lfValues.length) - lfValues = BandStructure.realloc(lfValues); - lfValues[fillp++] = val; - assert(uniqueValuesForDebug.add(val)); - assert(fillp <= maxForDebug); - last = val; - min = moreCentral(min, val); - //min2 = moreCentral(min2, val); - } - } else { - for (;;) { - int val = fc.readFrom(in); - if (fillp > 1 && (val == last || val == min)) //|| val == min2 - break; - if (fillp == lfValues.length) - lfValues = BandStructure.realloc(lfValues); - lfValues[fillp++] = val; - assert(uniqueValuesForDebug.add(val)); - assert(fillp <= maxForDebug); - last = val; - min = moreCentral(min, val); - //min2 = moreCentral2(min2, val, min); - } - } - return BandStructure.realloc(lfValues, fillp); - } - - private static int moreCentral(int x, int y) { - int kx = (x >> 31) ^ (x << 1); - int ky = (y >> 31) ^ (y << 1); - // bias kx/ky to get an unsigned comparison: - kx -= Integer.MIN_VALUE; - ky -= Integer.MIN_VALUE; - int xy = (kx < ky? x: y); - // assert that this ALU-ish version is the same: - assert(xy == moreCentralSlow(x, y)); - return xy; - } -// private static int moreCentral2(int x, int y, int min) { -// // Strict implementation of buggy 150.7 specification. -// // The bug is that the spec. says absolute-value ties are broken -// // in favor of positive numbers, but the suggested implementation -// // (also mentioned in the spec.) breaks ties in favor of negatives. -// if (x + y == 0) return (x > y? x : y); -// return min; -// } - private static int moreCentralSlow(int x, int y) { - int ax = x; - if (ax < 0) ax = -ax; - if (ax < 0) return y; //x is MIN_VALUE - int ay = y; - if (ay < 0) ay = -ay; - if (ay < 0) return x; //y is MIN_VALUE - if (ax < ay) return x; - if (ax > ay) return y; - // At this point the absolute values agree, and the negative wins. - return x < y ? x : y; - } - - static final int[] LValuesCoded - = { -1, 4, 8, 16, 32, 64, 128, 192, 224, 240, 248, 252 }; - - public byte[] getMetaCoding(Coding dflt) { - int K = fVlen; - int LCoded = 0; - if (tokenCoding instanceof Coding) { - Coding tc = (Coding) tokenCoding; - if (tc.B() == 1) { - LCoded = 1; - } else if (L >= 0) { - assert(L == tc.L()); - for (int i = 1; i < LValuesCoded.length; i++) { - if (LValuesCoded[i] == L) { LCoded = i; break; } - } - } - } - CodingMethod tokenDflt = null; - if (LCoded != 0 && tokenCoding == fitTokenCoding(fVlen, L)) { - // A simple L value is enough to recover the tokenCoding. - tokenDflt = tokenCoding; - } - int FDef = (favoredCoding == dflt)?1:0; - int UDef = (unfavoredCoding == dflt || unfavoredCoding == null)?1:0; - int TDef = (tokenCoding == tokenDflt)?1:0; - int TDefL = (TDef == 1) ? LCoded : 0; - assert(TDef == ((TDefL>0)?1:0)); - ByteArrayOutputStream bytes = new ByteArrayOutputStream(10); - bytes.write(_meta_pop + FDef + 2*UDef + 4*TDefL); - try { - if (FDef == 0) bytes.write(favoredCoding.getMetaCoding(dflt)); - if (TDef == 0) bytes.write(tokenCoding.getMetaCoding(dflt)); - if (UDef == 0) bytes.write(unfavoredCoding.getMetaCoding(dflt)); - } catch (IOException ee) { - throw new RuntimeException(ee); - } - return bytes.toByteArray(); - } - public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod res[]) { - int op = bytes[pos++] & 0xFF; - if (op < _meta_pop || op >= _meta_limit) return pos-1; // backup - op -= _meta_pop; - int FDef = op % 2; - int UDef = (op / 2) % 2; - int TDefL = (op / 4); - int TDef = (TDefL > 0)?1:0; - int L = LValuesCoded[TDefL]; - CodingMethod[] FCode = {dflt}, TCode = {null}, UCode = {dflt}; - if (FDef == 0) - pos = BandStructure.parseMetaCoding(bytes, pos, dflt, FCode); - if (TDef == 0) - pos = BandStructure.parseMetaCoding(bytes, pos, dflt, TCode); - if (UDef == 0) - pos = BandStructure.parseMetaCoding(bytes, pos, dflt, UCode); - PopulationCoding pop = new PopulationCoding(); - pop.L = L; // might be -1 - pop.favoredCoding = FCode[0]; - pop.tokenCoding = TCode[0]; // might be null! - pop.unfavoredCoding = UCode[0]; - res[0] = pop; - return pos; - } - - private String keyString(CodingMethod m) { - if (m instanceof Coding) - return ((Coding)m).keyString(); - if (m == null) - return "none"; - return m.toString(); - } - public String toString() { - PropMap p200 = Utils.currentPropMap(); - boolean verbose - = (p200 != null && - p200.getBoolean(Utils.COM_PREFIX+"verbose.pop")); - StringBuilder res = new StringBuilder(100); - res.append("pop(").append("fVlen=").append(fVlen); - if (verbose && fValues != null) { - res.append(" fV=["); - for (int i = 1; i <= fVlen; i++) { - res.append(i==1?"":",").append(fValues[i]); - } - res.append(";").append(computeSentinelValue()); - res.append("]"); - } - res.append(" fc=").append(keyString(favoredCoding)); - res.append(" tc=").append(keyString(tokenCoding)); - res.append(" uc=").append(keyString(unfavoredCoding)); - res.append(")"); - return res.toString(); - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java deleted file mode 100644 index c6c23117276..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/PropMap.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.jar.Pack200; - -/** - * Control block for publishing Pack200 options to the other classes. - */ - -@SuppressWarnings({"removal"}) -final class PropMap implements SortedMap { - private final TreeMap theMap = new TreeMap<>();; - - // Override: - public String put(String key, String value) { - String oldValue = theMap.put(key, value); - return oldValue; - } - - // All this other stuff is private to the current package. - // Outide clients of Pack200 do not need to use it; they can - // get by with generic SortedMap functionality. - private static Map defaultProps; - static { - Properties props = new Properties(); - - // Allow implementation selected via -Dpack.disable.native=true - String propValue = getPropertyValue(Utils.DEBUG_DISABLE_NATIVE, "false"); - props.put(Utils.DEBUG_DISABLE_NATIVE, - String.valueOf(Boolean.parseBoolean(propValue))); - - // Set the DEBUG_VERBOSE from system - int verbose = 0; - try { - verbose = Integer.decode(getPropertyValue(Utils.DEBUG_VERBOSE, "0")); - } catch (NumberFormatException e) { - } - props.put(Utils.DEBUG_VERBOSE, String.valueOf(verbose)); - - // The segment size is unlimited - props.put(Pack200.Packer.SEGMENT_LIMIT, "-1"); - - // Preserve file ordering by default. - props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE); - - // Preserve all modification times by default. - props.put(Pack200.Packer.MODIFICATION_TIME, Pack200.Packer.KEEP); - - // Preserve deflation hints by default. - props.put(Pack200.Packer.DEFLATE_HINT, Pack200.Packer.KEEP); - - // Pass through files with unrecognized attributes by default. - props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); - - // Pass through files with unrecognized format by default, also - // allow system property to be set - props.put(Utils.CLASS_FORMAT_ERROR, - getPropertyValue(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS)); - - // Default effort is 5, midway between 1 and 9. - props.put(Pack200.Packer.EFFORT, "5"); - - // Define certain attribute layouts by default. - // Do this after the previous props are put in place, - // to allow override if necessary. - String propFile = "intrinsic.properties"; - - PrivilegedAction pa = - () -> PackerImpl.class.getResourceAsStream(propFile); - try (InputStream propStr = AccessController.doPrivileged(pa)) { - if (propStr == null) { - throw new RuntimeException(propFile + " cannot be loaded"); - } - props.load(propStr); - } catch (IOException ee) { - throw new RuntimeException(ee); - } - - for (Map.Entry e : props.entrySet()) { - String key = (String) e.getKey(); - String val = (String) e.getValue(); - if (key.startsWith("attribute.")) { - e.setValue(Attribute.normalizeLayoutString(val)); - } - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - HashMap temp = new HashMap(props); // shrink to fit - defaultProps = temp; - } - - private static String getPropertyValue(String key, String defaultValue) { - PrivilegedAction pa = () -> System.getProperty(key); - String s = AccessController.doPrivileged(pa); - return s != null ? s : defaultValue; - } - - PropMap() { - theMap.putAll(defaultProps); - } - - // Return a view of this map which includes only properties - // that begin with the given prefix. This is easy because - // the map is sorted, and has a subMap accessor. - SortedMap prefixMap(String prefix) { - int len = prefix.length(); - if (len == 0) - return this; - char nextch = (char)(prefix.charAt(len-1) + 1); - String limit = prefix.substring(0, len-1)+nextch; - //System.out.println(prefix+" => "+subMap(prefix, limit)); - return subMap(prefix, limit); - } - - String getProperty(String s) { - return get(s); - } - String getProperty(String s, String defaultVal) { - String val = getProperty(s); - if (val == null) - return defaultVal; - return val; - } - String setProperty(String s, String val) { - return put(s, val); - } - - // Get sequence of props for "prefix", and "prefix.*". - List getProperties(String prefix) { - Collection values = prefixMap(prefix).values(); - List res = new ArrayList<>(values.size()); - res.addAll(values); - while (res.remove(null)); - return res; - } - - private boolean toBoolean(String val) { - return Boolean.valueOf(val).booleanValue(); - } - boolean getBoolean(String s) { - return toBoolean(getProperty(s)); - } - boolean setBoolean(String s, boolean val) { - return toBoolean(setProperty(s, String.valueOf(val))); - } - int toInteger(String val) { - return toInteger(val, 0); - } - int toInteger(String val, int def) { - if (val == null) return def; - if (Pack200.Packer.TRUE.equals(val)) return 1; - if (Pack200.Packer.FALSE.equals(val)) return 0; - return Integer.parseInt(val); - } - int getInteger(String s, int def) { - return toInteger(getProperty(s), def); - } - int getInteger(String s) { - return toInteger(getProperty(s)); - } - int setInteger(String s, int val) { - return toInteger(setProperty(s, String.valueOf(val))); - } - - long toLong(String val) { - try { - return val == null ? 0 : Long.parseLong(val); - } catch (java.lang.NumberFormatException nfe) { - throw new IllegalArgumentException("Invalid value"); - } - } - long getLong(String s) { - return toLong(getProperty(s)); - } - long setLong(String s, long val) { - return toLong(setProperty(s, String.valueOf(val))); - } - - int getTime(String s) { - String sval = getProperty(s, "0"); - if (Utils.NOW.equals(sval)) { - return (int)((System.currentTimeMillis()+500)/1000); - } - long lval = toLong(sval); - final long recentSecondCount = 1000000000; - - if (lval < recentSecondCount*10 && !"0".equals(sval)) - Utils.log.warning("Supplied modtime appears to be seconds rather than milliseconds: "+sval); - - return (int)((lval+500)/1000); - } - - void list(PrintStream out) { - PrintWriter outw = new PrintWriter(out); - list(outw); - outw.flush(); - } - void list(PrintWriter out) { - out.println("#"+Utils.PACK_ZIP_ARCHIVE_MARKER_COMMENT+"["); - Set> defaults = defaultProps.entrySet(); - for (Map.Entry e : theMap.entrySet()) { - if (defaults.contains(e)) continue; - out.println(" " + e.getKey() + " = " + e.getValue()); - } - out.println("#]"); - } - - @Override - public int size() { - return theMap.size(); - } - - @Override - public boolean isEmpty() { - return theMap.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return theMap.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return theMap.containsValue(value); - } - - @Override - public String get(Object key) { - return theMap.get(key); - } - - @Override - public String remove(Object key) { - return theMap.remove(key); - } - - @Override - public void putAll(Map m) { - theMap.putAll(m); - } - - @Override - public void clear() { - theMap.clear(); - } - - @Override - public Set keySet() { - return theMap.keySet(); - } - - @Override - public Collection values() { - return theMap.values(); - } - - @Override - public Set> entrySet() { - return theMap.entrySet(); - } - - @Override - public Comparator comparator() { - return theMap.comparator(); - } - - @Override - public SortedMap subMap(String fromKey, String toKey) { - return theMap.subMap(fromKey, toKey); - } - - @Override - public SortedMap headMap(String toKey) { - return theMap.headMap(toKey); - } - - @Override - public SortedMap tailMap(String fromKey) { - return theMap.tailMap(fromKey); - } - - @Override - public String firstKey() { - return theMap.firstKey(); - } - - @Override - public String lastKey() { - return theMap.lastKey(); - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/TLGlobals.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/TLGlobals.java deleted file mode 100644 index 12316768bb2..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/TLGlobals.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.java.util.jar.pack; - -import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; -import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; -import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry; -import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; -import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry; -import com.sun.java.util.jar.pack.ConstantPool.MethodTypeEntry; -import com.sun.java.util.jar.pack.ConstantPool.InvokeDynamicEntry; -import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; -import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; -import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedMap; - -/* - * @author ksrini - */ - -/* - * This class provides a container to hold the global variables, for packer - * and unpacker instances. This is typically stashed away in a ThreadLocal, - * and the storage is destroyed upon completion. Therefore any local - * references to these members must be eliminated appropriately to prevent a - * memory leak. - */ -class TLGlobals { - // Global environment - final PropMap props; - - // Needed by ConstantPool.java - private final Map utf8Entries; - private final Map classEntries; - private final Map literalEntries; - private final Map signatureEntries; - private final Map descriptorEntries; - private final Map memberEntries; - private final Map methodHandleEntries; - private final Map methodTypeEntries; - private final Map invokeDynamicEntries; - private final Map bootstrapMethodEntries; - - TLGlobals() { - utf8Entries = new HashMap<>(); - classEntries = new HashMap<>(); - literalEntries = new HashMap<>(); - signatureEntries = new HashMap<>(); - descriptorEntries = new HashMap<>(); - memberEntries = new HashMap<>(); - methodHandleEntries = new HashMap<>(); - methodTypeEntries = new HashMap<>(); - invokeDynamicEntries = new HashMap<>(); - bootstrapMethodEntries = new HashMap<>(); - props = new PropMap(); - } - - SortedMap getPropMap() { - return props; - } - - Map getUtf8Entries() { - return utf8Entries; - } - - Map getClassEntries() { - return classEntries; - } - - Map getLiteralEntries() { - return literalEntries; - } - - Map getDescriptorEntries() { - return descriptorEntries; - } - - Map getSignatureEntries() { - return signatureEntries; - } - - Map getMemberEntries() { - return memberEntries; - } - - Map getMethodHandleEntries() { - return methodHandleEntries; - } - - Map getMethodTypeEntries() { - return methodTypeEntries; - } - - Map getInvokeDynamicEntries() { - return invokeDynamicEntries; - } - - Map getBootstrapMethodEntries() { - return bootstrapMethodEntries; - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java deleted file mode 100644 index e5942075fbf..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.HashSet; -import java.util.Set; -import java.util.SortedMap; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; -import java.util.zip.CRC32; -import java.util.zip.CheckedOutputStream; -import java.util.zip.ZipEntry; - -/* - * Implementation of the Pack provider. - * - * @author John Rose - * @author Kumar Srinivasan - */ - - -@SuppressWarnings({"removal"}) -public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { - - public UnpackerImpl() {} - - - - /** - * Get the set of options for the pack and unpack engines. - * @return A sorted association of option key strings to option values. - */ - public SortedMap properties() { - return props; - } - - // Back-pointer to NativeUnpacker, when active. - Object _nunp; - - - public String toString() { - return Utils.getVersionString(); - } - - //Driver routines - - // The unpack worker... - /** - * Takes a packed-stream InputStream, and writes to a JarOutputStream. Internally - * the entire buffer must be read, it may be more efficient to read the packed-stream - * to a file and pass the File object, in the alternate method described below. - *

- * Closes its input but not its output. (The output can accumulate more elements.) - * @param in an InputStream. - * @param out a JarOutputStream. - * @exception IOException if an error is encountered. - */ - public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException { - if (in == null) { - throw new NullPointerException("null input"); - } - if (out == null) { - throw new NullPointerException("null output"); - } - assert(Utils.currentInstance.get() == null); - - try { - Utils.currentInstance.set(this); - final int verbose = props.getInteger(Utils.DEBUG_VERBOSE); - BufferedInputStream in0 = new BufferedInputStream(in); - if (Utils.isJarMagic(Utils.readMagic(in0))) { - if (verbose > 0) - Utils.log.info("Copying unpacked JAR file..."); - Utils.copyJarFile(new JarInputStream(in0), out); - } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) { - (new DoUnpack()).run(in0, out); - in0.close(); - Utils.markJarFile(out); - } else { - try { - (new NativeUnpack(this)).run(in0, out); - } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) { - // failover to java implementation - (new DoUnpack()).run(in0, out); - } - in0.close(); - Utils.markJarFile(out); - } - } finally { - _nunp = null; - Utils.currentInstance.set(null); - } - } - - /** - * Takes an input File containing the pack file, and generates a JarOutputStream. - *

- * Does not close its output. (The output can accumulate more elements.) - * @param in a File. - * @param out a JarOutputStream. - * @exception IOException if an error is encountered. - */ - public synchronized void unpack(File in, JarOutputStream out) throws IOException { - if (in == null) { - throw new NullPointerException("null input"); - } - if (out == null) { - throw new NullPointerException("null output"); - } - // Use the stream-based implementation. - // %%% Reconsider if native unpacker learns to memory-map the file. - try (FileInputStream instr = new FileInputStream(in)) { - unpack(instr, out); - } - if (props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) { - in.delete(); - } - } - - private class DoUnpack { - final int verbose = props.getInteger(Utils.DEBUG_VERBOSE); - - { - props.setInteger(Pack200.Unpacker.PROGRESS, 0); - } - - // Here's where the bits are read from disk: - final Package pkg = new Package(); - - final boolean keepModtime - = Pack200.Packer.KEEP.equals( - props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP)); - final boolean keepDeflateHint - = Pack200.Packer.KEEP.equals( - props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP)); - final int modtime; - final boolean deflateHint; - { - if (!keepModtime) { - modtime = props.getTime(Utils.UNPACK_MODIFICATION_TIME); - } else { - modtime = pkg.default_modtime; - } - - deflateHint = (keepDeflateHint) ? false : - props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT); - } - - // Checksum apparatus. - final CRC32 crc = new CRC32(); - final ByteArrayOutputStream bufOut = new ByteArrayOutputStream(); - final OutputStream crcOut = new CheckedOutputStream(bufOut, crc); - - public void run(BufferedInputStream in, JarOutputStream out) throws IOException { - if (verbose > 0) { - props.list(System.out); - } - for (int seg = 1; ; seg++) { - unpackSegment(in, out); - - // Try to get another segment. - if (!Utils.isPackMagic(Utils.readMagic(in))) break; - if (verbose > 0) - Utils.log.info("Finished segment #"+seg); - } - } - - private void unpackSegment(InputStream in, JarOutputStream out) throws IOException { - props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0"); - // Process the output directory or jar output. - new PackageReader(pkg, in).read(); - - if (props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug"); - if (props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile"); - props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50"); - pkg.ensureAllClassFiles(); - // Now write out the files. - Set classesToWrite = new HashSet<>(pkg.getClasses()); - for (Package.File file : pkg.getFiles()) { - String name = file.nameString; - JarEntry je = new JarEntry(Utils.getJarEntryName(name)); - boolean deflate; - - deflate = (keepDeflateHint) - ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) || - ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) - : deflateHint; - - boolean needCRC = !deflate; // STORE mode requires CRC - - if (needCRC) crc.reset(); - bufOut.reset(); - if (file.isClassStub()) { - Package.Class cls = file.getStubClass(); - assert(cls != null); - new ClassWriter(cls, needCRC ? crcOut : bufOut).write(); - classesToWrite.remove(cls); // for an error check - } else { - // collect data & maybe CRC - file.writeTo(needCRC ? crcOut : bufOut); - } - je.setMethod(deflate ? JarEntry.DEFLATED : JarEntry.STORED); - if (needCRC) { - if (verbose > 0) - Utils.log.info("stored size="+bufOut.size()+" and crc="+crc.getValue()); - - je.setMethod(JarEntry.STORED); - je.setSize(bufOut.size()); - je.setCrc(crc.getValue()); - } - if (keepModtime) { - LocalDateTime ldt = LocalDateTime - .ofEpochSecond(file.modtime, 0, ZoneOffset.UTC); - je.setTimeLocal(ldt); - } else { - je.setTime((long)modtime * 1000); - } - out.putNextEntry(je); - bufOut.writeTo(out); - out.closeEntry(); - if (verbose > 0) - Utils.log.info("Writing "+Utils.zeString((ZipEntry)je)); - } - assert(classesToWrite.isEmpty()); - props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100"); - pkg.reset(); // reset for the next segment, if any - } - } -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/Utils.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/Utils.java deleted file mode 100644 index d17dc899821..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/Utils.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.util.jar.pack; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collections; -import java.util.Date; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.zip.ZipEntry; -import sun.util.logging.PlatformLogger; - -class Utils { - static final String COM_PREFIX = "com.sun.java.util.jar.pack."; - static final String METAINF = "META-INF"; - - /* - * Outputs various diagnostic support information. - * If >0, print summary comments (e.g., constant pool info). - * If >1, print unit comments (e.g., processing of classes). - * If >2, print many comments (e.g., processing of members). - * If >3, print tons of comments (e.g., processing of references). - * (installer only) - */ - static final String DEBUG_VERBOSE = COM_PREFIX+"verbose"; - - /* - * Disables use of native code, prefers the Java-coded implementation. - * (installer only) - */ - static final String DEBUG_DISABLE_NATIVE = COM_PREFIX+"disable.native"; - - /* - * Property indicating that the unpacker should - * ignore the transmitted PACK_MODIFICATION_TIME, - * replacing it by the given value. The value can - * be a numeric string, representing the number of - * mSecs since the epoch (UTC), or the special string - * {@link #NOW}, meaning the current time (UTC). - * The default value is the special string {@link #KEEP}, - * which asks the unpacker to preserve all transmitted - * modification time information. - * (installer only) - */ - static final String UNPACK_MODIFICATION_TIME = COM_PREFIX+"unpack.modification.time"; - - /* - * Property indicating that the unpacker strip the - * Debug Attributes, if they are present, in the pack stream. - * The default value is false. - * (installer only) - */ - static final String UNPACK_STRIP_DEBUG = COM_PREFIX+"unpack.strip.debug"; - - /* - * Remove the input file after unpacking. - * (installer only) - */ - static final String UNPACK_REMOVE_PACKFILE = COM_PREFIX+"unpack.remove.packfile"; - - /* - * A possible value for MODIFICATION_TIME - */ - static final String NOW = "now"; - // Other debug options: - // com...debug.bands=false add band IDs to pack file, to verify sync - // com...dump.bands=false dump band contents to local disk - // com...no.vary.codings=false turn off coding variation heuristics - // com...no.big.strings=false turn off "big string" feature - - /* - * If this property is set to {@link #TRUE}, the packer will preserve - * the ordering of class files of the original jar in the output archive. - * The ordering is preserved only for class-files; resource files - * may be reordered. - *

- * If the packer is allowed to reorder class files, it can marginally - * decrease the transmitted size of the archive. - */ - static final String PACK_KEEP_CLASS_ORDER = COM_PREFIX+"keep.class.order"; - /* - * This string PACK200 is given as a zip comment on all JAR files - * produced by this utility. - */ - static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; - - /* - * behaviour when we hit a class format error, but not necessarily - * an unknown attribute, by default it is allowed to PASS. - */ - static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error"; - - // Keep a TLS point to the global data and environment. - // This makes it simpler to supply environmental options - // to the engine code, especially the native code. - static final ThreadLocal currentInstance = new ThreadLocal<>(); - - // convenience method to access the TL globals - static TLGlobals getTLGlobals() { - return currentInstance.get(); - } - - static PropMap currentPropMap() { - Object obj = currentInstance.get(); - if (obj instanceof PackerImpl) - return ((PackerImpl)obj).props; - if (obj instanceof UnpackerImpl) - return ((UnpackerImpl)obj).props; - return null; - } - - static final boolean nolog - = Boolean.getBoolean(COM_PREFIX+"nolog"); - - static final boolean SORT_MEMBERS_DESCR_MAJOR - = Boolean.getBoolean(COM_PREFIX+"sort.members.descr.major"); - - static final boolean SORT_HANDLES_KIND_MAJOR - = Boolean.getBoolean(COM_PREFIX+"sort.handles.kind.major"); - - static final boolean SORT_INDY_BSS_MAJOR - = Boolean.getBoolean(COM_PREFIX+"sort.indy.bss.major"); - - static final boolean SORT_BSS_BSM_MAJOR - = Boolean.getBoolean(COM_PREFIX+"sort.bss.bsm.major"); - - static class Pack200Logger { - private final String name; - private PlatformLogger log; - Pack200Logger(String name) { - this.name = name; - } - - private synchronized PlatformLogger getLogger() { - if (log == null) { - log = PlatformLogger.getLogger(name); - } - return log; - } - - public void warning(String msg, Object param) { - getLogger().warning(msg, param); - } - - public void warning(String msg) { - warning(msg, null); - } - - public void info(String msg) { - int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); - if (verbose > 0) { - if (nolog) { - System.out.println(msg); - } else { - getLogger().info(msg); - } - } - } - - public void fine(String msg) { - int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); - if (verbose > 0) { - System.out.println(msg); - } - } - } - - static final Pack200Logger log - = new Pack200Logger("java.util.jar.Pack200"); - - // Returns the Max Version String of this implementation - static String getVersionString() { - return "Pack200, Vendor: " + - System.getProperty("java.vendor") + - ", Version: " + Constants.MAX_PACKAGE_VERSION; - } - - static void markJarFile(JarOutputStream out) throws IOException { - out.setComment(PACK_ZIP_ARCHIVE_MARKER_COMMENT); - } - - // -0 mode helper - static void copyJarFile(JarInputStream in, JarOutputStream out) throws IOException { - if (in.getManifest() != null) { - ZipEntry me = new ZipEntry(JarFile.MANIFEST_NAME); - out.putNextEntry(me); - in.getManifest().write(out); - out.closeEntry(); - } - byte[] buffer = new byte[1 << 14]; - for (JarEntry je; (je = in.getNextJarEntry()) != null; ) { - out.putNextEntry(je); - for (int nr; 0 < (nr = in.read(buffer)); ) { - out.write(buffer, 0, nr); - } - } - in.close(); - markJarFile(out); // add PACK200 comment - } - static void copyJarFile(JarFile in, JarOutputStream out) throws IOException { - byte[] buffer = new byte[1 << 14]; - for (JarEntry je : Collections.list(in.entries())) { - out.putNextEntry(je); - InputStream ein = in.getInputStream(je); - for (int nr; 0 < (nr = ein.read(buffer)); ) { - out.write(buffer, 0, nr); - } - } - in.close(); - markJarFile(out); // add PACK200 comment - } - static void copyJarFile(JarInputStream in, OutputStream out) throws IOException { - // 4947205 : Peformance is slow when using pack-effort=0 - out = new BufferedOutputStream(out); - out = new NonCloser(out); // protect from JarOutputStream.close() - try (JarOutputStream jout = new JarOutputStream(out)) { - copyJarFile(in, jout); - } - } - static void copyJarFile(JarFile in, OutputStream out) throws IOException { - - // 4947205 : Peformance is slow when using pack-effort=0 - out = new BufferedOutputStream(out); - out = new NonCloser(out); // protect from JarOutputStream.close() - try (JarOutputStream jout = new JarOutputStream(out)) { - copyJarFile(in, jout); - } - } - // Wrapper to prevent closing of client-supplied stream. - private static - class NonCloser extends FilterOutputStream { - NonCloser(OutputStream out) { super(out); } - public void close() throws IOException { flush(); } - } - static String getJarEntryName(String name) { - if (name == null) return null; - return name.replace(File.separatorChar, '/'); - } - - static String zeString(ZipEntry ze) { - int store = (ze.getCompressedSize() > 0) ? - (int)( (1.0 - ((double)ze.getCompressedSize()/(double)ze.getSize()))*100 ) - : 0 ; - // Follow unzip -lv output - return ze.getSize() + "\t" + ze.getMethod() - + "\t" + ze.getCompressedSize() + "\t" - + store + "%\t" - + new Date(ze.getTime()) + "\t" - + Long.toHexString(ze.getCrc()) + "\t" - + ze.getName() ; - } - - - - static byte[] readMagic(BufferedInputStream in) throws IOException { - in.mark(4); - byte[] magic = new byte[4]; - for (int i = 0; i < magic.length; i++) { - // read 1 byte at a time, so we always get 4 - if (1 != in.read(magic, i, 1)) - break; - } - in.reset(); - return magic; - } - - // magic number recognizers - static boolean isJarMagic(byte[] magic) { - return (magic[0] == (byte)'P' && - magic[1] == (byte)'K' && - magic[2] >= 1 && - magic[2] < 8 && - magic[3] == magic[2] + 1); - } - static boolean isPackMagic(byte[] magic) { - return (magic[0] == (byte)0xCA && - magic[1] == (byte)0xFE && - magic[2] == (byte)0xD0 && - magic[3] == (byte)0x0D); - } - static boolean isGZIPMagic(byte[] magic) { - return (magic[0] == (byte)0x1F && - magic[1] == (byte)0x8B && - magic[2] == (byte)0x08); - // fourth byte is variable "flg" field - } - - private Utils() { } // do not instantiate -} diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties b/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties deleted file mode 100644 index f52a00c17f8..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties +++ /dev/null @@ -1,48 +0,0 @@ -# Properties which are known to Pack without further instruction, -# but are not part of the JSR 200 standard. -# They amount to default Pack properties. - -# Additional standard properties are hardwired into the code, -# but may be overridden here, if necessary. - -# The makefile for this directory must copy this file -# into the target class hierarchy so it will get into runtime image. - -# JCOV attributes -pack.code.attribute.CoverageTable = NH[PHHII] -pack.code.attribute.CharacterRangeTable = NH[PHPOHIIH] -pack.class.attribute.SourceID = RUH -pack.class.attribute.CompilationID = RUH -pack.class.attribute.NestHost = RCH -pack.class.attribute.NestMembers = NH[RCH] - -# Note: Zero-length ("marker") attributes do not need to be specified here. -# They are automatically defined to have an empty layout. -#pack.class.attribute.Deprecated = -#pack.field.attribute.Deprecated = -#pack.method.attribute.Deprecated = - -## Example layouts for builtins. (Do not uncomment.) -#pack.class.attribute.Signature = RSH -#pack.field.attribute.Signature = RSH -#pack.method.attribute.Signature = RSH -# Signature = { signature:u2 } -#pack.class.attribute.SourceFile = RUH -# SourceFile = { utf8:u2 } -#pack.class.attribute.InnerClasses = NH[RCH RCNH RUNH FH] -# InnerClasses = { (N:u2)*{ class:u2 class?:u2 utf8?:u2 flags:u2 } } -#pack.method.attribute.Exceptions = NH[RCH] -# Exceptions = { (N:u2)*{ class:u2 } } -#pack.code.attribute.StackMap = \ -# [NH[PH NH[(1)] NH[(1)]]] \ -# [TB (7)[RCH] (8,9)[PH] ()[]] -#pack.code.attribute.LineNumberTable = NH[PH H] -#pack.code.attribute.LocalVariableTable = NH[PH OH RUH RSH H] - -# Set this property if the classfile version number is bumped, -# as long as the format remains compatible with Pack200. -#com.sun.java.util.jar.pack.max.class.majver = 59 - -# Uncomment this line if the C-coded unpacker seems broken. -#com.sun.java.util.jar.pack.disable.native = true - diff --git a/src/java.base/share/classes/com/sun/java/util/jar/pack/package-info.java b/src/java.base/share/classes/com/sun/java/util/jar/pack/package-info.java deleted file mode 100644 index be6c818a249..00000000000 --- a/src/java.base/share/classes/com/sun/java/util/jar/pack/package-info.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * This package provides methods to read files from a JAR file and to - * transform them to a more compact transfer format called Pack200. - * It also provides methods to receive the transmitted data and expand - * it into a JAR file equivalent to the original JAR file. - * - *

- * The {@code pack} methods may be used by application developers who - * wish to deploy large JARs on the web. The {@code unpack} methods - * may be used by deployment applications such as Java Web Start and - * Java Plugin. - * - *

- * In typical use, the packed output should be further compressed - * using a suitable tool such as gzip or - * {@code java.util.zip.GZIPOutputStream}. The resulting file (with - * a suffix ".pack.gz") should be hosted on a HTTP/1.1 compliant - * server, which will be capable of handling "Accept-Encoding", as - * specified by the HTTP 1.1 RFC2616 specification. - * - *

- * NOTE: It is recommended that the original ".jar" file be - * hosted in addition to the ".pack.gz" file, so that older client - * implementations will continue to work reliably. (On-demand - * compression by the server is not recommended.) - * - *

- * When a client application requests a ".jar" file (call it - * "Large.jar"), the client will transmit the headers - * "Content-Type=application/x-java-archive" as well as - * "Accept-Encoding=pack200-gzip". This indicates to the server that - * the client application desires an version of the file encoded with - * Pack200 and further compressed with gzip. - * - *

- * The server implementation will typically check for the existence of - * "Large.pack.gz". If that file is available, the server will - * transmit it with the headers "Content-Encoding=pack200-gzip" and - * "Content-Type=application/x-java-archive". - * - *

- * If the ".pack.gz" file, is not available, then the server will - * transmit the original ".jar" with "Content-Encoding=null" and - * "Content-Type=application/x-java-archive". - * - *

- * A MIME type of "application/x-java-pack200" may be specified by the - * client application to indicate a ".pack" file is required. - * However, this has limited capability, and is not recommended. - * - *

Package Specification

- * Network Transfer Format Specification : - * http://jcp.org/en/jsr/detail?id=200 - * - *

Related Documentation

- * For overviews, tutorials, examples, guides, and tool documentation, please - * see: - * - * - *
  • - * @since 1.5
  • - */ -package com.sun.java.util.jar.pack; diff --git a/src/java.base/share/classes/java/util/jar/Pack200.java b/src/java.base/share/classes/java/util/jar/Pack200.java deleted file mode 100644 index 987ecfc509c..00000000000 --- a/src/java.base/share/classes/java/util/jar/Pack200.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.util.jar; - -import java.util.SortedMap; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.File; -import java.io.IOException; -import sun.security.action.GetPropertyAction; - - -/** - * Transforms a JAR file to or from a packed stream in Pack200 format. - * Please refer to
    Network Transfer Format JSR 200 Specification - *

    - * Typically the packer engine is used by application developers - * to deploy or host JAR files on a website. - * The unpacker engine is used by deployment applications to - * transform the byte-stream back to JAR format. - *

    - * Here is an example using packer and unpacker: - *

    {@code
    - *    import java.util.jar.Pack200;
    - *    import java.util.jar.Pack200.*;
    - *    ...
    - *    // Create the Packer object
    - *    Packer packer = Pack200.newPacker();
    - *
    - *    // Initialize the state by setting the desired properties
    - *    Map p = packer.properties();
    - *    // take more time choosing codings for better compression
    - *    p.put(Packer.EFFORT, "7");  // default is "5"
    - *    // use largest-possible archive segments (>10% better compression).
    - *    p.put(Packer.SEGMENT_LIMIT, "-1");
    - *    // reorder files for better compression.
    - *    p.put(Packer.KEEP_FILE_ORDER, Packer.FALSE);
    - *    // smear modification times to a single value.
    - *    p.put(Packer.MODIFICATION_TIME, Packer.LATEST);
    - *    // ignore all JAR deflation requests,
    - *    // transmitting a single request to use "store" mode.
    - *    p.put(Packer.DEFLATE_HINT, Packer.FALSE);
    - *    // discard debug attributes
    - *    p.put(Packer.CODE_ATTRIBUTE_PFX+"LineNumberTable", Packer.STRIP);
    - *    // throw an error if an attribute is unrecognized
    - *    p.put(Packer.UNKNOWN_ATTRIBUTE, Packer.ERROR);
    - *    // pass one class file uncompressed:
    - *    p.put(Packer.PASS_FILE_PFX+0, "mutants/Rogue.class");
    - *    try {
    - *        JarFile jarFile = new JarFile("/tmp/testref.jar");
    - *        FileOutputStream fos = new FileOutputStream("/tmp/test.pack");
    - *        // Call the packer
    - *        packer.pack(jarFile, fos);
    - *        jarFile.close();
    - *        fos.close();
    - *
    - *        File f = new File("/tmp/test.pack");
    - *        FileOutputStream fostream = new FileOutputStream("/tmp/test.jar");
    - *        JarOutputStream jostream = new JarOutputStream(fostream);
    - *        Unpacker unpacker = Pack200.newUnpacker();
    - *        // Call the unpacker
    - *        unpacker.unpack(f, jostream);
    - *        // Must explicitly close the output.
    - *        jostream.close();
    - *    } catch (IOException ioe) {
    - *        ioe.printStackTrace();
    - *    }
    - * }
    - *

    - * A Pack200 file compressed with gzip can be hosted on HTTP/1.1 web servers. - * The deployment applications can use "Accept-Encoding=pack200-gzip". This - * indicates to the server that the client application desires a version of - * the file encoded with Pack200 and further compressed with gzip. Please - * refer to the Java Deployment Guide for techniques and details. - *

    - * Unless otherwise noted, passing a {@code null} argument to a constructor or - * method in this class will cause a {@link NullPointerException} to be thrown. - * - * @author John Rose - * @author Kumar Srinivasan - * @since 1.5 - * @deprecated This class is deprecated, and is planned for removal in a future - * release. - */ -@Deprecated(since="11", forRemoval=true) -public abstract class Pack200 { - private Pack200() {} //prevent instantiation - - // Static methods of the Pack200 class. - /** - * Obtain new instance of a class that implements Packer. - *

      - *
    • If the system property {@systemProperty java.util.jar.Pack200.Packer} - * is defined, then the value is taken to be the fully-qualified name - * of a concrete implementation class, which must implement Packer. - * This class is loaded and instantiated. If this process fails - * then an unspecified error is thrown.

    • - * - *
    • If an implementation has not been specified with the system - * property, then the system-default implementation class is instantiated, - * and the result is returned.

    • - *
    - * - *

    Note: The returned object is not guaranteed to operate - * correctly if multiple threads use it at the same time. - * A multi-threaded application should either allocate multiple - * packer engines, or else serialize use of one engine with a lock. - * - * @return A newly allocated Packer engine. - */ - public static synchronized Packer newPacker() { - return (Packer) newInstance(PACK_PROVIDER); - } - - - /** - * Obtain new instance of a class that implements Unpacker. - *

      - *
    • If the system property {@systemProperty java.util.jar.Pack200.Unpacker} - * is defined, then the value is taken to be the fully-qualified - * name of a concrete implementation class, which must implement Unpacker. - * The class is loaded and instantiated. If this process fails - * then an unspecified error is thrown.

    • - * - *
    • If an implementation has not been specified with the - * system property, then the system-default implementation class - * is instantiated, and the result is returned.

    • - *
    - * - *

    Note: The returned object is not guaranteed to operate - * correctly if multiple threads use it at the same time. - * A multi-threaded application should either allocate multiple - * unpacker engines, or else serialize use of one engine with a lock. - * - * @return A newly allocated Unpacker engine. - */ - - public static Unpacker newUnpacker() { - return (Unpacker) newInstance(UNPACK_PROVIDER); - } - - // Interfaces - /** - * The packer engine applies various transformations to the input JAR file, - * making the pack stream highly compressible by a compressor such as - * gzip or zip. An instance of the engine can be obtained - * using {@link #newPacker}. - - * The high degree of compression is achieved - * by using a number of techniques described in the JSR 200 specification. - * Some of the techniques are sorting, re-ordering and co-location of the - * constant pool. - *

    - * The pack engine is initialized to an initial state as described - * by their properties below. - * The initial state can be manipulated by getting the - * engine properties (using {@link #properties}) and storing - * the modified properties on the map. - * The resource files will be passed through with no changes at all. - * The class files will not contain identical bytes, since the unpacker - * is free to change minor class file features such as constant pool order. - * However, the class files will be semantically identical, - * as specified in - * The Java™ Virtual Machine Specification. - *

    - * By default, the packer does not change the order of JAR elements. - * Also, the modification time and deflation hint of each - * JAR element is passed unchanged. - * (Any other ZIP-archive information, such as extra attributes - * giving Unix file permissions, are lost.) - *

    - * Note that packing and unpacking a JAR will in general alter the - * bytewise contents of classfiles in the JAR. This means that packing - * and unpacking will in general invalidate any digital signatures - * which rely on bytewise images of JAR elements. In order both to sign - * and to pack a JAR, you must first pack and unpack the JAR to - * "normalize" it, then compute signatures on the unpacked JAR elements, - * and finally repack the signed JAR. - * Both packing steps should - * use precisely the same options, and the segment limit may also - * need to be set to "-1", to prevent accidental variation of segment - * boundaries as class file sizes change slightly. - *

    - * (Here's why this works: Any reordering the packer does - * of any classfile structures is idempotent, so the second packing - * does not change the orderings produced by the first packing. - * Also, the unpacker is guaranteed by the JSR 200 specification - * to produce a specific bytewise image for any given transmission - * ordering of archive elements.) - *

    - * In order to maintain backward compatibility, the pack file's version is - * set to accommodate the class files present in the input JAR file. In - * other words, the pack file version will be the latest, if the class files - * are the latest and conversely the pack file version will be the oldest - * if the class file versions are also the oldest. For intermediate class - * file versions the corresponding pack file version will be used. - * For example: - * If the input JAR-files are solely comprised of 1.5 (or lesser) - * class files, a 1.5 compatible pack file is produced. This will also be - * the case for archives that have no class files. - * If the input JAR-files contains a 1.6 class file, then the pack file - * version will be set to 1.6. - *

    - * Note: Unless otherwise noted, passing a {@code null} argument to a - * constructor or method in this class will cause a {@link NullPointerException} - * to be thrown. - * - * @since 1.5 - * @deprecated This interface is deprecated, and is planned for removal in a - * future release. - */ - @Deprecated(since="11", forRemoval=true) - public interface Packer { - /** - * This property is a numeral giving the estimated target size N - * (in bytes) of each archive segment. - * If a single input file requires more than N bytes, - * it will be given its own archive segment. - *

    - * As a special case, a value of -1 will produce a single large - * segment with all input files, while a value of 0 will - * produce one segment for each class. - * Larger archive segments result in less fragmentation and - * better compression, but processing them requires more memory. - *

    - * The size of each segment is estimated by counting the size of each - * input file to be transmitted in the segment, along with the size - * of its name and other transmitted properties. - *

    - * The default is -1, which means the packer will always create a single - * segment output file. In cases where extremely large output files are - * generated, users are strongly encouraged to use segmenting or break - * up the input file into smaller JARs. - *

    - * A 10Mb JAR packed without this limit will - * typically pack about 10% smaller, but the packer may require - * a larger Java heap (about ten times the segment limit). - */ - String SEGMENT_LIMIT = "pack.segment.limit"; - - /** - * If this property is set to {@link #TRUE}, the packer will transmit - * all elements in their original order within the source archive. - *

    - * If it is set to {@link #FALSE}, the packer may reorder elements, - * and also remove JAR directory entries, which carry no useful - * information for Java applications. - * (Typically this enables better compression.) - *

    - * The default is {@link #TRUE}, which preserves the input information, - * but may cause the transmitted archive to be larger than necessary. - */ - String KEEP_FILE_ORDER = "pack.keep.file.order"; - - - /** - * If this property is set to a single decimal digit, the packer will - * use the indicated amount of effort in compressing the archive. - * Level 1 may produce somewhat larger size and faster compression speed, - * while level 9 will take much longer but may produce better compression. - *

    - * The special value 0 instructs the packer to copy through the - * original JAR file directly, with no compression. The JSR 200 - * standard requires any unpacker to understand this special case - * as a pass-through of the entire archive. - *

    - * The default is 5, investing a modest amount of time to - * produce reasonable compression. - */ - String EFFORT = "pack.effort"; - - /** - * If this property is set to {@link #TRUE} or {@link #FALSE}, the packer - * will set the deflation hint accordingly in the output archive, and - * will not transmit the individual deflation hints of archive elements. - *

    - * If this property is set to the special string {@link #KEEP}, the packer - * will attempt to determine an independent deflation hint for each - * available element of the input archive, and transmit this hint separately. - *

    - * The default is {@link #KEEP}, which preserves the input information, - * but may cause the transmitted archive to be larger than necessary. - *

    - * It is up to the unpacker implementation - * to take action upon the hint to suitably compress the elements of - * the resulting unpacked jar. - *

    - * The deflation hint of a ZIP or JAR element indicates - * whether the element was deflated or stored directly. - */ - String DEFLATE_HINT = "pack.deflate.hint"; - - /** - * If this property is set to the special string {@link #LATEST}, - * the packer will attempt to determine the latest modification time, - * among all the available entries in the original archive or the latest - * modification time of all the available entries in each segment. - * This single value will be transmitted as part of the segment and applied - * to all the entries in each segment, {@link #SEGMENT_LIMIT}. - *

    - * This can marginally decrease the transmitted size of the - * archive, at the expense of setting all installed files to a single - * date. - *

    - * If this property is set to the special string {@link #KEEP}, - * the packer transmits a separate modification time for each input - * element. - *

    - * The default is {@link #KEEP}, which preserves the input information, - * but may cause the transmitted archive to be larger than necessary. - *

    - * It is up to the unpacker implementation to take action to suitably - * set the modification time of each element of its output file. - * @see #SEGMENT_LIMIT - */ - String MODIFICATION_TIME = "pack.modification.time"; - - /** - * Indicates that a file should be passed through bytewise, with no - * compression. Multiple files may be specified by specifying - * additional properties with distinct strings appended, to - * make a family of properties with the common prefix. - *

    - * There is no pathname transformation, except - * that the system file separator is replaced by the JAR file - * separator '/'. - *

    - * The resulting file names must match exactly as strings with their - * occurrences in the JAR file. - *

    - * If a property value is a directory name, all files under that - * directory will be passed also. - *

    - * Examples: - *

    {@code
    -         *     Map p = packer.properties();
    -         *     p.put(PASS_FILE_PFX+0, "mutants/Rogue.class");
    -         *     p.put(PASS_FILE_PFX+1, "mutants/Wolverine.class");
    -         *     p.put(PASS_FILE_PFX+2, "mutants/Storm.class");
    -         *     # Pass all files in an entire directory hierarchy:
    -         *     p.put(PASS_FILE_PFX+3, "police/");
    -         * }
    - */ - String PASS_FILE_PFX = "pack.pass.file."; - - /// Attribute control. - - /** - * Indicates the action to take when a class-file containing an unknown - * attribute is encountered. Possible values are the strings {@link #ERROR}, - * {@link #STRIP}, and {@link #PASS}. - *

    - * The string {@link #ERROR} means that the pack operation - * as a whole will fail, with an exception of type {@code IOException}. - * The string - * {@link #STRIP} means that the attribute will be dropped. - * The string - * {@link #PASS} means that the whole class-file will be passed through - * (as if it were a resource file) without compression, with a suitable warning. - * This is the default value for this property. - *

    - * Examples: - *

    {@code
    -         *     Map p = pack200.getProperties();
    -         *     p.put(UNKNOWN_ATTRIBUTE, ERROR);
    -         *     p.put(UNKNOWN_ATTRIBUTE, STRIP);
    -         *     p.put(UNKNOWN_ATTRIBUTE, PASS);
    -         * }
    - */ - String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute"; - - /** - * When concatenated with a class attribute name, - * indicates the format of that attribute, - * using the layout language specified in the JSR 200 specification. - *

    - * For example, the effect of this option is built in: - * {@code pack.class.attribute.SourceFile=RUH}. - *

    - * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} are - * also allowed, with the same meaning as {@link #UNKNOWN_ATTRIBUTE}. - * This provides a way for users to request that specific attributes be - * refused, stripped, or passed bitwise (with no class compression). - *

    - * Code like this might be used to support attributes for JCOV: - *

    {@code
    -         *     Map p = packer.properties();
    -         *     p.put(CODE_ATTRIBUTE_PFX+"CoverageTable",       "NH[PHHII]");
    -         *     p.put(CODE_ATTRIBUTE_PFX+"CharacterRangeTable", "NH[PHPOHIIH]");
    -         *     p.put(CLASS_ATTRIBUTE_PFX+"SourceID",           "RUH");
    -         *     p.put(CLASS_ATTRIBUTE_PFX+"CompilationID",      "RUH");
    -         * }
    - *

    - * Code like this might be used to strip debugging attributes: - *

    {@code
    -         *     Map p = packer.properties();
    -         *     p.put(CODE_ATTRIBUTE_PFX+"LineNumberTable",    STRIP);
    -         *     p.put(CODE_ATTRIBUTE_PFX+"LocalVariableTable", STRIP);
    -         *     p.put(CLASS_ATTRIBUTE_PFX+"SourceFile",        STRIP);
    -         * }
    - */ - String CLASS_ATTRIBUTE_PFX = "pack.class.attribute."; - - /** - * When concatenated with a field attribute name, - * indicates the format of that attribute. - * For example, the effect of this option is built in: - * {@code pack.field.attribute.Deprecated=}. - * The special strings {@link #ERROR}, {@link #STRIP}, and - * {@link #PASS} are also allowed. - * @see #CLASS_ATTRIBUTE_PFX - */ - String FIELD_ATTRIBUTE_PFX = "pack.field.attribute."; - - /** - * When concatenated with a method attribute name, - * indicates the format of that attribute. - * For example, the effect of this option is built in: - * {@code pack.method.attribute.Exceptions=NH[RCH]}. - * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} - * are also allowed. - * @see #CLASS_ATTRIBUTE_PFX - */ - String METHOD_ATTRIBUTE_PFX = "pack.method.attribute."; - - /** - * When concatenated with a code attribute name, - * indicates the format of that attribute. - * For example, the effect of this option is built in: - * {@code pack.code.attribute.LocalVariableTable=NH[PHOHRUHRSHH]}. - * The special strings {@link #ERROR}, {@link #STRIP}, and {@link #PASS} - * are also allowed. - * @see #CLASS_ATTRIBUTE_PFX - */ - String CODE_ATTRIBUTE_PFX = "pack.code.attribute."; - - /** - * The packer's progress as a percentage, as periodically - * updated by the packer. - * Values of 0 - 100 are normal, and -1 indicates a stall. - * Progress can be monitored by polling the value of this - * property. - *

    - * At a minimum, the packer must set progress to 0 - * at the beginning of a packing operation, and to 100 - * at the end. - */ - String PROGRESS = "pack.progress"; - - /** The string "keep", a possible value for certain properties. - * @see #DEFLATE_HINT - * @see #MODIFICATION_TIME - */ - String KEEP = "keep"; - - /** The string "pass", a possible value for certain properties. - * @see #UNKNOWN_ATTRIBUTE - * @see #CLASS_ATTRIBUTE_PFX - * @see #FIELD_ATTRIBUTE_PFX - * @see #METHOD_ATTRIBUTE_PFX - * @see #CODE_ATTRIBUTE_PFX - */ - String PASS = "pass"; - - /** The string "strip", a possible value for certain properties. - * @see #UNKNOWN_ATTRIBUTE - * @see #CLASS_ATTRIBUTE_PFX - * @see #FIELD_ATTRIBUTE_PFX - * @see #METHOD_ATTRIBUTE_PFX - * @see #CODE_ATTRIBUTE_PFX - */ - String STRIP = "strip"; - - /** The string "error", a possible value for certain properties. - * @see #UNKNOWN_ATTRIBUTE - * @see #CLASS_ATTRIBUTE_PFX - * @see #FIELD_ATTRIBUTE_PFX - * @see #METHOD_ATTRIBUTE_PFX - * @see #CODE_ATTRIBUTE_PFX - */ - String ERROR = "error"; - - /** The string "true", a possible value for certain properties. - * @see #KEEP_FILE_ORDER - * @see #DEFLATE_HINT - */ - String TRUE = "true"; - - /** The string "false", a possible value for certain properties. - * @see #KEEP_FILE_ORDER - * @see #DEFLATE_HINT - */ - String FALSE = "false"; - - /** The string "latest", a possible value for certain properties. - * @see #MODIFICATION_TIME - */ - String LATEST = "latest"; - - /** - * Get the set of this engine's properties. - * This set is a "live view", so that changing its - * contents immediately affects the Packer engine, and - * changes from the engine (such as progress indications) - * are immediately visible in the map. - * - *

    The property map may contain pre-defined implementation - * specific and default properties. Users are encouraged to - * read the information and fully understand the implications, - * before modifying pre-existing properties. - *

    - * Implementation specific properties are prefixed with a - * package name associated with the implementor, beginning - * with {@code com.} or a similar prefix. - * All property names beginning with {@code pack.} and - * {@code unpack.} are reserved for use by this API. - *

    - * Unknown properties may be ignored or rejected with an - * unspecified error, and invalid entries may cause an - * unspecified error to be thrown. - * - *

    - * The returned map implements all optional {@link SortedMap} operations - * @return A sorted association of property key strings to property - * values. - */ - SortedMap properties(); - - /** - * Takes a JarFile and converts it into a Pack200 archive. - *

    - * Closes its input but not its output. (Pack200 archives are appendable.) - * @param in a JarFile - * @param out an OutputStream - * @throws IOException if an error is encountered. - */ - void pack(JarFile in, OutputStream out) throws IOException ; - - /** - * Takes a JarInputStream and converts it into a Pack200 archive. - *

    - * Closes its input but not its output. (Pack200 archives are appendable.) - *

    - * The modification time and deflation hint attributes are not available, - * for the JAR manifest file and its containing directory. - * - * @see #MODIFICATION_TIME - * @see #DEFLATE_HINT - * @param in a JarInputStream - * @param out an OutputStream - * @throws IOException if an error is encountered. - */ - void pack(JarInputStream in, OutputStream out) throws IOException ; - } - - /** - * The unpacker engine converts the packed stream to a JAR file. - * An instance of the engine can be obtained - * using {@link #newUnpacker}. - *

    - * Every JAR file produced by this engine will include the string - * "{@code PACK200}" as a zip file comment. - * This allows a deployer to detect if a JAR archive was packed and unpacked. - *

    - * Note: Unless otherwise noted, passing a {@code null} argument to a - * constructor or method in this class will cause a {@link NullPointerException} - * to be thrown. - *

    - * This version of the unpacker is compatible with all previous versions. - * @since 1.5 - * @deprecated This interface is deprecated, and is planned for removal in a - * future release. - */ - @Deprecated(since="11", forRemoval=true) - public interface Unpacker { - - /** The string "keep", a possible value for certain properties. - * @see #DEFLATE_HINT - */ - String KEEP = "keep"; - - /** The string "true", a possible value for certain properties. - * @see #DEFLATE_HINT - */ - String TRUE = "true"; - - /** The string "false", a possible value for certain properties. - * @see #DEFLATE_HINT - */ - String FALSE = "false"; - - /** - * Property indicating that the unpacker should - * ignore all transmitted values for DEFLATE_HINT, - * replacing them by the given value, {@link #TRUE} or {@link #FALSE}. - * The default value is the special string {@link #KEEP}, - * which asks the unpacker to preserve all transmitted - * deflation hints. - */ - String DEFLATE_HINT = "unpack.deflate.hint"; - - - - /** - * The unpacker's progress as a percentage, as periodically - * updated by the unpacker. - * Values of 0 - 100 are normal, and -1 indicates a stall. - * Progress can be monitored by polling the value of this - * property. - *

    - * At a minimum, the unpacker must set progress to 0 - * at the beginning of an unpacking operation, and to 100 - * at the end. - */ - String PROGRESS = "unpack.progress"; - - /** - * Get the set of this engine's properties. This set is - * a "live view", so that changing its - * contents immediately affects the Unpacker engine, and - * changes from the engine (such as progress indications) - * are immediately visible in the map. - * - *

    The property map may contain pre-defined implementation - * specific and default properties. Users are encouraged to - * read the information and fully understand the implications, - * before modifying pre-existing properties. - *

    - * Implementation specific properties are prefixed with a - * package name associated with the implementor, beginning - * with {@code com.} or a similar prefix. - * All property names beginning with {@code pack.} and - * {@code unpack.} are reserved for use by this API. - *

    - * Unknown properties may be ignored or rejected with an - * unspecified error, and invalid entries may cause an - * unspecified error to be thrown. - * - * @return A sorted association of option key strings to option values. - */ - SortedMap properties(); - - /** - * Read a Pack200 archive, and write the encoded JAR to - * a JarOutputStream. - * The entire contents of the input stream will be read. - * It may be more efficient to read the Pack200 archive - * to a file and pass the File object, using the alternate - * method described below. - *

    - * Closes its input but not its output. (The output can accumulate more elements.) - * @param in an InputStream. - * @param out a JarOutputStream. - * @throws IOException if an error is encountered. - */ - void unpack(InputStream in, JarOutputStream out) throws IOException; - - /** - * Read a Pack200 archive, and write the encoded JAR to - * a JarOutputStream. - *

    - * Does not close its output. (The output can accumulate more elements.) - * @param in a File. - * @param out a JarOutputStream. - * @throws IOException if an error is encountered. - */ - void unpack(File in, JarOutputStream out) throws IOException; - } - - // Private stuff.... - - private static final String PACK_PROVIDER = "java.util.jar.Pack200.Packer"; - private static final String UNPACK_PROVIDER = "java.util.jar.Pack200.Unpacker"; - - private static Class packerImpl; - private static Class unpackerImpl; - - private static synchronized Object newInstance(String prop) { - String implName = "(unknown)"; - try { - Class impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl; - if (impl == null) { - // The first time, we must decide which class to use. - implName = GetPropertyAction.privilegedGetProperty(prop,""); - if (implName != null && !implName.isEmpty()) - impl = Class.forName(implName); - else if (PACK_PROVIDER.equals(prop)) - impl = com.sun.java.util.jar.pack.PackerImpl.class; - else - impl = com.sun.java.util.jar.pack.UnpackerImpl.class; - } - // We have a class. Now instantiate it. - @SuppressWarnings("deprecation") - Object result = impl.newInstance(); - return result; - } catch (ClassNotFoundException e) { - throw new Error("Class not found: " + implName + - ":\ncheck property " + prop + - " in your properties file.", e); - } catch (InstantiationException e) { - throw new Error("Could not instantiate: " + implName + - ":\ncheck property " + prop + - " in your properties file.", e); - } catch (IllegalAccessException e) { - throw new Error("Cannot access class: " + implName + - ":\ncheck property " + prop + - " in your properties file.", e); - } - } - -} diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java index 3bb3b8b4022..fa940da2ff4 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java @@ -111,12 +111,6 @@ void process(Main jartool, String opt, String arg) { jartool.vflag = true; } }, - new Option(false, OptionType.CREATE, "--normalize", "-n") { - void process(Main jartool, String opt, String arg) { - jartool.nflag = true; - } - boolean isExtra() { return true; } - }, new Option(true, OptionType.CREATE_UPDATE, "--main-class", "-e") { void process(Main jartool, String opt, String arg) { jartool.ename = arg; diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index dfc6366401f..66e05f4d688 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -150,7 +150,7 @@ public int hashCode() { * pflag: preserve/don't strip leading slash and .. component from file name * dflag: print module descriptor */ - boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag; + boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, pflag, dflag; boolean suppressDeprecateMsg = false; @@ -318,34 +318,6 @@ public synchronized boolean run(String args[]) { try (OutputStream out = new FileOutputStream(tmpFile)) { create(new BufferedOutputStream(out, 4096), manifest); } - if (nflag) { - if (!suppressDeprecateMsg) { - warn(formatMsg("warn.flag.is.deprecated", "-n")); - } - File packFile = createTemporaryFile(tmpbase, ".pack"); - try { - java.util.jar.Pack200.Packer packer = java.util.jar.Pack200.newPacker(); - Map p = packer.properties(); - p.put(java.util.jar.Pack200.Packer.EFFORT, "1"); // Minimal effort to conserve CPU - try (JarFile jarFile = new JarFile(tmpFile.getCanonicalPath()); - OutputStream pack = new FileOutputStream(packFile)) - { - packer.pack(jarFile, pack); - } - if (tmpFile.exists()) { - tmpFile.delete(); - } - tmpFile = createTemporaryFile(tmpbase, ".jar"); - try (OutputStream out = new FileOutputStream(tmpFile); - JarOutputStream jos = new JarOutputStream(out)) - { - java.util.jar.Pack200.Unpacker unpacker = java.util.jar.Pack200.newUnpacker(); - unpacker.unpack(packFile, jos); - } - } finally { - Files.deleteIfExists(packFile.toPath()); - } - } validateAndClose(tmpFile); } else if (uflag) { File inputFile = null; @@ -587,9 +559,6 @@ boolean parseArgs(String args[]) { rootjar = args[count++]; iflag = true; break; - case 'n': - nflag = true; - break; case 'e': ename = args[count++]; break; diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties index 4f75242c02e..749fd0aa023 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties @@ -172,8 +172,6 @@ Options:\n\ \ \ -v generate verbose output on standard output\n\ \ \ -f specify archive file name\n\ \ \ -m include manifest information from specified manifest file\n\ -\ \ -n perform Pack200 normalization after creating a new archive,\n\ -\ \ this option is deprecated, and is planned for removal in a future JDK release\n\ \ \ -e specify application entry point for stand-alone application \n\ \ \ bundled into an executable jar file\n\ \ \ -0 store only; use no ZIP compression\n\ diff --git a/src/jdk.pack/share/classes/module-info.java b/src/jdk.pack/share/classes/module-info.java deleted file mode 100644 index d4952a50dec..00000000000 --- a/src/jdk.pack/share/classes/module-info.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * Defines tools for transforming a JAR file into a compressed pack200 file - * and transforming a packed file into a JAR file, including the - * {@index pack200 pack200 tool} and - * {@index unpack200 unpack200 tool} tools. - * - * @toolGuide pack200 - * @toolGuide unpack200 - * - * @moduleGraph - * @deprecated This module is deprecated, and is planned for removal in a - * future release. - * @since 9 - */ -@Deprecated(since="11", forRemoval=true) -module jdk.pack { -} diff --git a/src/jdk.pack/share/man/pack200.1 b/src/jdk.pack/share/man/pack200.1 deleted file mode 100644 index 31321c34487..00000000000 --- a/src/jdk.pack/share/man/pack200.1 +++ /dev/null @@ -1,357 +0,0 @@ -.\" Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. -.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -.\" -.\" This code is free software; you can redistribute it and/or modify it -.\" under the terms of the GNU General Public License version 2 only, as -.\" published by the Free Software Foundation. -.\" -.\" This code is distributed in the hope that it will be useful, but WITHOUT -.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -.\" version 2 for more details (a copy is included in the LICENSE file that -.\" accompanied this code). -.\" -.\" You should have received a copy of the GNU General Public License version -.\" 2 along with this work; if not, write to the Free Software Foundation, -.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -.\" -.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -.\" or visit www.oracle.com if you need additional information or have any -.\" questions. -.\" -.\" Automatically generated by Pandoc 2.3.1 -.\" -.TH "PACK200" "1" "2018" "JDK 13" "JDK Commands" -.hy -.SH NAME -.PP -pack200 \- transform a Java Archive (JAR) file into a compressed pack200 -file with the Java gzip compressor -.SH SYNOPSIS -.PP -\f[CB]pack200\f[R] [\f[I]\-opt...\f[R] | \f[I]\-\-option=value\f[R]] -\f[I]x.pack[.gz]\f[R] \f[I]JAR\-file\f[R] -.TP -.B \f[I]\-opt...\f[R] | \f[I]\-\-option=value\f[R] -Options can be in any order. -The last option on the command line or in a properties file supersedes -all previously specified options. -See \f[B]Options for the pack200 Command\f[R]. -.RS -.RE -.TP -.B \f[I]x.pack[.gz]\f[R] -Name of the output file. -.RS -.RE -.TP -.B \f[I]JAR\-file\f[R] -Name of the input file. -.RS -.RE -.SH DESCRIPTION -.PP -The \f[CB]pack200\f[R] command is a Java application that transforms a JAR -file into a compressed \f[CB]pack200\f[R] file with the Java gzip -compressor. -This command packages a JAR file into a compressed \f[CB]pack200\f[R] file -for web deployment. -The \f[CB]pack200\f[R] files are highly compressed files that can be -directly deployed to save bandwidth and reduce download time. -.PP -Typical usage is shown in the following example, where -\f[CB]myarchive.pack.gz\f[R] is produced with the default \f[CB]pack200\f[R] -command settings: -.RS -.PP -\f[CB]pack200\ myarchive.pack.gz\ myarchive.jar\f[R] -.RE -.PP -\f[B]Note:\f[R] -.PP -This command shouldn\[aq]t be confused with \f[CB]pack\f[R]. -The \f[CB]pack\f[R] and \f[CB]pack200\f[R] commands are separate products. -The Java SE API Specification provided with the JDK is the superseding -authority, when there are discrepancies. -.SH EXIT STATUS -.PP -The following exit values are returned: 0 for successful completion and -a number greater than 0 when an error occurs. -.SH OPTIONS FOR THE PACK200 COMMAND -.PP -The \f[CB]pack200\f[R] command has several options to fine\-tune and set -the compression engine. -The typical usage is shown in the following example, where -\f[CB]myarchive.pack.gz\f[R] is produced with the default \f[CB]pack200\f[R] -command settings: -.RS -.PP -\f[CB]pack200\ myarchive.pack.gz\ myarchive.jar\f[R] -.RE -.TP -.B \f[CB]\-r\f[R] or \f[CB]\-\-repack\f[R] -Produces a JAR file by packing and unpacking a JAR file. -The resulting file can be used as an input to the \f[CB]jarsigner\f[R] -tool. -The following example packs and unpacks the myarchive.jar file: -.RS -.RS -.PP -\f[CB]pack200\ \-\-repack\ myarchive\-packer.jar\ myarchive.jar\f[R] -.RE -.RS -.PP -\f[CB]pack200\ \-\-repack\ myarchive.jar\f[R] -.RE -.RE -.TP -.B \f[CB]\-g\f[R] or\f[CB]\-\-no\-gzip\f[R] -Produces a \f[CB]pack200\f[R] file. -With this option, a suitable compressor must be used, and the target -system must use a corresponding decompresser. -.RS -.RS -.PP -\f[CB]pack200\ \-\-no\-gzip\ myarchive.pack\ myarchive.jar\f[R] -.RE -.RE -.TP -.B \f[CB]\-\-gzip\f[R] -(Default) Post\-compresses the pack output with \f[CB]gzip\f[R]. -.RS -.RE -.TP -.B \f[CB]\-G\f[R] or \f[CB]\-\-strip\-debug\f[R] -Strips debugging attributes from the output. -These include \f[CB]SourceFile\f[R], \f[CB]LineNumberTable\f[R], -\f[CB]LocalVariableTable\f[R] and \f[CB]LocalVariableTypeTable\f[R]. -Removing these attributes reduces the size of both downloads and -installations, also reduces the usefulness of debuggers. -.RS -.RE -.TP -.B \f[CB]\-\-keep\-file\-order\f[R] -Preserves the order of files in the input file. -This is the default behavior. -.RS -.RE -.TP -.B \f[CB]\-O\f[R] or\f[CB]\-\-no\-keep\-file\-order\f[R] -Reorders and transmits all elements. -The packer can also remove JAR directory names to reduce the download -size. -However, certain JAR file optimizations, such as indexing, might not -work correctly. -.RS -.RE -.TP -.B \f[CB]\-S\f[R]\f[I]N\f[R] or \f[CB]\-\-segment\-limit=\f[R]\f[I]N\f[R] -The value is the estimated target size \f[I]N\f[R] (in bytes) of each -archive segment. -If a single input file requires more than \f[I]N\f[R] bytes, then its own -archive segment is provided. -As a special case, a value of \f[CB]\-1\f[R] produces a single large -segment with all input files, while a value of 0 produces one segment -for each class. -Larger archive segments result in less fragmentation and better -compression, but processing them requires more memory. -.RS -.PP -The size of each segment is estimated by counting the size of each input -file to be transmitted in the segment with the size of its name and -other transmitted properties. -.PP -The default is \f[CB]\-1\f[R], which means that the packer creates a -single segment output file. -In cases where extremely large output files are generated, users are -strongly encouraged to use segmenting or break up the input file into -smaller JAR file. -.PP -A 10 MB JAR packed without this limit typically packs about 10 percent -smaller, but the packer might require a larger Java heap (about 10 times -the segment limit). -.RE -.TP -.B \f[CB]\-E\f[R]\f[I]value\f[R] or \f[CB]\-\-effort=\f[R]\f[I]value\f[R] -If the value is set to a single decimal digit, then the packer uses the -indicated amount of effort in compressing the archive. -Level 1 might produce somewhat larger size and faster compression speed, -while level 9 takes much longer, but can produce better compression. -The special value 0 instructs the \f[CB]pack200\f[R] command to copy -through the original JAR file directly with no compression. -The JSR 200 standard requires any unpacker to understand this special -case as a pass\-through of the entire archive. -.RS -.PP -The default is 5, to invest a modest amount of time to produce -reasonable compression. -.RE -.TP -.B \f[CB]\-H\f[R]\f[I]value\f[R] or \f[CB]\-\-deflate\-hint=\f[R]\f[I]value\f[R] -Overrides the default, which preserves the input information, but can -cause the transmitted archive to be larger. -The possible values are: \f[CB]true\f[R], \f[CB]false\f[R], or -\f[CB]keep\f[R]. -.RS -.PP -If the \f[CB]value\f[R] is \f[CB]true\f[R] or false, then the -\f[CB]packer200\f[R] command sets the deflation hint accordingly in the -output archive and doesn\[aq]t transmit the individual deflation hints -of archive elements. -.PP -The \f[CB]keep\f[R] value preserves deflation hints observed in the input -JAR. -This is the default. -.RE -.TP -.B \f[CB]\-m\f[R]\f[I]value\f[R] or \f[CB]\-\-modification\-time=\f[R]\f[I]value\f[R] -The possible values are \f[CB]latest\f[R] and \f[CB]keep\f[R]. -.RS -.PP -If the value is \f[CB]latest\f[R], then the packer attempts to determine -the latest modification time, among all the available entries in the -original archive, or the latest modification time of all the available -entries in that segment. -This single value is transmitted as part of the segment and applied to -all the entries in each segment. -This can marginally decrease the transmitted size of the archive at the -expense of setting all installed files to a single date. -.PP -If the value is \f[CB]keep\f[R], then modification times observed in the -input JAR are preserved. -This is the default. -.RE -.TP -.B \f[CB]\-P\f[R]\f[I]file\f[R] or \f[CB]\-\-pass\-file=\f[R]\f[I]file\f[R] -Indicates that a file should be passed through bytewise with no -compression. -By repeating the option, multiple files can be specified. -There is no path name transformation, except that the system file -separator is replaced by the JAR file separator forward slash (/). -The resulting file names must match exactly as strings with their -occurrences in the JAR file. -If \f[I]file\f[R] is a directory name, then all files under that -directory are passed. -.RS -.RE -.TP -.B \f[CB]\-U\f[R]\f[I]action\f[R] or \f[CB]\-\-unknown\-attribute=\f[R]\f[I]action\f[R] -Overrides the default behavior, which means that the class file that -contains the unknown attribute is passed through with the specified -\f[I]action\f[R]. -The possible values for actions are \f[CB]error\f[R], \f[CB]strip\f[R], or -\f[CB]pass\f[R]. -.RS -.PP -If the value is \f[CB]error\f[R], then the entire \f[CB]pack200\f[R] command -operation fails with a suitable explanation. -.PP -If the value is \f[CB]strip\f[R], then the attribute is dropped. -Removing the required Java Virtual Machine (JVM) attributes can cause -class loader failures. -.PP -If the value is \f[CB]pass\f[R], then the entire class is transmitted as -though it is a resource. -.RE -.TP -.B \f[CB]\-C\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] or \f[CB]\-\-class\-attribute=\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] -(user\-defined attribute) See the description for -\f[CB]\-D\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R]. -.RS -.RE -.TP -.B \f[CB]\-F\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] or \f[CB]\-\-field\-attribute=\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] -(user\-defined attribute) See the description for -\f[CB]\-D\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R]. -.RS -.RE -.TP -.B \f[CB]\-M\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] or \f[CB]\-\-method\-attribute=\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] -(user\-defined attribute) See the description for -\f[CB]\-D\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R]. -.RS -.RE -.TP -.B \f[CB]\-D\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] or \f[CB]\-\-code\-attribute=\f[R]\f[I]attribute\-name\f[R]\f[CB]=\f[R]\f[I]layout\f[R] -(user\-defined attribute) The attribute layout can be specified for a -class entity, such as \f[CB]class\-attribute\f[R], -\f[CB]field\-attribute\f[R], \f[CB]method\-attribute\f[R], and -\f[CB]code\-attribute\f[R]. -The \f[I]attribute\-name\f[R] is the name of the attribute for which the -layout or action is being defined. -The possible values for \f[I]action\f[R] are -\f[I]some\-layout\-string\f[R], \f[CB]error\f[R], \f[CB]strip\f[R], -\f[CB]pass\f[R]. -.RS -.PP -\f[I]some\-layout\-string\f[R]: The layout language is defined in the JSR -200 specification, for example: -\f[CB]\-\-class\-attribute=SourceFile=RUH\f[R]. -.PP -If the value is \f[CB]error\f[R], then the \f[CB]pack200\f[R] operation -fails with an explanation. -.PP -If the value is \f[CB]strip\f[R], then the attribute is removed from the -output. -Removing JVM\-required attributes can cause class loader failures. -For example, \f[CB]\-\-class\-attribute=CompilationID=pass\f[R] causes the -class file that contains this attribute to be passed through without -further action by the packer. -.PP -If the value is \f[CB]pass\f[R], then the entire class is transmitted as -though it\[aq]s a resource. -.RE -.TP -.B \f[CB]\-f\f[R]\f[I]pack.properties\f[R] or \f[CB]\-\-config\-file=\f[R]\f[I]pack.properties\f[R] -Indicates a configuration file, containing Java properties to initialize -the packer, can be specified on the command line. -.RS -.IP -.nf -\f[CB] -pack200\ \-f\ pack.properties\ myarchive.pack.gz\ myarchive.jar -more\ pack.properties -#\ Generic\ properties\ for\ the\ packer. -modification.time=latest -deflate.hint=false -keep.file.order=false -#\ This\ option\ will\ cause\ the\ files\ bearing\ new\ attributes\ to -#\ be\ reported\ as\ an\ error\ rather\ than\ passed\ uncompressed. -unknown.attribute=error -#\ Change\ the\ segment\ limit\ to\ be\ unlimited. -segment.limit=\-1 -\f[R] -.fi -.RE -.TP -.B \f[CB]\-v\f[R] or \f[CB]\-\-verbose\f[R] -Outputs minimal messages. -Multiple specification of this option will create more verbose messages. -.RS -.RE -.TP -.B \f[CB]\-q\f[R] or \f[CB]\-\-quiet\f[R] -Specifies quiet operation with no messages. -.RS -.RE -.TP -.B \f[CB]\-l\f[R]\f[I]filename\f[R] or \f[CB]\-\-log\-file=\f[R]\f[I]filename\f[R] -Specifies a log file to output messages. -.RS -.RE -.TP -.B \f[CB]\-?\f[R], \f[CB]\-h\f[R], or\f[CB]\-\-help\f[R] -Prints help information about this command. -.RS -.RE -.TP -.B \f[CB]\-V\f[R] or \f[CB]\-\-version\f[R] -Prints version information about this command. -.RS -.RE -.TP -.B \f[CB]\-J\f[R]\f[I]option\f[R] -Passes the specified \f[I]option\f[R] to the Java Virtual Machine. -For example, \f[CB]\-J\-Xms48m\f[R] sets the startup memory to 48 MB. -.RS -.RE diff --git a/src/jdk.pack/share/man/unpack200.1 b/src/jdk.pack/share/man/unpack200.1 deleted file mode 100644 index 376ed88009b..00000000000 --- a/src/jdk.pack/share/man/unpack200.1 +++ /dev/null @@ -1,126 +0,0 @@ -.\" Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. -.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -.\" -.\" This code is free software; you can redistribute it and/or modify it -.\" under the terms of the GNU General Public License version 2 only, as -.\" published by the Free Software Foundation. -.\" -.\" This code is distributed in the hope that it will be useful, but WITHOUT -.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -.\" version 2 for more details (a copy is included in the LICENSE file that -.\" accompanied this code). -.\" -.\" You should have received a copy of the GNU General Public License version -.\" 2 along with this work; if not, write to the Free Software Foundation, -.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -.\" -.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -.\" or visit www.oracle.com if you need additional information or have any -.\" questions. -.\" -.\" Automatically generated by Pandoc 2.3.1 -.\" -.TH "UNPACK200" "1" "2018" "JDK 13" "JDK Commands" -.hy -.SH NAME -.PP -unpack200 \- transform a packed file into a JAR file for web deployment -.SH SYNOPSIS -.PP -\f[CB]unpack200\f[R] [\f[I]options\f[R]] \f[I]input\-file\f[R] -\f[I]JAR\-file\f[R] -.TP -.B \f[I]options\f[R] -The command\-line options. -See \f[B]Options for the unpack200 Command\f[R]. -.RS -.RE -.TP -.B \f[I]input\-file\f[R] -Name of the input file, which can be a \f[CB]pack200\ gzip\f[R] file or a -\f[CB]pack200\f[R] file. -The input can also be a JAR file produced by \f[CB]pack200\f[R] with an -effort of \f[CB]0\f[R], in which case the contents of the input file are -copied to the output JAR file with the \f[CB]pack200\f[R] marker. -.RS -.RE -.TP -.B \f[I]JAR\-file\f[R] -Name of the output JAR file. -.RS -.RE -.SH DESCRIPTION -.PP -The \f[CB]unpack200\f[R] command is a native implementation that -transforms a packed file produced by the \f[CB]pack200\f[R] into a JAR -file for web deployment. -An example of typical usage follows. -In the following example, the \f[CB]myarchive.jar\f[R] file is produced -from \f[CB]myarchive.pack.gz\f[R] with the default \f[CB]unpack200\f[R] -command settings. -.RS -.PP -\f[CB]unpack200\ myarchive.pack.gz\ myarchive.jar\f[R] -.RE -.SH OPTIONS FOR THE UNPACK200 COMMAND -.TP -.B \f[CB]\-H\f[R]\f[I]value\f[R] or \f[CB]\-\-deflate\-hint=\f[R]\f[I]value\f[R] -Sets the deflation to be \f[CB]true\f[R], \f[CB]false\f[R], or \f[CB]keep\f[R] -on all entries within a JAR file. -The default mode is \f[CB]keep\f[R]. -If the value is \f[CB]true\f[R] or \f[CB]false\f[R], then the -\f[CB]\-\-deflate=hint\f[R] option overrides the default behavior and sets -the deflation mode on all entries within the output JAR file. -.RS -.RE -.TP -.B \f[CB]\-r\f[R] or \f[CB]\-\-remove\-pack\-file\f[R] -Removes the input pack file. -.RS -.RE -.TP -.B \f[CB]\-v\f[R] or \f[CB]\-\-verbose\f[R] -Displays minimal messages. -Multiple specifications of this option displays more verbose messages. -.RS -.RE -.TP -.B \f[CB]\-q\f[R] or \f[CB]\-\-quiet\f[R] -Specifies quiet operation with no messages. -.RS -.RE -.TP -.B \f[CB]\-l\f[R] \f[I]filename\f[R] or \f[CB]\-\-log\-file=\f[R]\f[I]filename\f[R] -Specifies a log file where output messages are logged. -.RS -.RE -.TP -.B \f[CB]\-?\f[R] or \f[CB]\-h\f[R] or \f[CB]\-\-help\f[R] -Prints help information about the \f[CB]unpack200\f[R] command. -.RS -.RE -.TP -.B \f[CB]\-V\f[R] or \f[CB]\-\-version\f[R] -Prints version information about the \f[CB]unpack200\f[R] command. -.RS -.RE -.TP -.B \f[CB]\-J\f[R]\f[I]option\f[R] -Passes \f[I]option\f[R] to the Java Virtual Machine, where -\f[CB]option\f[R] is one of the options described on the reference page -for the Java application launcher. -For example, \f[CB]\-J\-Xms48m\f[R] sets the startup memory to 48 MB. -.RS -.RE -.SH NOTES -.PP -This command shouldn\[aq]t be confused with the \f[CB]unpack\f[R] command. -They\[aq]re distinctly separate products. -.PP -The Java SE API Specification provided with the JDK is the superseding -authority in case of discrepancies. -.SH EXIT STATUS -.PP -The following exit values are returned: 0 for successful completion, and -a value that is greater than 0 when an error occurred. diff --git a/src/jdk.pack/share/native/common-unpack/bands.cpp b/src/jdk.pack/share/native/common-unpack/bands.cpp deleted file mode 100644 index b7799f919c6..00000000000 --- a/src/jdk.pack/share/native/common-unpack/bands.cpp +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// -*- C++ -*- -// Small program for unpacking specially compressed Java packages. -// John R. Rose - -#include - -#include -#include -#include -#include - -#include "defines.h" -#include "bytes.h" -#include "utils.h" -#include "coding.h" -#include "bands.h" - -#include "constants.h" -#include "unpack.h" - -inline void band::abort(const char* msg) { u->abort(msg); } -inline bool band::aborting() { return u->aborting(); } - -void band::readData(int expectedLength) { - CHECK; - assert(expectedLength >= 0); - assert(vs[0].cmk == cmk_ERROR); - if (expectedLength != 0) { - assert(length == 0); - length = expectedLength; - } - if (length == 0) { - assert((rplimit = cm.vs0.rp = u->rp) != null); - return; - } - assert(length > 0); - - bool is_BYTE1 = (defc->spec == BYTE1_spec); - - if (is_BYTE1) { - // No possibility of coding change. Sizing is exact. - u->ensure_input(length); - } else { - // Make a conservatively generous estimate of band size in bytes. - // Assume B == 5 everywhere. - // Assume awkward pop with all {U} values (2*5 per value) - jlong generous = (jlong) length * (B_MAX*3+1) + C_SLOP; - u->ensure_input(generous); - } - - // Read one value to see what it might be. - int XB = _meta_default; - int cp1 = 0, cp2 = 0; - if (!is_BYTE1) { - // must be a variable-length coding - assert(defc->B() > 1 && defc->L() > 0); - // must have already read from previous band: - assert(bn >= BAND_LIMIT || bn <= 0 - || bn == e_cp_Utf8_big_chars - || endsWith(name, "_lo") // preceded by _hi conditional band - || bn == e_file_options // preceded by conditional band - || u->rp == u->all_bands[bn-1].maxRP() - || u->all_bands[bn-1].defc == null); - - value_stream xvs; - coding* valc = defc; - if (valc->D() != 0) { - valc = coding::findBySpec(defc->B(), defc->H(), defc->S()); - assert(!valc->isMalloc); - } - xvs.init(u->rp, u->rplimit, valc); - CHECK; - int X = xvs.getInt(); - if (valc->S() != 0) { - assert(valc->min <= -256); - XB = -1-X; - } else { - int L = valc->L(); - assert(valc->max >= L+255); - XB = X-L; - } - if (0 <= XB && XB < 256) { - // Skip over the escape value. - u->rp = xvs.rp; - cp1 = 1; - } else { - // No, it's still default. - XB = _meta_default; - } - } - - if (XB <= _meta_canon_max) { - byte XB_byte = (byte) XB; - byte* XB_ptr = &XB_byte; - cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null); - CHECK; - } else { - NOT_PRODUCT(byte* meta_rp0 = u->meta_rp); - assert(u->meta_rp != null); - // Scribble the initial byte onto the band. - byte* save_meta_rp = --u->meta_rp; - byte save_meta_xb = (*save_meta_rp); - (*save_meta_rp) = (byte) XB; - cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, null); - (*save_meta_rp) = save_meta_xb; // put it back, just to be tidy - NOT_PRODUCT(cp2 = (int)(u->meta_rp - meta_rp0)); - } - rplimit = u->rp; - - rewind(); - -#ifndef PRODUCT - PRINTCR((3,"readFrom %s at %p [%d values, %d bytes, cp=%d/%d]", - (name?name:"(band)"), minRP(), length, size(), cp1, cp2)); - if (u->verbose_bands || u->verbose >= 4) dump(); - - if (ix != null && u->verbose != 0 && length > 0) { - // Check referential integrity early, for easier debugging. - band saved = (*this); // save state - for (int i = 0; i < length; i++) { - int n = vs[0].getInt() - nullOK; - entry *ref = ix->get(n); - assert(ref != null || n == -1); - } - (*this) = saved; - } -#endif -} - -#ifndef PRODUCT -void band::dump() { - band saved = (*this); // save state - const char* b_name = name; - char b_name_buf[100]; - if (b_name == null) { - char* bp = &b_name_buf[0]; - b_name = bp; - sprintf(bp, "#%d/%d", bn, le_kind); bp += strlen(bp); - if (le_bci != 0) { sprintf(bp, "/bci%d", le_bci); bp += strlen(bp); } - if (le_back != 0) { sprintf(bp, "/back%d", le_back); bp += strlen(bp); } - if (le_len != 0) { sprintf(bp, "/len%d", le_len); bp += strlen(bp); } - } - fprintf(u->errstrm, "band %s[%d]%s", b_name, length, (length==0?"\n":" {")); - if (length > 0) { - for (int i = 0; i < length; i++) { - const char* eol = (length > 10 && i % 10 == 0) ? "\n" : " "; - fprintf(u->errstrm, "%s%d", eol, vs[0].getInt()); - } - fprintf(u->errstrm, " }\n"); - } - (*this) = saved; -} -#endif - -void band::setIndex(cpindex* ix_) { - assert(ix_ == null || ixTag == ix_->ixTag); - ix = ix_; -} -void band::setIndexByTag(byte tag) { - setIndex(u->cp.getIndex(tag)); -} - -entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) { - CHECK_0; - if (ix_ == NULL) { - abort("no index"); - return NULL; - } - assert(ix_->ixTag == ixTag - || ((ixTag == CONSTANT_All || - ixTag == CONSTANT_LoadableValue || - ixTag == CONSTANT_AnyMember) - || (ixTag == CONSTANT_FieldSpecific && - ix_->ixTag >= CONSTANT_Integer && - ix_->ixTag <= CONSTANT_String)) - ); - int n = vs[0].getInt() - nullOK; - // Note: band-local nullOK means null encodes as 0. - // But nullOKwithCaller means caller is willing to tolerate a null. - entry *ref = ix_->get(n); - if (ref == null && !(nullOKwithCaller && n == -1)) - abort(n == -1 ? "null ref" : "bad ref"); - return ref; -} - -jlong band::getLong(band& lo_band, bool have_hi) { - band& hi_band = (*this); - assert(lo_band.bn == hi_band.bn + 1); - uint lo = lo_band.getInt(); - if (!have_hi) { - assert(hi_band.length == 0); - return makeLong(0, lo); - } - uint hi = hi_band.getInt(); - return makeLong(hi, lo); -} - -int band::getIntTotal() { - CHECK_0; - if (length == 0) return 0; - if (total_memo > 0) return total_memo-1; - int total = getInt(); - // overflow checks require that none of the addends are <0, - // and that the partial sums never overflow (wrap negative) - if (total < 0) { - abort("overflow detected"); - return 0; - } - for (int k = length-1; k > 0; k--) { - int prev_total = total; - total += vs[0].getInt(); - if (total < prev_total) { - abort("overflow detected"); - return 0; - } - } - rewind(); - total_memo = total+1; - return total; -} - -int band::getIntCount(int tag) { - CHECK_0; - if (length == 0) return 0; - if (tag >= HIST0_MIN && tag <= HIST0_MAX) { - if (hist0 == null) { - // Lazily calculate an approximate histogram. - hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN)+1); - CHECK_0; - for (int k = length; k > 0; k--) { - int x = vs[0].getInt(); - if (x >= HIST0_MIN && x <= HIST0_MAX) - hist0[x - HIST0_MIN] += 1; - } - rewind(); - } - return hist0[tag - HIST0_MIN]; - } - int total = 0; - for (int k = length; k > 0; k--) { - total += (vs[0].getInt() == tag) ? 1 : 0; - } - rewind(); - return total; -} - -#define INDEX_INIT(tag, nullOK, subindex) \ - ((tag) + (subindex)*SUBINDEX_BIT + (nullOK)*256) - -#define INDEX(tag) INDEX_INIT(tag, 0, 0) -#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0) -#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1) -#define NO_INDEX 0 - -struct band_init { - int bn; - const char* name; - int defc; - int index; -}; - -#define BAND_INIT(name, cspec, ix) \ - { e_##name, #name, /*debug only*/ \ - cspec, ix } - -const band_init all_band_inits[BAND_LIMIT+1] = { -//BAND_INIT(archive_magic, BYTE1_spec, 0), -//BAND_INIT(archive_header, UNSIGNED5_spec, 0), -//BAND_INIT(band_headers, BYTE1_spec, 0), - BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), - BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0), - BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), - BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0), - BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), - BAND_INIT(cp_Int, UDELTA5_spec, 0), - BAND_INIT(cp_Float, UDELTA5_spec, 0), - BAND_INIT(cp_Long_hi, UDELTA5_spec, 0), - BAND_INIT(cp_Long_lo, DELTA5_spec, 0), - BAND_INIT(cp_Double_hi, UDELTA5_spec, 0), - BAND_INIT(cp_Double_lo, DELTA5_spec, 0), - BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), - BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), - BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), - BAND_INIT(cp_MethodHandle_refkind, DELTA5_spec, 0), - BAND_INIT(cp_MethodHandle_member, UDELTA5_spec, INDEX(CONSTANT_AnyMember)), - BAND_INIT(cp_MethodType, UDELTA5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(cp_BootstrapMethod_ref, DELTA5_spec, INDEX(CONSTANT_MethodHandle)), - BAND_INIT(cp_BootstrapMethod_arg_count, UDELTA5_spec, 0), - BAND_INIT(cp_BootstrapMethod_arg, DELTA5_spec, INDEX(CONSTANT_LoadableValue)), - BAND_INIT(cp_InvokeDynamic_spec, DELTA5_spec, INDEX(CONSTANT_BootstrapMethod)), - BAND_INIT(cp_InvokeDynamic_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), - BAND_INIT(attr_definition_headers, BYTE1_spec, 0), - BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(ic_flags, UNSIGNED5_spec, 0), - BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)), - BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), - BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(class_interface_count, DELTA5_spec, 0), - BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(class_field_count, DELTA5_spec, 0), - BAND_INIT(class_method_count, DELTA5_spec, 0), - BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)), - BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0), - BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0), - BAND_INIT(field_attr_count, UNSIGNED5_spec, 0), - BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0), - BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0), - BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_FieldSpecific)), - BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(field_metadata_bands, -1, -1), - BAND_INIT(field_attr_bands, -1, -1), - BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)), - BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0), - BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0), - BAND_INIT(method_attr_count, UNSIGNED5_spec, 0), - BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0), - BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0), - BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0), - BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(method_metadata_bands, -1, -1), - BAND_INIT(method_MethodParameters_NB, BYTE1_spec, 0), - BAND_INIT(method_MethodParameters_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), - BAND_INIT(method_MethodParameters_flag_FH, UNSIGNED5_spec, 0), - BAND_INIT(method_attr_bands, -1, -1), - BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0), - BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0), - BAND_INIT(class_attr_count, UNSIGNED5_spec, 0), - BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0), - BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0), - BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), - BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_NameandType)), - BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(class_metadata_bands, -1, -1), - BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0), - BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0), - BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), - BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), - BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0), - BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0), - BAND_INIT(class_attr_bands, -1, -1), - BAND_INIT(code_headers, BYTE1_spec, 0), - BAND_INIT(code_max_stack, UNSIGNED5_spec, 0), - BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0), - BAND_INIT(code_handler_count, UNSIGNED5_spec, 0), - BAND_INIT(code_handler_start_P, BCI5_spec, 0), - BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0), - BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0), - BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), - BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0), - BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0), - BAND_INIT(code_attr_count, UNSIGNED5_spec, 0), - BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0), - BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0), - BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0), - BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0), - BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0), - BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0), - BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0), - BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0), - BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), - BAND_INIT(code_StackMapTable_P, BCI5_spec, 0), - BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0), - BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0), - BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0), - BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0), - BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0), - BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0), - BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0), - BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0), - BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0), - BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0), - BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), - BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0), - BAND_INIT(code_attr_bands, -1, -1), - BAND_INIT(bc_codes, BYTE1_spec, 0), - BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), - BAND_INIT(bc_case_value, DELTA5_spec, 0), - BAND_INIT(bc_byte, BYTE1_spec, 0), - BAND_INIT(bc_short, DELTA5_spec, 0), - BAND_INIT(bc_local, UNSIGNED5_spec, 0), - BAND_INIT(bc_label, BRANCH5_spec, 0), - BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)), - BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)), - BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)), - BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)), - BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)), - BAND_INIT(bc_loadablevalueref, DELTA5_spec, INDEX(CONSTANT_LoadableValue)), - BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), - BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)), - BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)), - BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)), - BAND_INIT(bc_indyref, DELTA5_spec, INDEX(CONSTANT_InvokeDynamic)), - BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)), - BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)), - BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), - BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), - BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), - BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)), - BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), - BAND_INIT(bc_escsize, UNSIGNED5_spec, 0), - BAND_INIT(bc_escbyte, BYTE1_spec, 0), - BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), - BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), - BAND_INIT(file_size_lo, UNSIGNED5_spec, 0), - BAND_INIT(file_modtime, DELTA5_spec, 0), - BAND_INIT(file_options, UNSIGNED5_spec, 0), -//BAND_INIT(file_bits, BYTE1_spec, 0), - { 0, NULL, 0, 0 } -}; - -band* band::makeBands(unpacker* u) { - band* tmp_all_bands = U_NEW(band, BAND_LIMIT); - for (int i = 0; i < BAND_LIMIT; i++) { - assert((byte*)&all_band_inits[i+1] - < (byte*)all_band_inits+sizeof(all_band_inits)); - const band_init& bi = all_band_inits[i]; - band& b = tmp_all_bands[i]; - coding* defc = coding::findBySpec(bi.defc); - assert((defc == null) == (bi.defc == -1)); // no garbage, please - assert(defc == null || !defc->isMalloc); - assert(bi.bn == i); // band array consistent w/ band enum - b.init(u, i, defc); - if (bi.index > 0) { - b.nullOK = ((bi.index >> 8) & 1); - b.ixTag = (bi.index & 0xFF); - } -#ifndef PRODUCT - b.name = bi.name; -#endif - } - return tmp_all_bands; -} - -void band::initIndexes(unpacker* u) { - band* tmp_all_bands = u->all_bands; - for (int i = 0; i < BAND_LIMIT; i++) { - band* scan = &tmp_all_bands[i]; - uint tag = scan->ixTag; // Cf. #define INDEX(tag) above - if (tag != 0 && tag != CONSTANT_FieldSpecific && (tag & SUBINDEX_BIT) == 0) { - scan->setIndex(u->cp.getIndex(tag)); - } - } -} diff --git a/src/jdk.pack/share/native/common-unpack/bands.h b/src/jdk.pack/share/native/common-unpack/bands.h deleted file mode 100644 index c10b93d1888..00000000000 --- a/src/jdk.pack/share/native/common-unpack/bands.h +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// -*- C++ -*- -struct entry; -struct cpindex; -struct unpacker; - -struct band { - const char* name; - int bn; // band_number of this band - coding* defc; // default coding method - cpindex* ix; // CP entry mapping, if CPRefBand - byte ixTag; // 0 or 1; null is coded as (nullOK?0:-1) - byte nullOK; // 0 or 1; null is coded as (nullOK?0:-1) - int length; // expected # values - unpacker* u; // back pointer - - value_stream vs[2]; // source of values - coding_method cm; // method used for initial state of vs[0] - byte* rplimit; // end of band (encoded, transmitted) - - int total_memo; // cached value of getIntTotal, or -1 - int* hist0; // approximate. histogram - enum { HIST0_MIN = 0, HIST0_MAX = 255 }; // catches the usual cases - - // properties for attribute layout elements: - byte le_kind; // EK_XXX - byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO - byte le_back; // ==EF_BACK - byte le_len; // 0,1,2,4 (size in classfile), or call addr - band** le_body; // body of repl, union, call (null-terminated) - // Note: EK_CASE elements use hist0 to record union tags. - #define le_casetags hist0 - - band& nextBand() { return this[1]; } - band& prevBand() { return this[-1]; } - - void init(unpacker* u_, int bn_, coding* defc_) { - u = u_; - cm.u = u_; - bn = bn_; - defc = defc_; - } - void init(unpacker* u_, int bn_, int defcSpec) { - init(u_, bn_, coding::findBySpec(defcSpec)); - } - void initRef(int ixTag_ = 0, bool nullOK_ = false) { - ixTag = ixTag_; - nullOK = nullOK_; - setIndexByTag(ixTag); - } - - void expectMoreLength(int l) { - assert(length >= 0); // able to accept a length - assert((int)l >= 0); // no overflow - assert(rplimit == null); // readData not yet called - length += l; - assert(length >= l); // no overflow - } - - void setIndex(cpindex* ix_); - void setIndexByTag(byte tag); - - // Parse the band and its meta-coding header. - void readData(int expectedLength = 0); - - // Reset the band for another pass (Cf. Java Band.resetForSecondPass.) - void rewind() { - cm.reset(&vs[0]); - } - - byte* &curRP() { return vs[0].rp; } - byte* minRP() { return cm.vs0.rp; } - byte* maxRP() { return rplimit; } - size_t size() { return maxRP() - minRP(); } - - int getByte() { assert(ix == null); return vs[0].getByte(); } - int getInt() { assert(ix == null); return vs[0].getInt(); } - entry* getRefN() { return getRefCommon(ix, true); } - entry* getRef() { return getRefCommon(ix, false); } - entry* getRefUsing(cpindex* ix2) - { assert(ix == null); return getRefCommon(ix2, true); } - entry* getRefCommon(cpindex* ix, bool nullOK); - jlong getLong(band& lo_band, bool have_hi); - - static jlong makeLong(uint hi, uint lo) { - return ((julong)hi << 32) + (((julong)lo << 32) >> 32); - } - - int getIntTotal(); - int getIntCount(int tag); - - static band* makeBands(unpacker* u); - static void initIndexes(unpacker* u); - -#ifndef PRODUCT - void dump(); -#endif - - void abort(const char* msg = null); //{ u->abort(msg); } - bool aborting(); //{ return u->aborting(); } -}; - -extern band all_bands[]; - -#define BAND_LOCAL /* \ - band* band_temp = all_bands; \ - band* all_bands = band_temp */ - -// Band schema: -enum band_number { - //e_archive_magic, - //e_archive_header, - //e_band_headers, - - // constant pool contents - e_cp_Utf8_prefix, - e_cp_Utf8_suffix, - e_cp_Utf8_chars, - e_cp_Utf8_big_suffix, - e_cp_Utf8_big_chars, - e_cp_Int, - e_cp_Float, - e_cp_Long_hi, - e_cp_Long_lo, - e_cp_Double_hi, - e_cp_Double_lo, - e_cp_String, - e_cp_Class, - e_cp_Signature_form, - e_cp_Signature_classes, - e_cp_Descr_name, - e_cp_Descr_type, - e_cp_Field_class, - e_cp_Field_desc, - e_cp_Method_class, - e_cp_Method_desc, - e_cp_Imethod_class, - e_cp_Imethod_desc, - e_cp_MethodHandle_refkind, - e_cp_MethodHandle_member, - e_cp_MethodType, - e_cp_BootstrapMethod_ref, - e_cp_BootstrapMethod_arg_count, - e_cp_BootstrapMethod_arg, - e_cp_InvokeDynamic_spec, - e_cp_InvokeDynamic_desc, - - // bands which define transmission of attributes - e_attr_definition_headers, - e_attr_definition_name, - e_attr_definition_layout, - - // band for hardwired InnerClasses attribute (shared across the package) - e_ic_this_class, - e_ic_flags, - // These bands contain data only where flags sets ACC_IC_LONG_FORM: - e_ic_outer_class, - e_ic_name, - - // bands for carrying class schema information: - e_class_this, - e_class_super, - e_class_interface_count, - e_class_interface, - - // bands for class members - e_class_field_count, - e_class_method_count, - - e_field_descr, - e_field_flags_hi, - e_field_flags_lo, - e_field_attr_count, - e_field_attr_indexes, - e_field_attr_calls, - e_field_ConstantValue_KQ, - e_field_Signature_RS, - e_field_metadata_bands, - e_field_attr_bands, - - e_method_descr, - e_method_flags_hi, - e_method_flags_lo, - e_method_attr_count, - e_method_attr_indexes, - e_method_attr_calls, - e_method_Exceptions_N, - e_method_Exceptions_RC, - e_method_Signature_RS, - e_method_metadata_bands, - e_method_MethodParameters_NB, - e_method_MethodParameters_name_RUN, - e_method_MethodParameters_flag_FH, - e_method_attr_bands, - - e_class_flags_hi, - e_class_flags_lo, - e_class_attr_count, - e_class_attr_indexes, - e_class_attr_calls, - e_class_SourceFile_RUN, - e_class_EnclosingMethod_RC, - e_class_EnclosingMethod_RDN, - e_class_Signature_RS, - e_class_metadata_bands, - e_class_InnerClasses_N, - e_class_InnerClasses_RC, - e_class_InnerClasses_F, - e_class_InnerClasses_outer_RCN, - e_class_InnerClasses_name_RUN, - e_class_ClassFile_version_minor_H, - e_class_ClassFile_version_major_H, - e_class_attr_bands, - - e_code_headers, - e_code_max_stack, - e_code_max_na_locals, - e_code_handler_count, - e_code_handler_start_P, - e_code_handler_end_PO, - e_code_handler_catch_PO, - e_code_handler_class_RCN, - - // code attributes - e_code_flags_hi, - e_code_flags_lo, - e_code_attr_count, - e_code_attr_indexes, - e_code_attr_calls, - e_code_StackMapTable_N, - e_code_StackMapTable_frame_T, - e_code_StackMapTable_local_N, - e_code_StackMapTable_stack_N, - e_code_StackMapTable_offset, - e_code_StackMapTable_T, - e_code_StackMapTable_RC, - e_code_StackMapTable_P, - e_code_LineNumberTable_N, - e_code_LineNumberTable_bci_P, - e_code_LineNumberTable_line, - e_code_LocalVariableTable_N, - e_code_LocalVariableTable_bci_P, - e_code_LocalVariableTable_span_O, - e_code_LocalVariableTable_name_RU, - e_code_LocalVariableTable_type_RS, - e_code_LocalVariableTable_slot, - e_code_LocalVariableTypeTable_N, - e_code_LocalVariableTypeTable_bci_P, - e_code_LocalVariableTypeTable_span_O, - e_code_LocalVariableTypeTable_name_RU, - e_code_LocalVariableTypeTable_type_RS, - e_code_LocalVariableTypeTable_slot, - e_code_attr_bands, - - // bands for bytecodes - e_bc_codes, - // remaining bands provide typed opcode fields required by the bc_codes - - e_bc_case_count, - e_bc_case_value, - e_bc_byte, - e_bc_short, - e_bc_local, - e_bc_label, - - // ldc* operands: - e_bc_intref, - e_bc_floatref, - e_bc_longref, - e_bc_doubleref, - e_bc_stringref, - e_bc_loadablevalueref, - e_bc_classref, - - e_bc_fieldref, - e_bc_methodref, - e_bc_imethodref, - e_bc_indyref, - - // _self_linker_op family - e_bc_thisfield, - e_bc_superfield, - e_bc_thismethod, - e_bc_supermethod, - - // bc_invokeinit family: - e_bc_initref, - - // bytecode escape sequences - e_bc_escref, - e_bc_escrefsize, - e_bc_escsize, - e_bc_escbyte, - - // file attributes and contents - e_file_name, - e_file_size_hi, - e_file_size_lo, - e_file_modtime, - e_file_options, - //e_file_bits, // handled specially as an appendix - - BAND_LIMIT -}; - -// Symbolic names for bands, as if in a giant global struct: -//#define archive_magic all_bands[e_archive_magic] -//#define archive_header all_bands[e_archive_header] -//#define band_headers all_bands[e_band_headers] -#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix] -#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix] -#define cp_Utf8_chars all_bands[e_cp_Utf8_chars] -#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix] -#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars] -#define cp_Int all_bands[e_cp_Int] -#define cp_Float all_bands[e_cp_Float] -#define cp_Long_hi all_bands[e_cp_Long_hi] -#define cp_Long_lo all_bands[e_cp_Long_lo] -#define cp_Double_hi all_bands[e_cp_Double_hi] -#define cp_Double_lo all_bands[e_cp_Double_lo] -#define cp_String all_bands[e_cp_String] -#define cp_Class all_bands[e_cp_Class] -#define cp_Signature_form all_bands[e_cp_Signature_form] -#define cp_Signature_classes all_bands[e_cp_Signature_classes] -#define cp_Descr_name all_bands[e_cp_Descr_name] -#define cp_Descr_type all_bands[e_cp_Descr_type] -#define cp_Field_class all_bands[e_cp_Field_class] -#define cp_Field_desc all_bands[e_cp_Field_desc] -#define cp_Method_class all_bands[e_cp_Method_class] -#define cp_Method_desc all_bands[e_cp_Method_desc] -#define cp_Imethod_class all_bands[e_cp_Imethod_class] -#define cp_Imethod_desc all_bands[e_cp_Imethod_desc] -#define cp_MethodHandle_refkind all_bands[e_cp_MethodHandle_refkind] -#define cp_MethodHandle_member all_bands[e_cp_MethodHandle_member] -#define cp_MethodType all_bands[e_cp_MethodType] -#define cp_BootstrapMethod_ref all_bands[e_cp_BootstrapMethod_ref] -#define cp_BootstrapMethod_arg_count all_bands[e_cp_BootstrapMethod_arg_count] -#define cp_BootstrapMethod_arg all_bands[e_cp_BootstrapMethod_arg] -#define cp_InvokeDynamic_spec all_bands[e_cp_InvokeDynamic_spec] -#define cp_InvokeDynamic_desc all_bands[e_cp_InvokeDynamic_desc] -#define attr_definition_headers all_bands[e_attr_definition_headers] -#define attr_definition_name all_bands[e_attr_definition_name] -#define attr_definition_layout all_bands[e_attr_definition_layout] -#define ic_this_class all_bands[e_ic_this_class] -#define ic_flags all_bands[e_ic_flags] -#define ic_outer_class all_bands[e_ic_outer_class] -#define ic_name all_bands[e_ic_name] -#define class_this all_bands[e_class_this] -#define class_super all_bands[e_class_super] -#define class_interface_count all_bands[e_class_interface_count] -#define class_interface all_bands[e_class_interface] -#define class_field_count all_bands[e_class_field_count] -#define class_method_count all_bands[e_class_method_count] -#define field_descr all_bands[e_field_descr] -#define field_flags_hi all_bands[e_field_flags_hi] -#define field_flags_lo all_bands[e_field_flags_lo] -#define field_attr_count all_bands[e_field_attr_count] -#define field_attr_indexes all_bands[e_field_attr_indexes] -#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ] -#define field_Signature_RS all_bands[e_field_Signature_RS] -#define field_attr_bands all_bands[e_field_attr_bands] -#define method_descr all_bands[e_method_descr] -#define method_flags_hi all_bands[e_method_flags_hi] -#define method_flags_lo all_bands[e_method_flags_lo] -#define method_attr_count all_bands[e_method_attr_count] -#define method_attr_indexes all_bands[e_method_attr_indexes] -#define method_Exceptions_N all_bands[e_method_Exceptions_N] -#define method_Exceptions_RC all_bands[e_method_Exceptions_RC] -#define method_Signature_RS all_bands[e_method_Signature_RS] -#define method_MethodParameters_NB all_bands[e_method_MethodParameters_NB] -#define method_MethodParameters_name_RUN all_bands[e_method_MethodParameters_name_RUN] -#define method_MethodParameters_flag_FH all_bands[e_method_MethodParameters_flag_FH] -#define method_attr_bands all_bands[e_method_attr_bands] -#define class_flags_hi all_bands[e_class_flags_hi] -#define class_flags_lo all_bands[e_class_flags_lo] -#define class_attr_count all_bands[e_class_attr_count] -#define class_attr_indexes all_bands[e_class_attr_indexes] -#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN] -#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC] -#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN] -#define class_Signature_RS all_bands[e_class_Signature_RS] -#define class_InnerClasses_N all_bands[e_class_InnerClasses_N] -#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC] -#define class_InnerClasses_F all_bands[e_class_InnerClasses_F] -#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN] -#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN] -#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H] -#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H] -#define class_attr_bands all_bands[e_class_attr_bands] -#define code_headers all_bands[e_code_headers] -#define code_max_stack all_bands[e_code_max_stack] -#define code_max_na_locals all_bands[e_code_max_na_locals] -#define code_handler_count all_bands[e_code_handler_count] -#define code_handler_start_P all_bands[e_code_handler_start_P] -#define code_handler_end_PO all_bands[e_code_handler_end_PO] -#define code_handler_catch_PO all_bands[e_code_handler_catch_PO] -#define code_handler_class_RCN all_bands[e_code_handler_class_RCN] -#define code_flags_hi all_bands[e_code_flags_hi] -#define code_flags_lo all_bands[e_code_flags_lo] -#define code_attr_count all_bands[e_code_attr_count] -#define code_attr_indexes all_bands[e_code_attr_indexes] -#define code_StackMapTable_N all_bands[e_code_StackMapTable_N] -#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T] -#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N] -#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N] -#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset] -#define code_StackMapTable_T all_bands[e_code_StackMapTable_T] -#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC] -#define code_StackMapTable_P all_bands[e_code_StackMapTable_P] -#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N] -#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P] -#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line] -#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N] -#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P] -#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O] -#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU] -#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS] -#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot] -#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N] -#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P] -#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O] -#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU] -#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS] -#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot] -#define code_attr_bands all_bands[e_code_attr_bands] -#define bc_codes all_bands[e_bc_codes] -#define bc_case_count all_bands[e_bc_case_count] -#define bc_case_value all_bands[e_bc_case_value] -#define bc_byte all_bands[e_bc_byte] -#define bc_short all_bands[e_bc_short] -#define bc_local all_bands[e_bc_local] -#define bc_label all_bands[e_bc_label] -#define bc_intref all_bands[e_bc_intref] -#define bc_floatref all_bands[e_bc_floatref] -#define bc_longref all_bands[e_bc_longref] -#define bc_doubleref all_bands[e_bc_doubleref] -#define bc_stringref all_bands[e_bc_stringref] -#define bc_loadablevalueref all_bands[e_bc_loadablevalueref] -#define bc_classref all_bands[e_bc_classref] -#define bc_fieldref all_bands[e_bc_fieldref] -#define bc_methodref all_bands[e_bc_methodref] -#define bc_imethodref all_bands[e_bc_imethodref] -#define bc_indyref all_bands[e_bc_indyref] -#define bc_thisfield all_bands[e_bc_thisfield] -#define bc_superfield all_bands[e_bc_superfield] -#define bc_thismethod all_bands[e_bc_thismethod] -#define bc_supermethod all_bands[e_bc_supermethod] -#define bc_initref all_bands[e_bc_initref] -#define bc_escref all_bands[e_bc_escref] -#define bc_escrefsize all_bands[e_bc_escrefsize] -#define bc_escsize all_bands[e_bc_escsize] -#define bc_escbyte all_bands[e_bc_escbyte] -#define file_name all_bands[e_file_name] -#define file_size_hi all_bands[e_file_size_hi] -#define file_size_lo all_bands[e_file_size_lo] -#define file_modtime all_bands[e_file_modtime] -#define file_options all_bands[e_file_options] diff --git a/src/jdk.pack/share/native/common-unpack/bytes.cpp b/src/jdk.pack/share/native/common-unpack/bytes.cpp deleted file mode 100644 index 44b4bc581d9..00000000000 --- a/src/jdk.pack/share/native/common-unpack/bytes.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -#include -#include -#include -#include "defines.h" -#include "bytes.h" -#include "utils.h" - - -static byte dummy[1 << 10]; - -bool bytes::inBounds(const void* p) { - return p >= ptr && p < limit(); -} - -void bytes::malloc(size_t len_) { - len = len_; - ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always - if (ptr == null) { - // set ptr to some victim memory, to ease escape - set(dummy, sizeof(dummy)-1); - unpack_abort(ERROR_ENOMEM); - } -} - -void bytes::realloc(size_t len_) { - if (len == len_) return; // nothing to do - if (ptr == dummy) return; // escaping from an error - if (ptr == null) { - malloc(len_); - return; - } - byte* oldptr = ptr; - ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, add_size(len_, 1)); - if (ptr != null) { - mtrace('r', oldptr, 0); - mtrace('m', ptr, len_+1); - if (len < len_) memset(ptr+len, 0, len_-len); - ptr[len_] = 0; - len = len_; - } else { - ptr = oldptr; // ease our escape - unpack_abort(ERROR_ENOMEM); - } -} - -void bytes::free() { - if (ptr == dummy) return; // escaping from an error - if (ptr != null) { - mtrace('f', ptr, 0); - ::free(ptr); - } - len = 0; - ptr = 0; -} - -int bytes::indexOf(byte c) { - byte* p = (byte*) memchr(ptr, c, len); - return (p == 0) ? -1 : (int)(p - ptr); -} - -byte* bytes::writeTo(byte* bp) { - memcpy(bp, ptr, len); - return bp+len; -} - -int bytes::compareTo(bytes& other) { - size_t l1 = len; - size_t l2 = other.len; - int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2); - if (cmp != 0) return cmp; - return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0; -} - -void bytes::saveFrom(const void* ptr_, size_t len_) { - malloc(len_); - // Save as much as possible. (Helps unpacker::abort.) - if (len_ > len) { - assert(ptr == dummy); // error recovery - len_ = len; - } - copyFrom(ptr_, len_); -} - -//#TODO: Need to fix for exception handling -void bytes::copyFrom(const void* ptr_, size_t len_, size_t offset) { - assert(len_ == 0 || inBounds(ptr + offset)); - assert(len_ == 0 || inBounds(ptr + offset+len_-1)); - memcpy(ptr+offset, ptr_, len_); -} - - -#ifndef PRODUCT -const char* bytes::string() { - if (len == 0) return ""; - if (ptr[len] == 0 && strlen((char*)ptr) == len) return (const char*) ptr; - bytes junk; - junk.saveFrom(*this); - return (char*) junk.ptr; -} -#endif - -// Make sure there are 'o' bytes beyond the fill pointer, -// advance the fill pointer, and return the old fill pointer. -byte* fillbytes::grow(size_t s) { - size_t nlen = add_size(b.len, s); - if (nlen <= allocated) { - b.len = nlen; - return limit()-s; - } - size_t maxlen = nlen; - if (maxlen < 128) maxlen = 128; - if (maxlen < allocated*2) maxlen = allocated*2; - if (allocated == 0) { - // Initial buffer was not malloced. Do not reallocate it. - bytes old = b; - b.malloc(maxlen); - if (b.len == maxlen) - old.writeTo(b.ptr); - } else { - b.realloc(maxlen); - } - allocated = b.len; - if (allocated != maxlen) { - assert(unpack_aborting()); - b.len = nlen-s; // back up - return dummy; // scribble during error recov. - } - // after realloc, recompute pointers - b.len = nlen; - assert(b.len <= allocated); - return limit()-s; -} - -void fillbytes::ensureSize(size_t s) { - if (allocated >= s) return; - size_t len0 = b.len; - grow(s - size()); - b.len = len0; // put it back -} - -int ptrlist::indexOf(const void* x) { - int len = length(); - for (int i = 0; i < len; i++) { - if (get(i) == x) return i; - } - return -1; -} - -void ptrlist::freeAll() { - int len = length(); - for (int i = 0; i < len; i++) { - void* p = (void*) get(i); - if (p != null) { - mtrace('f', p, 0); - ::free(p); - } - } - free(); -} - -int intlist::indexOf(int x) { - int len = length(); - for (int i = 0; i < len; i++) { - if (get(i) == x) return i; - } - return -1; -} diff --git a/src/jdk.pack/share/native/common-unpack/bytes.h b/src/jdk.pack/share/native/common-unpack/bytes.h deleted file mode 100644 index 60c5b4f2a69..00000000000 --- a/src/jdk.pack/share/native/common-unpack/bytes.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#ifdef WIN32_LEAN_AND_MEAN -typedef signed char byte ; -#endif - -struct bytes { - byte* ptr; - size_t len; - byte* limit() { return ptr+len; } - - void set(byte* ptr_, size_t len_) { ptr = ptr_; len = len_; } - void set(const char* str) { ptr = (byte*)str; len = strlen(str); } - bool inBounds(const void* p); // p in [ptr, limit) - void malloc(size_t len_); - void realloc(size_t len_); - void free(); - void copyFrom(const void* ptr_, size_t len_, size_t offset = 0); - void saveFrom(const void* ptr_, size_t len_); - void saveFrom(const char* str) { saveFrom(str, strlen(str)); } - void copyFrom(bytes& other, size_t offset = 0) { - copyFrom(other.ptr, other.len, offset); - } - void saveFrom(bytes& other) { - saveFrom(other.ptr, other.len); - } - void clear(int fill_byte = 0) { memset(ptr, fill_byte, len); } - byte* writeTo(byte* bp); - bool equals(bytes& other) { return 0 == compareTo(other); } - int compareTo(bytes& other); - bool contains(byte c) { return indexOf(c) >= 0; } - int indexOf(byte c); - // substrings: - static bytes of(byte* ptr, size_t len) { - bytes res; - res.set(ptr, len); - return res; - } - bytes slice(size_t beg, size_t end) { - bytes res; - res.ptr = ptr + beg; - res.len = end - beg; - assert(res.len == 0 || (inBounds(res.ptr) && inBounds(res.limit()-1))); - return res; - } - // building C strings inside byte buffers: - bytes& strcat(const char* str) { ::strcat((char*)ptr, str); return *this; } - bytes& strcat(bytes& other) { ::strncat((char*)ptr, (char*)other.ptr, other.len); return *this; } - char* strval() { assert(strlen((char*)ptr) == len); return (char*) ptr; } -#ifdef PRODUCT - const char* string() { return 0; } -#else - const char* string(); -#endif -}; -#define BYTES_OF(var) (bytes::of((byte*)&(var), sizeof(var))) - -struct fillbytes { - bytes b; - size_t allocated; - - byte* base() { return b.ptr; } - size_t size() { return b.len; } - byte* limit() { return b.limit(); } // logical limit - void setLimit(byte* lp) { assert(isAllocated(lp)); b.len = lp - b.ptr; } - byte* end() { return b.ptr + allocated; } // physical limit - byte* loc(size_t o) { assert(o < b.len); return b.ptr + o; } - void init() { allocated = 0; b.set(null, 0); } - void init(size_t s) { init(); ensureSize(s); } - void free() { if (allocated != 0) b.free(); allocated = 0; } - void empty() { b.len = 0; } - byte* grow(size_t s); // grow so that limit() += s - int getByte(uint i) { return *loc(i) & 0xFF; } - void addByte(byte x) { *grow(1) = x; } - void ensureSize(size_t s); // make sure allocated >= s - void trimToSize() { if (allocated > size()) b.realloc(allocated = size()); } - bool canAppend(size_t s) { return allocated > b.len+s; } - bool isAllocated(byte* p) { return p >= base() && p <= end(); } //asserts - void set(bytes& src) { set(src.ptr, src.len); } - - void set(byte* ptr, size_t len) { - b.set(ptr, len); - allocated = 0; // mark as not reallocatable - } - - // block operations on resizing byte buffer: - fillbytes& append(const void* ptr_, size_t len_) - { memcpy(grow(len_), ptr_, len_); return (*this); } - fillbytes& append(bytes& other) - { return append(other.ptr, other.len); } - fillbytes& append(const char* str) - { return append(str, strlen(str)); } -}; - -struct ptrlist : fillbytes { - typedef const void* cvptr; - int length() { return (int)(size() / sizeof(cvptr)); } - cvptr* base() { return (cvptr*) fillbytes::base(); } - cvptr& get(int i) { return *(cvptr*)loc(i * sizeof(cvptr)); } - cvptr* limit() { return (cvptr*) fillbytes::limit(); } - void add(cvptr x) { *(cvptr*)grow(sizeof(x)) = x; } - void popTo(int l) { assert(l <= length()); b.len = l * sizeof(cvptr); } - int indexOf(cvptr x); - bool contains(cvptr x) { return indexOf(x) >= 0; } - void freeAll(); // frees every ptr on the list, plus the list itself -}; -// Use a macro rather than mess with subtle mismatches -// between member and non-member function pointers. -#define PTRLIST_QSORT(ptrls, fn) \ - ::qsort((ptrls).base(), (ptrls).length(), sizeof(void*), fn) - -struct intlist : fillbytes { - int length() { return (int)(size() / sizeof(int)); } - int* base() { return (int*) fillbytes::base(); } - int& get(int i) { return *(int*)loc(i * sizeof(int)); } - int* limit() { return (int*) fillbytes::limit(); } - void add(int x) { *(int*)grow(sizeof(x)) = x; } - void popTo(int l) { assert(l <= length()); b.len = l * sizeof(int); } - int indexOf(int x); - bool contains(int x) { return indexOf(x) >= 0; } -}; diff --git a/src/jdk.pack/share/native/common-unpack/coding.cpp b/src/jdk.pack/share/native/common-unpack/coding.cpp deleted file mode 100644 index 66ecc1bff63..00000000000 --- a/src/jdk.pack/share/native/common-unpack/coding.cpp +++ /dev/null @@ -1,989 +0,0 @@ -/* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// -*- C++ -*- -// Small program for unpacking specially compressed Java packages. -// John R. Rose - -#include -#include -#include -#include - -#include "jni_util.h" - -#include "defines.h" -#include "bytes.h" -#include "utils.h" -#include "coding.h" - -#include "constants.h" -#include "unpack.h" - -extern coding basic_codings[]; - -#define CODING_PRIVATE(spec) \ - int spec_ = spec; \ - int B = CODING_B(spec_); \ - int H = CODING_H(spec_); \ - int L = 256 - H; \ - int S = CODING_S(spec_); \ - int D = CODING_D(spec_) - -#define IS_NEG_CODE(S, codeVal) \ - ( (((int)(codeVal)+1) & ((1<> 1) ^ -((int)(ux) & 1) ) - -static maybe_inline -int decode_sign(int S, uint ux) { // == Coding.decodeSign32 - assert(S > 0); - uint sigbits = (ux >> S); - if (IS_NEG_CODE(S, ux)) - return (int)( ~sigbits); - else - return (int)(ux - sigbits); - // Note that (int)(ux-sigbits) can be negative, if ux is large enough. -} - -coding* coding::init() { - if (umax > 0) return this; // already done - assert(spec != 0); // sanity - - // fill in derived fields - CODING_PRIVATE(spec); - - // Return null if 'arb(BHSD)' parameter constraints are not met: - if (B < 1 || B > B_MAX) return null; - if (H < 1 || H > 256) return null; - if (S < 0 || S > 2) return null; - if (D < 0 || D > 1) return null; - if (B == 1 && H != 256) return null; // 1-byte coding must be fixed-size - if (B >= 5 && H == 256) return null; // no 5-byte fixed-size coding - - // first compute the range of the coding, in 64 bits - jlong range = 0; - { - jlong H_i = 1; - for (int i = 0; i < B; i++) { - range += H_i; - H_i *= H; - } - range *= L; - range += H_i; - } - assert(range > 0); // no useless codings, please - - int this_umax; - - // now, compute min and max - if (range >= ((jlong)1 << 32)) { - this_umax = INT_MAX_VALUE; - this->umin = INT_MIN_VALUE; - this->max = INT_MAX_VALUE; - this->min = INT_MIN_VALUE; - } else { - this_umax = (range > INT_MAX_VALUE) ? INT_MAX_VALUE : (int)range-1; - this->max = this_umax; - this->min = this->umin = 0; - if (S != 0 && range != 0) { - int Smask = (1<max = INT_MAX_VALUE; // 32-bit wraparound - else - this->max = maxPos; - if (maxNegCode < 0) - this->min = 0; // No negative codings at all. - else - this->min = decode_sign(S, (uint)maxNegCode); - } - } - - assert(!(isFullRange | isSigned | isSubrange)); // init - if (min < 0) - this->isSigned = true; - if (max < INT_MAX_VALUE && range <= INT_MAX_VALUE) - this->isSubrange = true; - if (max == INT_MAX_VALUE && min == INT_MIN_VALUE) - this->isFullRange = true; - - // do this last, to reduce MT exposure (should have a membar too) - this->umax = this_umax; - - return this; -} - -coding* coding::findBySpec(int spec) { - for (coding* scan = &basic_codings[0]; ; scan++) { - if (scan->spec == spec) - return scan->init(); - if (scan->spec == 0) - break; - } - coding* ptr = NEW(coding, 1); - CHECK_NULL_RETURN(ptr, 0); - coding* c = ptr->initFrom(spec); - if (c == null) { - mtrace('f', ptr, 0); - ::free(ptr); - } else - // else caller should free it... - c->isMalloc = true; - return c; -} - -coding* coding::findBySpec(int B, int H, int S, int D) { - if (B < 1 || B > B_MAX) return null; - if (H < 1 || H > 256) return null; - if (S < 0 || S > 2) return null; - if (D < 0 || D > 1) return null; - return findBySpec(CODING_SPEC(B, H, S, D)); -} - -void coding::free() { - if (isMalloc) { - mtrace('f', this, 0); - ::free(this); - } -} - -void coding_method::reset(value_stream* state) { - assert(state->rp == state->rplimit); // not in mid-stream, please - //assert(this == vs0.cm); - state[0] = vs0; - if (uValues != null) { - uValues->reset(state->helper()); - } -} - -maybe_inline -uint coding::parse(byte* &rp, int B, int H) { - int L = 256-H; - byte* ptr = rp; - // hand peel the i==0 part of the loop: - uint b_i = *ptr++ & 0xFF; - if (B == 1 || b_i < (uint)L) - { rp = ptr; return b_i; } - uint sum = b_i; - uint H_i = H; - assert(B <= B_MAX); - for (int i = 2; i <= B_MAX; i++) { // easy for compilers to unroll if desired - b_i = *ptr++ & 0xFF; - sum += b_i * H_i; - if (i == B || b_i < (uint)L) - { rp = ptr; return sum; } - H_i *= H; - } - assert(false); - return 0; -} - -maybe_inline -uint coding::parse_lgH(byte* &rp, int B, int H, int lgH) { - assert(H == (1< limit) { - abort(ERB); - return; - } - rp = ptr+len; - return; - } - // Note: We assume rp has enough zero-padding. - int L = 256-H; - int n = B; - while (N > 0) { - ptr += 1; - if (--n == 0) { - // end of encoding at B bytes, regardless of byte value - } else { - int b = (ptr[-1] & 0xFF); - if (b >= L) { - // keep going, unless we find a byte < L - continue; - } - } - // found the last byte - N -= 1; - n = B; // reset length counter - // do an error check here - if (ptr > limit) { - abort(ERB); - return; - } - } - rp = ptr; - return; -} - -bool value_stream::hasHelper() { - // If my coding method is a pop-style method, - // then I need a second value stream to transmit - // unfavored values. - // This can be determined by examining fValues. - return cm->fValues != null; -} - -void value_stream::init(byte* rp_, byte* rplimit_, coding* defc) { - rp = rp_; - rplimit = rplimit_; - sum = 0; - cm = null; // no need in the simple case - setCoding(defc); -} - -void value_stream::setCoding(coding* defc) { - if (defc == null) { - unpack_abort("bad coding"); - defc = coding::findByIndex(_meta_canon_min); // random pick for recovery - } - - c = (*defc); - - // choose cmk - cmk = cmk_ERROR; - switch (c.spec) { - case BYTE1_spec: cmk = cmk_BYTE1; break; - case CHAR3_spec: cmk = cmk_CHAR3; break; - case UNSIGNED5_spec: cmk = cmk_UNSIGNED5; break; - case DELTA5_spec: cmk = cmk_DELTA5; break; - case BCI5_spec: cmk = cmk_BCI5; break; - case BRANCH5_spec: cmk = cmk_BRANCH5; break; - default: - if (c.D() == 0) { - switch (c.S()) { - case 0: cmk = cmk_BHS0; break; - case 1: cmk = cmk_BHS1; break; - default: cmk = cmk_BHS; break; - } - } else { - if (c.S() == 1) { - if (c.isFullRange) cmk = cmk_BHS1D1full; - if (c.isSubrange) cmk = cmk_BHS1D1sub; - } - if (cmk == cmk_ERROR) cmk = cmk_BHSD1; - } - } -} - -static maybe_inline -int getPopValue(value_stream* self, uint uval) { - if (uval > 0) { - // note that the initial parse performed a range check - assert(uval <= (uint)self->cm->fVlength); - return self->cm->fValues[uval-1]; - } else { - // take an unfavored value - return self->helper()->getInt(); - } -} - -maybe_inline -int coding::sumInUnsignedRange(int x, int y) { - assert(isSubrange); - int range = (int)(umax+1); - assert(range > 0); - x += y; - if (x != (int)((jlong)(x-y) + (jlong)y)) { - // 32-bit overflow interferes with range reduction. - // Back off from the overflow by adding a multiple of range: - if (x < 0) { - x -= range; - assert(x >= 0); - } else { - x += range; - assert(x < 0); - } - } - if (x < 0) { - x += range; - if (x >= 0) return x; - } else if (x >= range) { - x -= range; - if (x < range) return x; - } else { - // in range - return x; - } - // do it the hard way - x %= range; - if (x < 0) x += range; - return x; -} - -static maybe_inline -int getDeltaValue(value_stream* self, uint uval, bool isSubrange) { - assert((uint)(self->c.isSubrange) == (uint)isSubrange); - assert(self->c.isSubrange | self->c.isFullRange); - if (isSubrange) - return self->sum = self->c.sumInUnsignedRange(self->sum, (int)uval); - else - return self->sum += (int) uval; -} - -bool value_stream::hasValue() { - if (rp < rplimit) return true; - if (cm == null) return false; - if (cm->next == null) return false; - cm->next->reset(this); - return hasValue(); -} - -int value_stream::getInt() { - if (rp >= rplimit) { - // Advance to next coding segment. - if (rp > rplimit || cm == null || cm->next == null) { - // Must perform this check and throw an exception on bad input. - unpack_abort(ERB); - return 0; - } - cm->next->reset(this); - return getInt(); - } - - CODING_PRIVATE(c.spec); - uint uval; - enum { - B5 = 5, - B3 = 3, - H128 = 128, - H64 = 64, - H4 = 4 - }; - switch (cmk) { - case cmk_BHS: - assert(D == 0); - uval = coding::parse(rp, B, H); - if (S == 0) - return (int) uval; - return decode_sign(S, uval); - - case cmk_BHS0: - assert(S == 0 && D == 0); - uval = coding::parse(rp, B, H); - return (int) uval; - - case cmk_BHS1: - assert(S == 1 && D == 0); - uval = coding::parse(rp, B, H); - return DECODE_SIGN_S1(uval); - - case cmk_BYTE1: - assert(c.spec == BYTE1_spec); - assert(B == 1 && H == 256 && S == 0 && D == 0); - return *rp++ & 0xFF; - - case cmk_CHAR3: - assert(c.spec == CHAR3_spec); - assert(B == B3 && H == H128 && S == 0 && D == 0); - return coding::parse_lgH(rp, B3, H128, 7); - - case cmk_UNSIGNED5: - assert(c.spec == UNSIGNED5_spec); - assert(B == B5 && H == H64 && S == 0 && D == 0); - return coding::parse_lgH(rp, B5, H64, 6); - - case cmk_BHSD1: - assert(D == 1); - uval = coding::parse(rp, B, H); - if (S != 0) - uval = (uint) decode_sign(S, uval); - return getDeltaValue(this, uval, (bool)c.isSubrange); - - case cmk_BHS1D1full: - assert(S == 1 && D == 1 && c.isFullRange); - uval = coding::parse(rp, B, H); - uval = (uint) DECODE_SIGN_S1(uval); - return getDeltaValue(this, uval, false); - - case cmk_BHS1D1sub: - assert(S == 1 && D == 1 && c.isSubrange); - uval = coding::parse(rp, B, H); - uval = (uint) DECODE_SIGN_S1(uval); - return getDeltaValue(this, uval, true); - - case cmk_DELTA5: - assert(c.spec == DELTA5_spec); - assert(B == B5 && H == H64 && S == 1 && D == 1 && c.isFullRange); - uval = coding::parse_lgH(rp, B5, H64, 6); - sum += DECODE_SIGN_S1(uval); - return sum; - - case cmk_BCI5: - assert(c.spec == BCI5_spec); - assert(B == B5 && H == H4 && S == 0 && D == 0); - return coding::parse_lgH(rp, B5, H4, 2); - - case cmk_BRANCH5: - assert(c.spec == BRANCH5_spec); - assert(B == B5 && H == H4 && S == 2 && D == 0); - uval = coding::parse_lgH(rp, B5, H4, 2); - return decode_sign(S, uval); - - case cmk_pop: - uval = coding::parse(rp, B, H); - if (S != 0) { - uval = (uint) decode_sign(S, uval); - } - if (D != 0) { - assert(c.isSubrange | c.isFullRange); - if (c.isSubrange) - sum = c.sumInUnsignedRange(sum, (int) uval); - else - sum += (int) uval; - uval = (uint) sum; - } - return getPopValue(this, uval); - - case cmk_pop_BHS0: - assert(S == 0 && D == 0); - uval = coding::parse(rp, B, H); - return getPopValue(this, uval); - - case cmk_pop_BYTE1: - assert(c.spec == BYTE1_spec); - assert(B == 1 && H == 256 && S == 0 && D == 0); - return getPopValue(this, *rp++ & 0xFF); - - default: - break; - } - assert(false); - return 0; -} - -static maybe_inline -int moreCentral(int x, int y) { // used to find end of Pop.{F} - // Suggested implementation from the Pack200 specification: - uint kx = (x >> 31) ^ (x << 1); - uint ky = (y >> 31) ^ (y << 1); - return (kx < ky? x: y); -} -//static maybe_inline -//int moreCentral2(int x, int y, int min) { -// // Strict implementation of buggy 150.7 specification. -// // The bug is that the spec. says absolute-value ties are broken -// // in favor of positive numbers, but the suggested implementation -// // (also mentioned in the spec.) breaks ties in favor of negative numbers. -// if ((x + y) != 0) -// return min; -// else -// // return the other value, which breaks a tie in the positive direction -// return (x > y)? x: y; -//} - -static const byte* no_meta[] = {null}; -#define NO_META (*(byte**)no_meta) -enum { POP_FAVORED_N = -2 }; - -// mode bits -#define DISABLE_RUN 1 // used immediately inside ACodee -#define DISABLE_POP 2 // used recursively in all pop sub-bands - -// This function knows all about meta-coding. -void coding_method::init(byte* &band_rp, byte* band_limit, - byte* &meta_rp, int mode, - coding* defc, int N, - intlist* valueSink) { - assert(N != 0); - - assert(u != null); // must be pre-initialized - //if (u == null) u = unpacker::current(); // expensive - - int op = (meta_rp == null) ? _meta_default : (*meta_rp++ & 0xFF); - coding* foundc = null; - coding* to_free = null; - - if (op == _meta_default) { - foundc = defc; - // and fall through - - } else if (op >= _meta_canon_min && op <= _meta_canon_max) { - foundc = coding::findByIndex(op); - // and fall through - - } else if (op == _meta_arb) { - int args = (*meta_rp++ & 0xFF); - // args = (D:[0..1] + 2*S[0..2] + 8*(B:[1..5]-1)) - int D = ((args >> 0) & 1); - int S = ((args >> 1) & 3); - int B = ((args >> 3) & -1) + 1; - // & (H[1..256]-1) - int H = (*meta_rp++ & 0xFF) + 1; - foundc = coding::findBySpec(B, H, S, D); - to_free = foundc; // findBySpec may dynamically allocate - if (foundc == null) { - abort("illegal arb. coding"); - return; - } - // and fall through - - } else if (op >= _meta_run && op < _meta_pop) { - int args = (op - _meta_run); - // args: KX:[0..3] + 4*(KBFlag:[0..1]) + 8*(ABDef:[0..2]) - int KX = ((args >> 0) & 3); - int KBFlag = ((args >> 2) & 1); - int ABDef = ((args >> 3) & -1); - assert(ABDef <= 2); - // & KB: one of [0..255] if KBFlag=1 - int KB = (!KBFlag? 3: (*meta_rp++ & 0xFF)); - int K = (KB+1) << (KX * 4); - int N2 = (N >= 0) ? N-K : N; - if (N == 0 || (N2 <= 0 && N2 != N)) { - abort("illegal run encoding"); - return; - } - if ((mode & DISABLE_RUN) != 0) { - abort("illegal nested run encoding"); - return; - } - - // & Enc{ ACode } if ADef=0 (ABDef != 1) - // No direct nesting of 'run' in ACode, but in BCode it's OK. - int disRun = mode | DISABLE_RUN; - if (ABDef == 1) { - this->init(band_rp, band_limit, NO_META, disRun, defc, K, valueSink); - } else { - this->init(band_rp, band_limit, meta_rp, disRun, defc, K, valueSink); - } - CHECK; - - // & Enc{ BCode } if BDef=0 (ABDef != 2) - coding_method* tail = U_NEW(coding_method, 1); - CHECK_NULL(tail); - tail->u = u; - - // The 'run' codings may be nested indirectly via 'pop' codings. - // This means that this->next may already be filled in, if - // ACode was of type 'pop' with a 'run' token coding. - // No problem: Just chain the upcoming BCode onto the end. - for (coding_method* self = this; ; self = self->next) { - if (self->next == null) { - self->next = tail; - break; - } - } - - if (ABDef == 2) { - tail->init(band_rp, band_limit, NO_META, mode, defc, N2, valueSink); - } else { - tail->init(band_rp, band_limit, meta_rp, mode, defc, N2, valueSink); - } - // Note: The preceding calls to init should be tail-recursive. - - return; // done; no falling through - - } else if (op >= _meta_pop && op < _meta_limit) { - int args = (op - _meta_pop); - // args: (FDef:[0..1]) + 2*UDef:[0..1] + 4*(TDefL:[0..11]) - int FDef = ((args >> 0) & 1); - int UDef = ((args >> 1) & 1); - int TDefL = ((args >> 2) & -1); - assert(TDefL <= 11); - int TDef = (TDefL > 0); - int TL = (TDefL <= 6) ? (2 << TDefL) : (256 - (4 << (11-TDefL))); - int TH = (256-TL); - if (N <= 0) { - abort("illegal pop encoding"); - return; - } - if ((mode & DISABLE_POP) != 0) { - abort("illegal nested pop encoding"); - return; - } - - // No indirect nesting of 'pop', but 'run' is OK. - int disPop = DISABLE_POP; - - // & Enc{ FCode } if FDef=0 - int FN = POP_FAVORED_N; - assert(valueSink == null); - intlist fValueSink; fValueSink.init(); - coding_method fval; - BYTES_OF(fval).clear(); fval.u = u; - if (FDef != 0) { - fval.init(band_rp, band_limit, NO_META, disPop, defc, FN, &fValueSink); - } else { - fval.init(band_rp, band_limit, meta_rp, disPop, defc, FN, &fValueSink); - } - bytes fvbuf; - fValues = (u->saveTo(fvbuf, fValueSink.b), (int*) fvbuf.ptr); - fVlength = fValueSink.length(); // i.e., the parameter K - fValueSink.free(); - CHECK; - - // Skip the first {F} run in all subsequent passes. - // The next call to this->init(...) will set vs0.rp to point after the {F}. - - // & Enc{ TCode } if TDef=0 (TDefL==0) - if (TDef != 0) { - coding* tcode = coding::findBySpec(1, 256); // BYTE1 - // find the most narrowly sufficient code: - for (int B = 2; B <= B_MAX; B++) { - if (fVlength <= tcode->umax) break; // found it - tcode->free(); - tcode = coding::findBySpec(B, TH); - CHECK_NULL(tcode); - } - if (!(fVlength <= tcode->umax)) { - abort("pop.L value too small"); - return; - } - this->init(band_rp, band_limit, NO_META, disPop, tcode, N, null); - tcode->free(); - } else { - this->init(band_rp, band_limit, meta_rp, disPop, defc, N, null); - } - CHECK; - - // Count the number of zero tokens right now. - // Also verify that they are in bounds. - int UN = 0; // one {U} for each zero in {T} - value_stream vs = vs0; - for (int i = 0; i < N; i++) { - uint val = vs.getInt(); - if (val == 0) UN += 1; - if (!(val <= (uint)fVlength)) { - abort("pop token out of range"); - return; - } - } - vs.done(); - - // & Enc{ UCode } if UDef=0 - if (UN != 0) { - uValues = U_NEW(coding_method, 1); - CHECK_NULL(uValues); - uValues->u = u; - if (UDef != 0) { - uValues->init(band_rp, band_limit, NO_META, disPop, defc, UN, null); - } else { - uValues->init(band_rp, band_limit, meta_rp, disPop, defc, UN, null); - } - } else { - if (UDef == 0) { - int uop = (*meta_rp++ & 0xFF); - if (uop > _meta_canon_max) - // %%% Spec. requires the more strict (uop != _meta_default). - abort("bad meta-coding for empty pop/U"); - } - } - - // Bug fix for 6259542 - // Last of all, adjust vs0.cmk to the 'pop' flavor - for (coding_method* self = this; self != null; self = self->next) { - coding_method_kind cmk2 = cmk_pop; - switch (self->vs0.cmk) { - case cmk_BHS0: cmk2 = cmk_pop_BHS0; break; - case cmk_BYTE1: cmk2 = cmk_pop_BYTE1; break; - default: break; - } - self->vs0.cmk = cmk2; - if (self != this) { - assert(self->fValues == null); // no double init - self->fValues = this->fValues; - self->fVlength = this->fVlength; - assert(self->uValues == null); // must stay null - } - } - - return; // done; no falling through - - } else { - abort("bad meta-coding"); - return; - } - - // Common code here skips a series of values with one coding. - assert(foundc != null); - - assert(vs0.cmk == cmk_ERROR); // no garbage, please - assert(vs0.rp == null); // no garbage, please - assert(vs0.rplimit == null); // no garbage, please - assert(vs0.sum == 0); // no garbage, please - - vs0.init(band_rp, band_limit, foundc); - - // Done with foundc. Free if necessary. - if (to_free != null) { - to_free->free(); - to_free = null; - } - foundc = null; - - coding& c = vs0.c; - CODING_PRIVATE(c.spec); - // assert sane N - assert((uint)N < INT_MAX_VALUE || N == POP_FAVORED_N); - - // Look at the values, or at least skip over them quickly. - if (valueSink == null) { - // Skip and ignore values in the first pass. - c.parseMultiple(band_rp, N, band_limit, B, H); - } else if (N >= 0) { - // Pop coding, {F} sequence, initial run of values... - assert((mode & DISABLE_POP) != 0); - value_stream vs = vs0; - for (int n = 0; n < N; n++) { - int val = vs.getInt(); - valueSink->add(val); - } - band_rp = vs.rp; - } else { - // Pop coding, {F} sequence, final run of values... - assert((mode & DISABLE_POP) != 0); - assert(N == POP_FAVORED_N); - int min = INT_MIN_VALUE; // farthest from the center - // min2 is based on the buggy specification of centrality in version 150.7 - // no known implementations transmit this value, but just in case... - //int min2 = INT_MIN_VALUE; - int last = 0; - // if there were initial runs, find the potential sentinels in them: - for (int i = 0; i < valueSink->length(); i++) { - last = valueSink->get(i); - min = moreCentral(min, last); - //min2 = moreCentral2(min2, last, min); - } - value_stream vs = vs0; - for (;;) { - int val = vs.getInt(); - if (valueSink->length() > 0 && - (val == last || val == min)) //|| val == min2 - break; - valueSink->add(val); - CHECK; - last = val; - min = moreCentral(min, last); - //min2 = moreCentral2(min2, last, min); - } - band_rp = vs.rp; - } - CHECK; - - // Get an accurate upper limit now. - vs0.rplimit = band_rp; - vs0.cm = this; - - return; // success -} - -coding basic_codings[] = { - // This one is not a usable irregular coding, but is used by cp_Utf8_chars. - CODING_INIT(3,128,0,0), - - // Fixed-length codings: - CODING_INIT(1,256,0,0), - CODING_INIT(1,256,1,0), - CODING_INIT(1,256,0,1), - CODING_INIT(1,256,1,1), - CODING_INIT(2,256,0,0), - CODING_INIT(2,256,1,0), - CODING_INIT(2,256,0,1), - CODING_INIT(2,256,1,1), - CODING_INIT(3,256,0,0), - CODING_INIT(3,256,1,0), - CODING_INIT(3,256,0,1), - CODING_INIT(3,256,1,1), - CODING_INIT(4,256,0,0), - CODING_INIT(4,256,1,0), - CODING_INIT(4,256,0,1), - CODING_INIT(4,256,1,1), - - // Full-range variable-length codings: - CODING_INIT(5, 4,0,0), - CODING_INIT(5, 4,1,0), - CODING_INIT(5, 4,2,0), - CODING_INIT(5, 16,0,0), - CODING_INIT(5, 16,1,0), - CODING_INIT(5, 16,2,0), - CODING_INIT(5, 32,0,0), - CODING_INIT(5, 32,1,0), - CODING_INIT(5, 32,2,0), - CODING_INIT(5, 64,0,0), - CODING_INIT(5, 64,1,0), - CODING_INIT(5, 64,2,0), - CODING_INIT(5,128,0,0), - CODING_INIT(5,128,1,0), - CODING_INIT(5,128,2,0), - - CODING_INIT(5, 4,0,1), - CODING_INIT(5, 4,1,1), - CODING_INIT(5, 4,2,1), - CODING_INIT(5, 16,0,1), - CODING_INIT(5, 16,1,1), - CODING_INIT(5, 16,2,1), - CODING_INIT(5, 32,0,1), - CODING_INIT(5, 32,1,1), - CODING_INIT(5, 32,2,1), - CODING_INIT(5, 64,0,1), - CODING_INIT(5, 64,1,1), - CODING_INIT(5, 64,2,1), - CODING_INIT(5,128,0,1), - CODING_INIT(5,128,1,1), - CODING_INIT(5,128,2,1), - - // Variable length subrange codings: - CODING_INIT(2,192,0,0), - CODING_INIT(2,224,0,0), - CODING_INIT(2,240,0,0), - CODING_INIT(2,248,0,0), - CODING_INIT(2,252,0,0), - - CODING_INIT(2, 8,0,1), - CODING_INIT(2, 8,1,1), - CODING_INIT(2, 16,0,1), - CODING_INIT(2, 16,1,1), - CODING_INIT(2, 32,0,1), - CODING_INIT(2, 32,1,1), - CODING_INIT(2, 64,0,1), - CODING_INIT(2, 64,1,1), - CODING_INIT(2,128,0,1), - CODING_INIT(2,128,1,1), - CODING_INIT(2,192,0,1), - CODING_INIT(2,192,1,1), - CODING_INIT(2,224,0,1), - CODING_INIT(2,224,1,1), - CODING_INIT(2,240,0,1), - CODING_INIT(2,240,1,1), - CODING_INIT(2,248,0,1), - CODING_INIT(2,248,1,1), - - CODING_INIT(3,192,0,0), - CODING_INIT(3,224,0,0), - CODING_INIT(3,240,0,0), - CODING_INIT(3,248,0,0), - CODING_INIT(3,252,0,0), - - CODING_INIT(3, 8,0,1), - CODING_INIT(3, 8,1,1), - CODING_INIT(3, 16,0,1), - CODING_INIT(3, 16,1,1), - CODING_INIT(3, 32,0,1), - CODING_INIT(3, 32,1,1), - CODING_INIT(3, 64,0,1), - CODING_INIT(3, 64,1,1), - CODING_INIT(3,128,0,1), - CODING_INIT(3,128,1,1), - CODING_INIT(3,192,0,1), - CODING_INIT(3,192,1,1), - CODING_INIT(3,224,0,1), - CODING_INIT(3,224,1,1), - CODING_INIT(3,240,0,1), - CODING_INIT(3,240,1,1), - CODING_INIT(3,248,0,1), - CODING_INIT(3,248,1,1), - - CODING_INIT(4,192,0,0), - CODING_INIT(4,224,0,0), - CODING_INIT(4,240,0,0), - CODING_INIT(4,248,0,0), - CODING_INIT(4,252,0,0), - - CODING_INIT(4, 8,0,1), - CODING_INIT(4, 8,1,1), - CODING_INIT(4, 16,0,1), - CODING_INIT(4, 16,1,1), - CODING_INIT(4, 32,0,1), - CODING_INIT(4, 32,1,1), - CODING_INIT(4, 64,0,1), - CODING_INIT(4, 64,1,1), - CODING_INIT(4,128,0,1), - CODING_INIT(4,128,1,1), - CODING_INIT(4,192,0,1), - CODING_INIT(4,192,1,1), - CODING_INIT(4,224,0,1), - CODING_INIT(4,224,1,1), - CODING_INIT(4,240,0,1), - CODING_INIT(4,240,1,1), - CODING_INIT(4,248,0,1), - CODING_INIT(4,248,1,1), - CODING_INIT(0,0,0,0) -}; -#define BASIC_INDEX_LIMIT \ - (int)(sizeof(basic_codings)/sizeof(basic_codings[0])-1) - -coding* coding::findByIndex(int idx) { -#ifndef PRODUCT - /* Tricky assert here, constants and gcc complains about it without local. */ - int index_limit = BASIC_INDEX_LIMIT; - assert(_meta_canon_min == 1 && _meta_canon_max+1 == index_limit); -#endif - if (idx >= _meta_canon_min && idx <= _meta_canon_max) - return basic_codings[idx].init(); - else - return null; -} - -#ifndef PRODUCT -const char* coding::string() { - CODING_PRIVATE(spec); - bytes buf; - buf.malloc(100); - char maxS[20], minS[20]; - sprintf(maxS, "%d", max); - sprintf(minS, "%d", min); - if (max == INT_MAX_VALUE) strcpy(maxS, "max"); - if (min == INT_MIN_VALUE) strcpy(minS, "min"); - sprintf((char*)buf.ptr, "(%d,%d,%d,%d) L=%d r=[%s,%s]", - B,H,S,D,L,minS,maxS); - return (const char*) buf.ptr; -} -#endif diff --git a/src/jdk.pack/share/native/common-unpack/coding.h b/src/jdk.pack/share/native/common-unpack/coding.h deleted file mode 100644 index 2ff235f679e..00000000000 --- a/src/jdk.pack/share/native/common-unpack/coding.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -struct unpacker; - -#define INT_MAX_VALUE ((int)0x7FFFFFFF) -#define INT_MIN_VALUE ((int)0x80000000) - -#define CODING_SPEC(B, H, S, D) ((B)<<20|(H)<<8|(S)<<4|(D)<<0) -#define CODING_B(x) ((x)>>20 & 0xF) -#define CODING_H(x) ((x)>>8 & 0xFFF) -#define CODING_S(x) ((x)>>4 & 0xF) -#define CODING_D(x) ((x)>>0 & 0xF) - -#define CODING_INIT(B, H, S, D) \ - { CODING_SPEC(B, H, S, D) , 0, 0, 0, 0, 0, 0, 0, 0} - -// For debugging purposes, some compilers do not like this and will complain. -// #define long do_not_use_C_long_types_use_jlong_or_int -// Use of the type "long" is problematic, do not use it. - -struct coding { - int spec; // B,H,S,D - - // Handy values derived from the spec: - int B() { return CODING_B(spec); } - int H() { return CODING_H(spec); } - int S() { return CODING_S(spec); } - int D() { return CODING_D(spec); } - int L() { return 256-CODING_H(spec); } - int min, max; - int umin, umax; - char isSigned, isSubrange, isFullRange, isMalloc; - - coding* init(); // returns self or null if error - coding* initFrom(int spec_) { - assert(this->spec == 0); - this->spec = spec_; - return init(); - } - - static coding* findBySpec(int spec); - static coding* findBySpec(int B, int H, int S=0, int D=0); - static coding* findByIndex(int irregularCodingIndex); - - static uint parse(byte* &rp, int B, int H); - static uint parse_lgH(byte* &rp, int B, int H, int lgH); - static void parseMultiple(byte* &rp, int N, byte* limit, int B, int H); - - uint parse(byte* &rp) { - return parse(rp, CODING_B(spec), CODING_H(spec)); - } - void parseMultiple(byte* &rp, int N, byte* limit) { - parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec)); - } - - bool canRepresent(int x) { return (x >= min && x <= max); } - bool canRepresentUnsigned(int x) { return (x >= umin && x <= umax); } - - int sumInUnsignedRange(int x, int y); - - int readFrom(byte* &rpVar, int* dbase); - void readArrayFrom(byte* &rpVar, int* dbase, int length, int* values); - void skipArrayFrom(byte* &rpVar, int length) { - readArrayFrom(rpVar, (int*)NULL, length, (int*)NULL); - } - -#ifndef PRODUCT - const char* string(); -#endif - - void free(); // free self if isMalloc - - // error handling - static void abort(const char* msg = null) { unpack_abort(msg); } -}; - -enum coding_method_kind { - cmk_ERROR, - cmk_BHS, - cmk_BHS0, - cmk_BHS1, - cmk_BHSD1, - cmk_BHS1D1full, // isFullRange - cmk_BHS1D1sub, // isSubRange - - // special cases hand-optimized (~50% of all decoded values) - cmk_BYTE1, //(1,256) 6% - cmk_CHAR3, //(3,128) 7% - cmk_UNSIGNED5, //(5,64) 13% - cmk_DELTA5, //(5,64,1,1) 5% - cmk_BCI5, //(5,4) 18% - cmk_BRANCH5, //(5,4,2) 4% -//cmk_UNSIGNED5H16, //(5,16) 5% -//cmk_UNSIGNED2H4, //(2,4) 6% -//cmk_DELTA4H8, //(4,8,1,1) 10% -//cmk_DELTA3H16, //(3,16,1,1) 9% - cmk_BHS_LIMIT, - - cmk_pop, - cmk_pop_BHS0, - cmk_pop_BYTE1, - cmk_pop_LIMIT, - - cmk_LIMIT -}; - -enum { - BYTE1_spec = CODING_SPEC(1, 256, 0, 0), - CHAR3_spec = CODING_SPEC(3, 128, 0, 0), - UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0), - UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0), - SIGNED5_spec = CODING_SPEC(5, 64, 1, 0), - DELTA5_spec = CODING_SPEC(5, 64, 1, 1), - UDELTA5_spec = CODING_SPEC(5, 64, 0, 1), - MDELTA5_spec = CODING_SPEC(5, 64, 2, 1), - BCI5_spec = CODING_SPEC(5, 4, 0, 0), - BRANCH5_spec = CODING_SPEC(5, 4, 2, 0) -}; - -enum { - B_MAX = 5, - C_SLOP = B_MAX*10 -}; - -struct coding_method; - -// iterator under the control of a meta-coding -struct value_stream { - // current coding of values or values - coding c; // B,H,S,D,etc. - coding_method_kind cmk; // type of decoding needed - byte* rp; // read pointer - byte* rplimit; // final value of read pointer - int sum; // partial sum of all values so far (D=1 only) - coding_method* cm; // coding method that defines this stream - - void init(byte* band_rp, byte* band_limit, coding* defc); - void init(byte* band_rp, byte* band_limit, int spec) - { init(band_rp, band_limit, coding::findBySpec(spec)); } - - void setCoding(coding* c); - void setCoding(int spec) { setCoding(coding::findBySpec(spec)); } - - // Parse and decode a single value. - int getInt(); - - // Parse and decode a single byte, with no error checks. - int getByte() { - assert(cmk == cmk_BYTE1); - assert(rp < rplimit); - return *rp++ & 0xFF; - } - - // Used only for asserts. - bool hasValue(); - - void done() { assert(!hasValue()); } - - // Sometimes a value stream has an auxiliary (but there are never two). - value_stream* helper() { - assert(hasHelper()); - return this+1; - } - bool hasHelper(); - - // error handling - // inline void abort(const char* msg); - // inline void aborting(); -}; - -struct coding_method { - value_stream vs0; // initial state snapshot (vs.meta==this) - - coding_method* next; // what to do when we run out of bytes - - // these fields are used for pop codes only: - int* fValues; // favored value array - int fVlength; // maximum favored value token - coding_method* uValues; // unfavored value stream - - // pointer to outer unpacker, for error checks etc. - unpacker* u; - - // Initialize a value stream. - void reset(value_stream* state); - - // Parse a band header, size a band, and initialize for further action. - // band_rp advances (but not past band_limit), and meta_rp advances. - // The mode gives context, such as "inside a pop". - // The defc and N are the incoming parameters to a meta-coding. - // The value sink is used to collect output values, when desired. - void init(byte* &band_rp, byte* band_limit, - byte* &meta_rp, int mode, - coding* defc, int N, - intlist* valueSink); - - // error handling - void abort(const char* msg) { unpack_abort(msg, u); } - bool aborting() { return unpack_aborting(u); } -}; - -//inline void value_stream::abort(const char* msg) { cm->abort(msg); } -//inline void value_stream::aborting() { cm->aborting(); } diff --git a/src/jdk.pack/share/native/common-unpack/constants.h b/src/jdk.pack/share/native/common-unpack/constants.h deleted file mode 100644 index 6fc34f75a08..00000000000 --- a/src/jdk.pack/share/native/common-unpack/constants.h +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// classfile constants -#define JAVA_MAGIC 0xCAFEBABE - -// Class version history, refer to Constants.java - -// package file constants -#define JAVA_PACKAGE_MAGIC 0xCAFED00D -#define JAVA5_PACKAGE_MAJOR_VERSION 150 -#define JAVA5_PACKAGE_MINOR_VERSION 7 - -#define JAVA6_PACKAGE_MAJOR_VERSION 160 -#define JAVA6_PACKAGE_MINOR_VERSION 1 - -#define JAVA7_PACKAGE_MAJOR_VERSION 170 -#define JAVA7_PACKAGE_MINOR_VERSION 1 - -#define JAVA8_PACKAGE_MAJOR_VERSION 171 -#define JAVA8_PACKAGE_MINOR_VERSION 0 - -// magic number for gzip streams (for processing pack200-gzip data) -#define GZIP_MAGIC 0x1F8B0800 -#define GZIP_MAGIC_MASK 0xFFFFFF00 // last byte is variable "flg" field - -enum { - CONSTANT_None = 0, - CONSTANT_Utf8 = 1, - CONSTANT_unused = 2, /* unused, was Unicode */ - CONSTANT_Integer = 3, - CONSTANT_Float = 4, - CONSTANT_Long = 5, - CONSTANT_Double = 6, - CONSTANT_Class = 7, - CONSTANT_String = 8, - CONSTANT_Fieldref = 9, - CONSTANT_Methodref = 10, - CONSTANT_InterfaceMethodref = 11, - CONSTANT_NameandType = 12, - CONSTANT_unused13 = 13, - CONSTANT_unused14 = 14, - CONSTANT_MethodHandle = 15, - CONSTANT_MethodType = 16, - CONSTANT_unused17 = 17, - CONSTANT_InvokeDynamic = 18, - CONSTANT_Limit = 19, - CONSTANT_Signature = CONSTANT_unused13, - CONSTANT_BootstrapMethod = CONSTANT_unused17, // used only for InvokeDynamic - CONSTANT_All = 50, // combined global map - CONSTANT_LoadableValue = 51, // used for 'KL' and qldc operands - CONSTANT_AnyMember = 52, // union of refs to field or (interface) method - CONSTANT_FieldSpecific = 53, // used only for 'KQ' ConstantValue attrs - CONSTANT_GroupFirst = CONSTANT_All, // start group marker - CONSTANT_GroupLimit = 54, // end group marker - - // CONSTANT_MethodHandle reference kinds - REF_getField = 1, - REF_getStatic = 2, - REF_putField = 3, - REF_putStatic = 4, - REF_invokeVirtual = 5, - REF_invokeStatic = 6, - REF_invokeSpecial = 7, - REF_newInvokeSpecial = 8, - REF_invokeInterface = 9, - - SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag - - ACC_STATIC = 0x0008, - ACC_IC_LONG_FORM = (1<<16), //for ic_flags - - CLASS_ATTR_SourceFile = 17, - CLASS_ATTR_EnclosingMethod = 18, - CLASS_ATTR_InnerClasses = 23, - CLASS_ATTR_ClassFile_version = 24, - CLASS_ATTR_BootstrapMethods = 25, - FIELD_ATTR_ConstantValue = 17, - METHOD_ATTR_Code = 17, - METHOD_ATTR_Exceptions = 18, - METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23, - METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24, - METHOD_ATTR_AnnotationDefault = 25, - METHOD_ATTR_MethodParameters = 26, - CODE_ATTR_StackMapTable = 0, - CODE_ATTR_LineNumberTable = 1, - CODE_ATTR_LocalVariableTable = 2, - CODE_ATTR_LocalVariableTypeTable = 3, - //X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined - X_ATTR_Signature = 19, - X_ATTR_Deprecated = 20, - X_ATTR_RuntimeVisibleAnnotations = 21, - X_ATTR_RuntimeInvisibleAnnotations = 22, - X_ATTR_RuntimeVisibleTypeAnnotations = 27, - X_ATTR_RuntimeInvisibleTypeAnnotations = 28, - X_ATTR_OVERFLOW = 16, - X_ATTR_LIMIT_NO_FLAGS_HI = 32, - X_ATTR_LIMIT_FLAGS_HI = 63, - -#define O_ATTR_DO(F) \ - F(X_ATTR_OVERFLOW,01) \ - /*(end)*/ -#define X_ATTR_DO(F) \ - O_ATTR_DO(F) \ - F(X_ATTR_Signature,Signature) \ - F(X_ATTR_Deprecated,Deprecated) \ - F(X_ATTR_RuntimeVisibleAnnotations,RuntimeVisibleAnnotations) \ - F(X_ATTR_RuntimeInvisibleAnnotations,RuntimeInvisibleAnnotations) \ - F(X_ATTR_RuntimeVisibleTypeAnnotations,RuntimeVisibleTypeAnnotations) \ - F(X_ATTR_RuntimeInvisibleTypeAnnotations,RuntimeInvisibleTypeAnnotations) \ - /*F(X_ATTR_Synthetic,Synthetic)*/ \ - /*(end)*/ -#define CLASS_ATTR_DO(F) \ - F(CLASS_ATTR_SourceFile,SourceFile) \ - F(CLASS_ATTR_InnerClasses,InnerClasses) \ - F(CLASS_ATTR_EnclosingMethod,EnclosingMethod) \ - F(CLASS_ATTR_ClassFile_version,02) \ - F(CLASS_ATTR_BootstrapMethods,BootstrapMethods) \ - /*(end)*/ -#define FIELD_ATTR_DO(F) \ - F(FIELD_ATTR_ConstantValue,ConstantValue) \ - /*(end)*/ -#define METHOD_ATTR_DO(F) \ - F(METHOD_ATTR_Code,Code) \ - F(METHOD_ATTR_Exceptions,Exceptions) \ - F(METHOD_ATTR_RuntimeVisibleParameterAnnotations,RuntimeVisibleParameterAnnotations) \ - F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations,RuntimeInvisibleParameterAnnotations) \ - F(METHOD_ATTR_AnnotationDefault,AnnotationDefault) \ - F(METHOD_ATTR_MethodParameters,MethodParameters) \ - /*(end)*/ -#define CODE_ATTR_DO(F) \ - F(CODE_ATTR_StackMapTable,StackMapTable) \ - F(CODE_ATTR_LineNumberTable,LineNumberTable) \ - F(CODE_ATTR_LocalVariableTable,LocalVariableTable) \ - F(CODE_ATTR_LocalVariableTypeTable,LocalVariableTypeTable) \ - /*(end)*/ -#define ALL_ATTR_DO(F) \ - X_ATTR_DO(F) \ - CLASS_ATTR_DO(F) \ - FIELD_ATTR_DO(F) \ - METHOD_ATTR_DO(F) \ - CODE_ATTR_DO(F) \ - /*(end)*/ - - // attribute "context types" - ATTR_CONTEXT_CLASS = 0, - ATTR_CONTEXT_FIELD = 1, - ATTR_CONTEXT_METHOD = 2, - ATTR_CONTEXT_CODE = 3, - ATTR_CONTEXT_LIMIT = 4, - - // constants for parsed layouts (stored in band::le_kind) - EK_NONE = 0, // not a layout element - EK_INT = 'I', // B H I SH etc., also FH etc. - EK_BCI = 'P', // PH etc. - EK_BCID = 'Q', // POH etc. - EK_BCO = 'O', // OH etc. - EK_REPL = 'N', // NH[...] etc. - EK_REF = 'R', // RUH, RUNH, KQH, etc. - EK_UN = 'T', // TB(...)[...] etc. - EK_CASE = 'K', // (...)[...] etc. - EK_CALL = '(', // (0), (1), etc. - EK_CBLE = '[', // [...][...] etc. - NO_BAND_INDEX = -1, - - // File option bits, from LSB in ascending bit position. - FO_DEFLATE_HINT = 1<<0, - FO_IS_CLASS_STUB = 1<<1, - - // Archive option bits, from LSB in ascending bit position: - AO_HAVE_SPECIAL_FORMATS = 1<<0, - AO_HAVE_CP_NUMBERS = 1<<1, - AO_HAVE_ALL_CODE_FLAGS = 1<<2, - AO_HAVE_CP_EXTRAS = 1<<3, - AO_HAVE_FILE_HEADERS = 1<<4, - AO_DEFLATE_HINT = 1<<5, - AO_HAVE_FILE_MODTIME = 1<<6, - AO_HAVE_FILE_OPTIONS = 1<<7, - AO_HAVE_FILE_SIZE_HI = 1<<8, - AO_HAVE_CLASS_FLAGS_HI = 1<<9, - AO_HAVE_FIELD_FLAGS_HI = 1<<10, - AO_HAVE_METHOD_FLAGS_HI = 1<<11, - AO_HAVE_CODE_FLAGS_HI = 1<<12, - AO_UNUSED_MBZ = (int)((~0U)<<13), // options bits reserved for future use. - -#define ARCHIVE_BIT_DO(F) \ - F(AO_HAVE_SPECIAL_FORMATS) \ - F(AO_HAVE_CP_NUMBERS) \ - F(AO_HAVE_ALL_CODE_FLAGS) \ - F(AO_HAVE_CP_EXTRAS) \ - F(AO_HAVE_FILE_HEADERS) \ - F(AO_DEFLATE_HINT) \ - F(AO_HAVE_FILE_MODTIME) \ - F(AO_HAVE_FILE_OPTIONS) \ - F(AO_HAVE_FILE_SIZE_HI) \ - F(AO_HAVE_CLASS_FLAGS_HI) \ - F(AO_HAVE_FIELD_FLAGS_HI) \ - F(AO_HAVE_METHOD_FLAGS_HI) \ - F(AO_HAVE_CODE_FLAGS_HI) \ - /*(end)*/ - - // Constants for decoding attribute definition header bytes. - ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK) - ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB -#define ADH_BYTE(context, index) \ - ((((index) + ADH_BIT_IS_LSB)<> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB) - - NO_MODTIME = 0, // null modtime value - - // meta-coding - _meta_default = 0, - _meta_canon_min = 1, - _meta_canon_max = 115, - _meta_arb = 116, - _meta_run = 117, - _meta_pop = 141, - _meta_limit = 189, - _meta_error = 255, - - _xxx_1_end -}; - -// Bytecodes. - -enum { - bc_nop = 0, // 0x00 - bc_aconst_null = 1, // 0x01 - bc_iconst_m1 = 2, // 0x02 - bc_iconst_0 = 3, // 0x03 - bc_iconst_1 = 4, // 0x04 - bc_iconst_2 = 5, // 0x05 - bc_iconst_3 = 6, // 0x06 - bc_iconst_4 = 7, // 0x07 - bc_iconst_5 = 8, // 0x08 - bc_lconst_0 = 9, // 0x09 - bc_lconst_1 = 10, // 0x0a - bc_fconst_0 = 11, // 0x0b - bc_fconst_1 = 12, // 0x0c - bc_fconst_2 = 13, // 0x0d - bc_dconst_0 = 14, // 0x0e - bc_dconst_1 = 15, // 0x0f - bc_bipush = 16, // 0x10 - bc_sipush = 17, // 0x11 - bc_ldc = 18, // 0x12 - bc_ldc_w = 19, // 0x13 - bc_ldc2_w = 20, // 0x14 - bc_iload = 21, // 0x15 - bc_lload = 22, // 0x16 - bc_fload = 23, // 0x17 - bc_dload = 24, // 0x18 - bc_aload = 25, // 0x19 - bc_iload_0 = 26, // 0x1a - bc_iload_1 = 27, // 0x1b - bc_iload_2 = 28, // 0x1c - bc_iload_3 = 29, // 0x1d - bc_lload_0 = 30, // 0x1e - bc_lload_1 = 31, // 0x1f - bc_lload_2 = 32, // 0x20 - bc_lload_3 = 33, // 0x21 - bc_fload_0 = 34, // 0x22 - bc_fload_1 = 35, // 0x23 - bc_fload_2 = 36, // 0x24 - bc_fload_3 = 37, // 0x25 - bc_dload_0 = 38, // 0x26 - bc_dload_1 = 39, // 0x27 - bc_dload_2 = 40, // 0x28 - bc_dload_3 = 41, // 0x29 - bc_aload_0 = 42, // 0x2a - bc_aload_1 = 43, // 0x2b - bc_aload_2 = 44, // 0x2c - bc_aload_3 = 45, // 0x2d - bc_iaload = 46, // 0x2e - bc_laload = 47, // 0x2f - bc_faload = 48, // 0x30 - bc_daload = 49, // 0x31 - bc_aaload = 50, // 0x32 - bc_baload = 51, // 0x33 - bc_caload = 52, // 0x34 - bc_saload = 53, // 0x35 - bc_istore = 54, // 0x36 - bc_lstore = 55, // 0x37 - bc_fstore = 56, // 0x38 - bc_dstore = 57, // 0x39 - bc_astore = 58, // 0x3a - bc_istore_0 = 59, // 0x3b - bc_istore_1 = 60, // 0x3c - bc_istore_2 = 61, // 0x3d - bc_istore_3 = 62, // 0x3e - bc_lstore_0 = 63, // 0x3f - bc_lstore_1 = 64, // 0x40 - bc_lstore_2 = 65, // 0x41 - bc_lstore_3 = 66, // 0x42 - bc_fstore_0 = 67, // 0x43 - bc_fstore_1 = 68, // 0x44 - bc_fstore_2 = 69, // 0x45 - bc_fstore_3 = 70, // 0x46 - bc_dstore_0 = 71, // 0x47 - bc_dstore_1 = 72, // 0x48 - bc_dstore_2 = 73, // 0x49 - bc_dstore_3 = 74, // 0x4a - bc_astore_0 = 75, // 0x4b - bc_astore_1 = 76, // 0x4c - bc_astore_2 = 77, // 0x4d - bc_astore_3 = 78, // 0x4e - bc_iastore = 79, // 0x4f - bc_lastore = 80, // 0x50 - bc_fastore = 81, // 0x51 - bc_dastore = 82, // 0x52 - bc_aastore = 83, // 0x53 - bc_bastore = 84, // 0x54 - bc_castore = 85, // 0x55 - bc_sastore = 86, // 0x56 - bc_pop = 87, // 0x57 - bc_pop2 = 88, // 0x58 - bc_dup = 89, // 0x59 - bc_dup_x1 = 90, // 0x5a - bc_dup_x2 = 91, // 0x5b - bc_dup2 = 92, // 0x5c - bc_dup2_x1 = 93, // 0x5d - bc_dup2_x2 = 94, // 0x5e - bc_swap = 95, // 0x5f - bc_iadd = 96, // 0x60 - bc_ladd = 97, // 0x61 - bc_fadd = 98, // 0x62 - bc_dadd = 99, // 0x63 - bc_isub = 100, // 0x64 - bc_lsub = 101, // 0x65 - bc_fsub = 102, // 0x66 - bc_dsub = 103, // 0x67 - bc_imul = 104, // 0x68 - bc_lmul = 105, // 0x69 - bc_fmul = 106, // 0x6a - bc_dmul = 107, // 0x6b - bc_idiv = 108, // 0x6c - bc_ldiv = 109, // 0x6d - bc_fdiv = 110, // 0x6e - bc_ddiv = 111, // 0x6f - bc_irem = 112, // 0x70 - bc_lrem = 113, // 0x71 - bc_frem = 114, // 0x72 - bc_drem = 115, // 0x73 - bc_ineg = 116, // 0x74 - bc_lneg = 117, // 0x75 - bc_fneg = 118, // 0x76 - bc_dneg = 119, // 0x77 - bc_ishl = 120, // 0x78 - bc_lshl = 121, // 0x79 - bc_ishr = 122, // 0x7a - bc_lshr = 123, // 0x7b - bc_iushr = 124, // 0x7c - bc_lushr = 125, // 0x7d - bc_iand = 126, // 0x7e - bc_land = 127, // 0x7f - bc_ior = 128, // 0x80 - bc_lor = 129, // 0x81 - bc_ixor = 130, // 0x82 - bc_lxor = 131, // 0x83 - bc_iinc = 132, // 0x84 - bc_i2l = 133, // 0x85 - bc_i2f = 134, // 0x86 - bc_i2d = 135, // 0x87 - bc_l2i = 136, // 0x88 - bc_l2f = 137, // 0x89 - bc_l2d = 138, // 0x8a - bc_f2i = 139, // 0x8b - bc_f2l = 140, // 0x8c - bc_f2d = 141, // 0x8d - bc_d2i = 142, // 0x8e - bc_d2l = 143, // 0x8f - bc_d2f = 144, // 0x90 - bc_i2b = 145, // 0x91 - bc_i2c = 146, // 0x92 - bc_i2s = 147, // 0x93 - bc_lcmp = 148, // 0x94 - bc_fcmpl = 149, // 0x95 - bc_fcmpg = 150, // 0x96 - bc_dcmpl = 151, // 0x97 - bc_dcmpg = 152, // 0x98 - bc_ifeq = 153, // 0x99 - bc_ifne = 154, // 0x9a - bc_iflt = 155, // 0x9b - bc_ifge = 156, // 0x9c - bc_ifgt = 157, // 0x9d - bc_ifle = 158, // 0x9e - bc_if_icmpeq = 159, // 0x9f - bc_if_icmpne = 160, // 0xa0 - bc_if_icmplt = 161, // 0xa1 - bc_if_icmpge = 162, // 0xa2 - bc_if_icmpgt = 163, // 0xa3 - bc_if_icmple = 164, // 0xa4 - bc_if_acmpeq = 165, // 0xa5 - bc_if_acmpne = 166, // 0xa6 - bc_goto = 167, // 0xa7 - bc_jsr = 168, // 0xa8 - bc_ret = 169, // 0xa9 - bc_tableswitch = 170, // 0xaa - bc_lookupswitch = 171, // 0xab - bc_ireturn = 172, // 0xac - bc_lreturn = 173, // 0xad - bc_freturn = 174, // 0xae - bc_dreturn = 175, // 0xaf - bc_areturn = 176, // 0xb0 - bc_return = 177, // 0xb1 - bc_getstatic = 178, // 0xb2 - bc_putstatic = 179, // 0xb3 - bc_getfield = 180, // 0xb4 - bc_putfield = 181, // 0xb5 - bc_invokevirtual = 182, // 0xb6 - bc_invokespecial = 183, // 0xb7 - bc_invokestatic = 184, // 0xb8 - bc_invokeinterface = 185, // 0xb9 - bc_invokedynamic = 186, // 0xba - bc_new = 187, // 0xbb - bc_newarray = 188, // 0xbc - bc_anewarray = 189, // 0xbd - bc_arraylength = 190, // 0xbe - bc_athrow = 191, // 0xbf - bc_checkcast = 192, // 0xc0 - bc_instanceof = 193, // 0xc1 - bc_monitorenter = 194, // 0xc2 - bc_monitorexit = 195, // 0xc3 - bc_wide = 196, // 0xc4 - bc_multianewarray = 197, // 0xc5 - bc_ifnull = 198, // 0xc6 - bc_ifnonnull = 199, // 0xc7 - bc_goto_w = 200, // 0xc8 - bc_jsr_w = 201, // 0xc9 - bc_bytecode_limit = 202 // 0xca -}; - -enum { - bc_end_marker = 255, - bc_byte_escape = 254, - bc_ref_escape = 253, - - _first_linker_op = bc_getstatic, - _last_linker_op = bc_invokestatic, - _num_linker_ops = (_last_linker_op - _first_linker_op) + 1, - _self_linker_op = bc_bytecode_limit, - _self_linker_aload_flag = 1*_num_linker_ops, - _self_linker_super_flag = 2*_num_linker_ops, - _self_linker_limit = _self_linker_op + 4*_num_linker_ops, - - _invokeinit_op = _self_linker_limit, - _invokeinit_self_option = 0, - _invokeinit_super_option = 1, - _invokeinit_new_option = 2, - _invokeinit_limit = _invokeinit_op+3, - - _xldc_op = _invokeinit_limit, - bc_sldc = bc_ldc, // previously named bc_aldc - bc_cldc = _xldc_op+0, - bc_ildc = _xldc_op+1, - bc_fldc = _xldc_op+2, - bc_sldc_w = bc_ldc_w, // previously named bc_aldc_w - bc_cldc_w = _xldc_op+3, - bc_ildc_w = _xldc_op+4, - bc_fldc_w = _xldc_op+5, - bc_lldc2_w = bc_ldc2_w, - bc_dldc2_w = _xldc_op+6, - // anything other primitive, string, or class must be handled with qldc: - bc_qldc = _xldc_op+7, - bc_qldc_w = _xldc_op+8, - _xldc_limit = _xldc_op+9, - _invoke_int_op = _xldc_limit, - _invokespecial_int = _invoke_int_op+0, - _invokestatic_int = _invoke_int_op+1, - _invoke_int_limit = _invoke_int_op+2, - _xxx_3_end -}; diff --git a/src/jdk.pack/share/native/common-unpack/defines.h b/src/jdk.pack/share/native/common-unpack/defines.h deleted file mode 100644 index e2235fb7a1f..00000000000 --- a/src/jdk.pack/share/native/common-unpack/defines.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// random definitions - -#ifdef _MSC_VER -#include -#include -#else -#include -#endif - -#ifndef NO_ZLIB -#include -#endif - -#ifndef FULL -#define FULL 1 /* Adds <500 bytes to the zipped final product. */ -#endif - -#if FULL // define this if you want debugging and/or compile-time attributes -#define IF_FULL(x) x -#else -#define IF_FULL(x) /*x*/ -#endif - -#ifdef PRODUCT -#define IF_PRODUCT(xxx) xxx -#define NOT_PRODUCT(xxx) -#define assert(p) -#define PRINTCR(args) -#define VERSION_STRING "%s version %s\n" -#else -#define IF_PRODUCT(xxx) -#define NOT_PRODUCT(xxx) xxx -#define assert(p) ((p) || assert_failed(#p)) -#define PRINTCR(args) u->verbose && u->printcr_if_verbose args -#define VERSION_STRING "%s version non-product %s\n" -extern "C" void breakpoint(); -extern int assert_failed(const char*); -#define BREAK (breakpoint()) -#endif - -// Build-time control of some C++ inlining. -// To make a slightly faster smaller binary, say "CC -Dmaybe_inline=inline" -#ifndef maybe_inline -#define maybe_inline /*inline*/ -#endif -// By marking larger member functions inline, we remove external linkage. -#ifndef local_inline -#define local_inline inline -#endif - -// Error messages that we have -#define ERROR_ENOMEM "Native allocation failed" -#define ERROR_FORMAT "Corrupted pack file" -#define ERROR_RESOURCE "Cannot extract resource file" -#define ERROR_OVERFLOW "Internal buffer overflow" -#define ERROR_INTERNAL "Internal error" -#define ERROR_INIT "cannot init class members" - -#define LOGFILE_STDOUT "-" -#define LOGFILE_STDERR "" - -#define lengthof(array) (sizeof(array)/sizeof(array[0])) - -#define NEW(T, n) (T*) must_malloc((int)(scale_size(n, sizeof(T)))) -#define U_NEW(T, n) (T*) u->alloc(scale_size(n, sizeof(T))) -#define T_NEW(T, n) (T*) u->temp_alloc(scale_size(n, sizeof(T))) - -// Dealing with big-endian arch -#ifdef _BIG_ENDIAN -#define SWAP_INT(a) (((a>>24)&0xff) | ((a<<8)&0xff0000) | ((a>>8)&0xff00) | ((a<<24)&0xff000000)) -#else -#define SWAP_INT(a) (a) -#endif - -// bytes and byte arrays - -typedef unsigned int uint; -#if defined(NO_ZLIB) -#ifdef _LP64 -typedef unsigned int uLong; // Historical zlib, should be 32-bit. -#else -typedef unsigned long uLong; -#endif -#endif -#ifdef _MSC_VER -typedef LONGLONG jlong; -typedef DWORDLONG julong; -#define MKDIR(dir) mkdir(dir) -#define getpid() _getpid() -#define PATH_MAX MAX_PATH -#define dup2(a,b) _dup2(a,b) -#define strcasecmp(s1, s2) _stricmp(s1,s2) -#define tempname _tempname -#define sleep Sleep -#define snprintf _snprintf -#define PATH_SEPARATOR '\\' -#else -typedef signed char byte; -#ifdef _LP64 -typedef long jlong; -typedef long unsigned julong; -#else -typedef long long jlong; -typedef long long unsigned julong; -#endif -#define MKDIR(dir) mkdir(dir, 0777); -#define PATH_SEPARATOR '/' -#endif - -#ifdef OLDCC -typedef int bool; -enum { false, true }; -#endif - -#define null (0) - -/* Must cast to void *, then size_t, then int. */ -#define ptrlowbits(x) ((int)(size_t)(void*)(x)) - -/* Back and forth from jlong to pointer */ -#define ptr2jlong(x) ((jlong)(size_t)(void*)(x)) -#define jlong2ptr(x) ((void*)(size_t)(x)) - -// Keys used by Java: -#define UNPACK_DEFLATE_HINT "unpack.deflate.hint" - -#define COM_PREFIX "com.sun.java.util.jar.pack." -#define UNPACK_MODIFICATION_TIME COM_PREFIX"unpack.modification.time" -#define DEBUG_VERBOSE COM_PREFIX"verbose" - -#define ZIP_ARCHIVE_MARKER_COMMENT "PACK200" - -// The following are not known to the Java classes: -#define UNPACK_LOG_FILE COM_PREFIX"unpack.log.file" -#define UNPACK_REMOVE_PACKFILE COM_PREFIX"unpack.remove.packfile" - - -// Called from unpacker layers -#define _CHECK_DO(t,x) { if (t) {x;} } - -#define CHECK _CHECK_DO(aborting(), return) -#define CHECK_(y) _CHECK_DO(aborting(), return y) -#define CHECK_0 _CHECK_DO(aborting(), return 0) - -#define CHECK_COUNT(t) if (t < 0){abort("bad value count");} CHECK - -#define STR_TRUE "true" -#define STR_FALSE "false" - -#define STR_TF(x) ((x) ? STR_TRUE : STR_FALSE) -#define BOOL_TF(x) (((x) != null && strcmp((x),STR_TRUE) == 0) ? true : false) - -#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT diff --git a/src/jdk.pack/share/native/common-unpack/unpack.cpp b/src/jdk.pack/share/native/common-unpack/unpack.cpp deleted file mode 100644 index a19938f3cdd..00000000000 --- a/src/jdk.pack/share/native/common-unpack/unpack.cpp +++ /dev/null @@ -1,5250 +0,0 @@ -/* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -// -*- C++ -*- -// Program for unpacking specially compressed Java packages. -// John R. Rose - -/* - * When compiling for a 64bit LP64 system (longs and pointers being 64bits), - * the printf format %ld is correct and use of %lld will cause warning - * errors from some compilers (gcc/g++). - * _LP64 can be explicitly set (used on Linux). - * Should be checking for the Visual C++ since the _LP64 is set on the 64-bit - * systems but the correct format prefix for 64-bit integers is ll. - * Solaris compilers will define __sparcv9 or __x86_64 on 64bit compilations. - */ -#if !defined (_MSC_VER) && \ - (defined(_LP64) || defined(__sparcv9) || defined(__x86_64)) - #define LONG_LONG_FORMAT "%ld" - #define LONG_LONG_HEX_FORMAT "%lx" -#else - #define LONG_LONG_FORMAT "%lld" - #define LONG_LONG_HEX_FORMAT "%016llx" -#endif - -#include - -#include -#include -#include -#include - -#include -#include - - - - -#include "defines.h" -#include "bytes.h" -#include "utils.h" -#include "coding.h" -#include "bands.h" - -#include "constants.h" - -#include "zip.h" - -#include "unpack.h" - -#define STATIC_ASSERT(COND) typedef char static_assertion[(COND)?1:-1] - -// tags, in canonical order: -static const byte TAGS_IN_ORDER[] = { - CONSTANT_Utf8, - CONSTANT_Integer, - CONSTANT_Float, - CONSTANT_Long, - CONSTANT_Double, - CONSTANT_String, - CONSTANT_Class, - CONSTANT_Signature, - CONSTANT_NameandType, - CONSTANT_Fieldref, - CONSTANT_Methodref, - CONSTANT_InterfaceMethodref, - // constants defined as of JDK 7 - CONSTANT_MethodHandle, - CONSTANT_MethodType, - CONSTANT_BootstrapMethod, - CONSTANT_InvokeDynamic -}; -#define N_TAGS_IN_ORDER (sizeof TAGS_IN_ORDER) - -#ifndef PRODUCT -static const char* TAG_NAME[] = { - "*None", - "Utf8", - "*Unicode", - "Integer", - "Float", - "Long", - "Double", - "Class", - "String", - "Fieldref", - "Methodref", - "InterfaceMethodref", - "NameandType", - "*Signature", - "unused14", - "MethodHandle", - "MethodType", - "*BootstrapMethod", - "InvokeDynamic", - 0 -}; - -static const char* ATTR_CONTEXT_NAME[] = { // match ATTR_CONTEXT_NAME, etc. - "class", "field", "method", "code" -}; - -#else - -#define ATTR_CONTEXT_NAME ((const char**)null) - -#endif - -// Note that REQUESTED_LDC comes first, then the normal REQUESTED, -// in the regular constant pool. -enum { REQUESTED_NONE = -1, - // The codes below REQUESTED_NONE are in constant pool output order, - // for the sake of outputEntry_cmp: - REQUESTED_LDC = -99, REQUESTED -}; - -#define NO_INORD ((uint)-1) - -struct entry { - byte tag; - - #if 0 - byte bits; - enum { - //EB_EXTRA = 1, - EB_SUPER = 2 - }; - #endif - unsigned short nrefs; // pack w/ tag - - int outputIndex; - uint inord; // &cp.entries[cp.tag_base[this->tag]+this->inord] == this - - entry* *refs; - - // put last to pack best - union { - bytes b; - int i; - jlong l; - } value; - - void requestOutputIndex(cpool& cp, int req = REQUESTED); - int getOutputIndex() { - assert(outputIndex > REQUESTED_NONE); - return outputIndex; - } - - entry* ref(int refnum) { - assert((uint)refnum < nrefs); - return refs[refnum]; - } - - const char* utf8String() { - assert(tagMatches(CONSTANT_Utf8)); - if (value.b.len != strlen((const char*)value.b.ptr)) { - unpack_abort("bad utf8 encoding"); - // and fall through - } - return (const char*)value.b.ptr; - } - - entry* className() { - assert(tagMatches(CONSTANT_Class)); - return ref(0); - } - - entry* memberClass() { - assert(tagMatches(CONSTANT_AnyMember)); - return ref(0); - } - - entry* memberDescr() { - assert(tagMatches(CONSTANT_AnyMember)); - return ref(1); - } - - entry* descrName() { - assert(tagMatches(CONSTANT_NameandType)); - return ref(0); - } - - entry* descrType() { - assert(tagMatches(CONSTANT_NameandType)); - return ref(1); - } - - int typeSize(); - - bytes& asUtf8(); - int asInteger() { assert(tag == CONSTANT_Integer); return value.i; } - - bool isUtf8(bytes& b) { return tagMatches(CONSTANT_Utf8) && value.b.equals(b); } - - bool isDoubleWord() { return tag == CONSTANT_Double || tag == CONSTANT_Long; } - - bool tagMatches(byte tag2) { - return (tag2 == tag) - || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature) - #ifndef PRODUCT - || (tag2 == CONSTANT_FieldSpecific - && tag >= CONSTANT_Integer && tag <= CONSTANT_String && tag != CONSTANT_Class) - || (tag2 == CONSTANT_AnyMember - && tag >= CONSTANT_Fieldref && tag <= CONSTANT_InterfaceMethodref) - #endif - ; - } - -#ifdef PRODUCT - const char* string() { return NULL; } -#else - const char* string(); // see far below -#endif -}; - -entry* cpindex::get(uint i) { - if (i >= len) - return null; - else if (base1 != null) - // primary index - return &base1[i]; - else - // secondary index - return base2[i]; -} - -inline bytes& entry::asUtf8() { - assert(tagMatches(CONSTANT_Utf8)); - return value.b; -} - -int entry::typeSize() { - assert(tagMatches(CONSTANT_Utf8)); - const char* sigp = (char*) value.b.ptr; - switch (*sigp) { - case '(': sigp++; break; // skip opening '(' - case 'D': - case 'J': return 2; // double field - default: return 1; // field - } - int siglen = 0; - for (;;) { - int ch = *sigp++; - switch (ch) { - case 'D': case 'J': - siglen += 1; - break; - case '[': - // Skip rest of array info. - while (ch == '[') { ch = *sigp++; } - if (ch != 'L') break; - // else fall through - case 'L': - sigp = strchr(sigp, ';'); - if (sigp == null) { - unpack_abort("bad data"); - return 0; - } - sigp += 1; - break; - case ')': // closing ')' - return siglen; - } - siglen += 1; - } -} - -inline cpindex* cpool::getFieldIndex(entry* classRef) { - if (classRef == NULL) { abort("missing class reference"); return NULL; } - assert(classRef->tagMatches(CONSTANT_Class)); - assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); - return &member_indexes[classRef->inord*2+0]; -} -inline cpindex* cpool::getMethodIndex(entry* classRef) { - if (classRef == NULL) { abort("missing class reference"); return NULL; } - assert(classRef->tagMatches(CONSTANT_Class)); - assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); - return &member_indexes[classRef->inord*2+1]; -} - -struct inner_class { - entry* inner; - entry* outer; - entry* name; - int flags; - inner_class* next_sibling; - bool requested; -}; - -// Here is where everything gets deallocated: -void unpacker::free() { - int i; - assert(jniobj == null); // caller resp. - assert(infileptr == null); // caller resp. - if (jarout != null) jarout->reset(); - if (gzin != null) { gzin->free(); gzin = null; } - if (free_input) input.free(); - // free everybody ever allocated with U_NEW or (recently) with T_NEW - assert(smallbuf.base() == null || mallocs.contains(smallbuf.base())); - assert(tsmallbuf.base() == null || tmallocs.contains(tsmallbuf.base())); - mallocs.freeAll(); - tmallocs.freeAll(); - smallbuf.init(); - tsmallbuf.init(); - bcimap.free(); - class_fixup_type.free(); - class_fixup_offset.free(); - class_fixup_ref.free(); - code_fixup_type.free(); - code_fixup_offset.free(); - code_fixup_source.free(); - requested_ics.free(); - cp.requested_bsms.free(); - cur_classfile_head.free(); - cur_classfile_tail.free(); - for (i = 0; i < ATTR_CONTEXT_LIMIT; i++) - attr_defs[i].free(); - - // free CP state - cp.outputEntries.free(); - for (i = 0; i < CONSTANT_Limit; i++) - cp.tag_extras[i].free(); -} - -// input handling -// Attempts to advance rplimit so that (rplimit-rp) is at least 'more'. -// Will eagerly read ahead by larger chunks, if possible. -// Returns false if (rplimit-rp) is not at least 'more', -// unless rplimit hits input.limit(). -bool unpacker::ensure_input(jlong more) { - julong want = more - input_remaining(); - if ((jlong)want <= 0) return true; // it's already in the buffer - if (rplimit == input.limit()) return true; // not expecting any more - - if (read_input_fn == null) { - // assume it is already all there - bytes_read += input.limit() - rplimit; - rplimit = input.limit(); - return true; - } - CHECK_0; - - julong remaining = (input.limit() - rplimit); // how much left to read? - byte* rpgoal = (want >= remaining)? input.limit(): rplimit + (size_t)want; - enum { CHUNK_SIZE = (1<<14) }; - julong fetch = want; - if (fetch < CHUNK_SIZE) - fetch = CHUNK_SIZE; - if (fetch > remaining*3/4) - fetch = remaining; - // Try to fetch at least "more" bytes. - while ((jlong)fetch > 0) { - jlong nr = (*read_input_fn)(this, rplimit, fetch, remaining); - if (nr <= 0) { - return (rplimit >= rpgoal); - } - remaining -= nr; - rplimit += nr; - fetch -= nr; - bytes_read += nr; - assert(remaining == (julong)(input.limit() - rplimit)); - } - return true; -} - -// output handling - -fillbytes* unpacker::close_output(fillbytes* which) { - assert(wp != null); - if (which == null) { - if (wpbase == cur_classfile_head.base()) { - which = &cur_classfile_head; - } else { - which = &cur_classfile_tail; - } - } - assert(wpbase == which->base()); - assert(wplimit == which->end()); - which->setLimit(wp); - wp = null; - wplimit = null; - //wpbase = null; - return which; -} - -//maybe_inline -void unpacker::ensure_put_space(size_t size) { - if (wp + size <= wplimit) return; - // Determine which segment needs expanding. - fillbytes* which = close_output(); - byte* wp0 = which->grow(size); - wpbase = which->base(); - wplimit = which->end(); - wp = wp0; -} - -maybe_inline -byte* unpacker::put_space(size_t size) { - byte* wp0 = wp; - byte* wp1 = wp0 + size; - if (wp1 > wplimit) { - ensure_put_space(size); - wp0 = wp; - wp1 = wp0 + size; - } - wp = wp1; - return wp0; -} - -maybe_inline -void unpacker::putu2_at(byte* wp, int n) { - if (n != (unsigned short)n) { - unpack_abort(ERROR_OVERFLOW); - return; - } - wp[0] = (n) >> 8; - wp[1] = (n) >> 0; -} - -maybe_inline -void unpacker::putu4_at(byte* wp, int n) { - wp[0] = (n) >> 24; - wp[1] = (n) >> 16; - wp[2] = (n) >> 8; - wp[3] = (n) >> 0; -} - -maybe_inline -void unpacker::putu8_at(byte* wp, jlong n) { - putu4_at(wp+0, (int)((julong)n >> 32)); - putu4_at(wp+4, (int)((julong)n >> 0)); -} - -maybe_inline -void unpacker::putu2(int n) { - putu2_at(put_space(2), n); -} - -maybe_inline -void unpacker::putu4(int n) { - putu4_at(put_space(4), n); -} - -maybe_inline -void unpacker::putu8(jlong n) { - putu8_at(put_space(8), n); -} - -maybe_inline -int unpacker::putref_index(entry* e, int size) { - if (e == null) - return 0; - else if (e->outputIndex > REQUESTED_NONE) - return e->outputIndex; - else if (e->tag == CONSTANT_Signature) - return putref_index(e->ref(0), size); - else { - e->requestOutputIndex(cp, (size == 1 ? REQUESTED_LDC : REQUESTED)); - // Later on we'll fix the bits. - class_fixup_type.addByte(size); - class_fixup_offset.add((int)wpoffset()); - class_fixup_ref.add(e); -#ifdef PRODUCT - return 0; -#else - return 0x20+size; // 0x22 is easy to eyeball -#endif - } -} - -maybe_inline -void unpacker::putref(entry* e) { - int oidx = putref_index(e, 2); - putu2_at(put_space(2), oidx); -} - -maybe_inline -void unpacker::putu1ref(entry* e) { - int oidx = putref_index(e, 1); - putu1_at(put_space(1), oidx); -} - - -static int total_cp_size[] = {0, 0}; -static int largest_cp_ref[] = {0, 0}; -static int hash_probes[] = {0, 0}; - -// Allocation of small and large blocks. - -enum { CHUNK = (1 << 14), SMALL = (1 << 9) }; - -// Call malloc. Try to combine small blocks and free much later. -void* unpacker::alloc_heap(size_t size, bool smallOK, bool temp) { - if (!smallOK || size > SMALL) { - void* res = must_malloc((int)size); - (temp ? &tmallocs : &mallocs)->add(res); - return res; - } - fillbytes& xsmallbuf = *(temp ? &tsmallbuf : &smallbuf); - if (!xsmallbuf.canAppend(size+1)) { - xsmallbuf.init(CHUNK); - (temp ? &tmallocs : &mallocs)->add(xsmallbuf.base()); - } - int growBy = (int)size; - growBy += -growBy & 7; // round up mod 8 - return xsmallbuf.grow(growBy); -} - -maybe_inline -void unpacker::saveTo(bytes& b, byte* ptr, size_t len) { - b.ptr = U_NEW(byte, add_size(len,1)); - if (aborting()) { - b.len = 0; - return; - } - b.len = len; - b.copyFrom(ptr, len); -} - -bool testBit(int archive_options, int bitMask) { - return (archive_options & bitMask) != 0; -} - -// Read up through band_headers. -// Do the archive_size dance to set the size of the input mega-buffer. -void unpacker::read_file_header() { - // Read file header to determine file type and total size. - enum { - MAGIC_BYTES = 4, - AH_LENGTH_0 = 3, // archive_header_0 = {minver, majver, options} - AH_LENGTH_MIN = 15, // observed in spec {header_0[3], cp_counts[8], class_counts[4]} - AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes - AH_LENGTH = 30, //maximum archive header length (w/ all fields) - // Length contributions from optional header fields: - AH_LENGTH_S = 2, // archive_header_S = optional {size_hi, size_lo} - AH_ARCHIVE_SIZE_HI = 0, // offset in archive_header_S - AH_ARCHIVE_SIZE_LO = 1, // offset in archive_header_S - AH_FILE_HEADER_LEN = 5, // file_counts = {{size_hi, size_lo), next, modtile, files} - AH_SPECIAL_FORMAT_LEN = 2, // special_count = {layouts, band_headers} - AH_CP_NUMBER_LEN = 4, // cp_number_counts = {int, float, long, double} - AH_CP_EXTRA_LEN = 4, // cp_attr_counts = {MH, MT, InDy, BSM} - ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S, - FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN - }; - - STATIC_ASSERT(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic - // An absolute minimum null archive is magic[4], {minver,majver,options}[3], - // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes. - // (Note that archive_size is optional; it may be 0..10 bytes in length.) - // The first read must capture everything up through the options field. - // This happens to work even if {minver,majver,options} is a pathological - // 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes. - STATIC_ASSERT(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX); - - // Up through archive_size, the largest possible archive header is - // magic[4], {minver,majver,options}[4], archive_size[10]. - // (Note only the low 12 bits of options are allowed to be non-zero.) - // In order to parse archive_size, we need at least this many bytes - // in the first read. Of course, if archive_size_hi is more than - // a byte, we probably will fail to allocate the buffer, since it - // will be many gigabytes long. This is a practical, not an - // architectural limit to Pack200 archive sizes. - STATIC_ASSERT(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2*B_MAX); - - bool foreign_buf = (read_input_fn == null); - byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O - if (foreign_buf) { - // inbytes is all there is - input.set(inbytes); - rp = input.base(); - rplimit = input.limit(); - } else { - // inbytes, if not empty, contains some read-ahead we must use first - // ensure_input will take care of copying it into initbuf, - // then querying read_input_fn for any additional data needed. - // However, the caller must assume that we use up all of inbytes. - // There is no way to tell the caller that we used only part of them. - // Therefore, the caller must use only a bare minimum of read-ahead. - if (inbytes.len > FIRST_READ) { - abort("too much read-ahead"); - return; - } - input.set(initbuf, sizeof(initbuf)); - input.b.clear(); - input.b.copyFrom(inbytes); - rplimit = rp = input.base(); - rplimit += inbytes.len; - bytes_read += inbytes.len; - } - // Read only 19 bytes, which is certain to contain #archive_options fields, - // but is certain not to overflow past the archive_header. - input.b.len = FIRST_READ; - if (!ensure_input(FIRST_READ)) - abort("EOF reading archive magic number"); - - if (rp[0] == 'P' && rp[1] == 'K') { -#ifdef UNPACK_JNI - // Java driver must handle this case before we get this far. - abort("encountered a JAR header in unpacker"); -#else - // In the Unix-style program, we simply simulate a copy command. - // Copy until EOF; assume the JAR file is the last segment. - fprintf(errstrm, "Copy-mode.\n"); - for (;;) { - jarout->write_data(rp, (int)input_remaining()); - if (foreign_buf) - break; // one-time use of a passed in buffer - if (input.size() < CHUNK) { - // Get some breathing room. - input.set(U_NEW(byte, (size_t) CHUNK + C_SLOP), (size_t) CHUNK); - CHECK; - } - rp = rplimit = input.base(); - if (!ensure_input(1)) - break; - } - jarout->closeJarFile(false); -#endif - return; - } - - // Read the magic number. - magic = 0; - for (int i1 = 0; i1 < (int)sizeof(magic); i1++) { - magic <<= 8; - magic += (*rp++ & 0xFF); - } - - // Read the first 3 values from the header. - value_stream hdr; - int hdrVals = 0; - int hdrValsSkipped = 0; // for assert - hdr.init(rp, rplimit, UNSIGNED5_spec); - minver = hdr.getInt(); - majver = hdr.getInt(); - hdrVals += 2; - - int majmin[4][2] = { - {JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION}, - {JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION}, - {JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION}, - {JAVA8_PACKAGE_MAJOR_VERSION, JAVA8_PACKAGE_MINOR_VERSION} - }; - int majminfound = false; - for (int i = 0 ; i < 4 ; i++) { - if (majver == majmin[i][0] && minver == majmin[i][1]) { - majminfound = true; - break; - } - } - if (majminfound == null) { - char message[200]; - sprintf(message, "@" ERROR_FORMAT ": magic/ver = " - "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d OR %08X/%d.%d OR %08X/%d.%d\n", - magic, majver, minver, - JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION, - JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION, - JAVA_PACKAGE_MAGIC, JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION, - JAVA_PACKAGE_MAGIC, JAVA8_PACKAGE_MAJOR_VERSION, JAVA8_PACKAGE_MINOR_VERSION); - abort(message); - } - CHECK; - - archive_options = hdr.getInt(); - hdrVals += 1; - assert(hdrVals == AH_LENGTH_0); // first three fields only - bool haveSizeHi = testBit(archive_options, AO_HAVE_FILE_SIZE_HI); - bool haveModTime = testBit(archive_options, AO_HAVE_FILE_MODTIME); - bool haveFileOpt = testBit(archive_options, AO_HAVE_FILE_OPTIONS); - - bool haveSpecial = testBit(archive_options, AO_HAVE_SPECIAL_FORMATS); - bool haveFiles = testBit(archive_options, AO_HAVE_FILE_HEADERS); - bool haveNumbers = testBit(archive_options, AO_HAVE_CP_NUMBERS); - bool haveCPExtra = testBit(archive_options, AO_HAVE_CP_EXTRAS); - - if (majver < JAVA7_PACKAGE_MAJOR_VERSION) { - if (haveCPExtra) { - abort("Format bits for Java 7 must be zero in previous releases"); - return; - } - } - if (testBit(archive_options, AO_UNUSED_MBZ)) { - abort("High archive option bits are reserved and must be zero"); - return; - } - if (haveFiles) { - uint hi = hdr.getInt(); - uint lo = hdr.getInt(); - julong x = band::makeLong(hi, lo); - archive_size = (size_t) x; - if (archive_size != x) { - // Silly size specified; force overflow. - archive_size = PSIZE_MAX+1; - } - hdrVals += 2; - } else { - hdrValsSkipped += 2; - } - - // Now we can size the whole archive. - // Read everything else into a mega-buffer. - rp = hdr.rp; - size_t header_size_0 = (rp - input.base()); // used-up header (4byte + 3int) - size_t header_size_1 = (rplimit - rp); // buffered unused initial fragment - size_t header_size = header_size_0 + header_size_1; - unsized_bytes_read = header_size_0; - CHECK; - if (foreign_buf) { - if (archive_size > header_size_1) { - abort("EOF reading fixed input buffer"); - return; - } - } else if (archive_size != 0) { - if (archive_size < ARCHIVE_SIZE_MIN) { - abort("impossible archive size"); // bad input data - return; - } - if (archive_size < header_size_1) { - abort("too much read-ahead"); // somehow we pre-fetched too much? - return; - } - input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)), - header_size_0 + archive_size); - CHECK; - assert(input.limit()[0] == 0); - // Move all the bytes we read initially into the real buffer. - input.b.copyFrom(initbuf, header_size); - rp = input.b.ptr + header_size_0; - rplimit = input.b.ptr + header_size; - } else { - // It's more complicated and painful. - // A zero archive_size means that we must read until EOF. - input.init(CHUNK*2); - CHECK; - input.b.len = input.allocated; - rp = rplimit = input.base(); - // Set up input buffer as if we already read the header: - input.b.copyFrom(initbuf, header_size); - CHECK; - rplimit += header_size; - while (ensure_input(input.limit() - rp)) { - size_t dataSoFar = input_remaining(); - size_t nextSize = add_size(dataSoFar, CHUNK); - input.ensureSize(nextSize); - CHECK; - input.b.len = input.allocated; - rp = rplimit = input.base(); - rplimit += dataSoFar; - } - size_t dataSize = (rplimit - input.base()); - input.b.len = dataSize; - input.grow(C_SLOP); - CHECK; - free_input = true; // free it later - input.b.len = dataSize; - assert(input.limit()[0] == 0); - rp = rplimit = input.base(); - rplimit += dataSize; - rp += header_size_0; // already scanned these bytes... - } - live_input = true; // mark as "do not reuse" - if (aborting()) { - abort("cannot allocate large input buffer for package file"); - return; - } - - // read the rest of the header fields int assertSkipped = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; - int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; - if (haveSpecial) - remainingHeaders += AH_SPECIAL_FORMAT_LEN; - if (haveFiles) - remainingHeaders += AH_FILE_HEADER_LEN; - if (haveNumbers) - remainingHeaders += AH_CP_NUMBER_LEN; - if (haveCPExtra) - remainingHeaders += AH_CP_EXTRA_LEN; - - ensure_input(remainingHeaders * B_MAX); - CHECK; - hdr.rp = rp; - hdr.rplimit = rplimit; - - if (haveFiles) { - archive_next_count = hdr.getInt(); - CHECK_COUNT(archive_next_count); - archive_modtime = hdr.getInt(); - file_count = hdr.getInt(); - CHECK_COUNT(file_count); - hdrVals += 3; - } else { - hdrValsSkipped += 3; - } - - if (haveSpecial) { - band_headers_size = hdr.getInt(); - CHECK_COUNT(band_headers_size); - attr_definition_count = hdr.getInt(); - CHECK_COUNT(attr_definition_count); - hdrVals += 2; - } else { - hdrValsSkipped += 2; - } - - int cp_counts[N_TAGS_IN_ORDER]; - for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++) { - if (!haveNumbers) { - switch (TAGS_IN_ORDER[k]) { - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_Long: - case CONSTANT_Double: - cp_counts[k] = 0; - hdrValsSkipped += 1; - continue; - } - } - if (!haveCPExtra) { - switch(TAGS_IN_ORDER[k]) { - case CONSTANT_MethodHandle: - case CONSTANT_MethodType: - case CONSTANT_InvokeDynamic: - case CONSTANT_BootstrapMethod: - cp_counts[k] = 0; - hdrValsSkipped += 1; - continue; - } - } - cp_counts[k] = hdr.getInt(); - CHECK_COUNT(cp_counts[k]); - hdrVals += 1; - } - - ic_count = hdr.getInt(); - CHECK_COUNT(ic_count); - default_class_minver = hdr.getInt(); - default_class_majver = hdr.getInt(); - class_count = hdr.getInt(); - CHECK_COUNT(class_count); - hdrVals += 4; - - // done with archive_header, time to reconcile to ensure - // we have read everything correctly - hdrVals += hdrValsSkipped; - assert(hdrVals == AH_LENGTH); - rp = hdr.rp; - if (rp > rplimit) - abort("EOF reading archive header"); - - // Now size the CP. -#ifndef PRODUCT - // bool x = (N_TAGS_IN_ORDER == CONSTANT_Limit); - // assert(x); -#endif //PRODUCT - cp.init(this, cp_counts); - CHECK; - - default_file_modtime = archive_modtime; - if (default_file_modtime == 0 && haveModTime) - default_file_modtime = DEFAULT_ARCHIVE_MODTIME; // taken from driver - if (testBit(archive_options, AO_DEFLATE_HINT)) - default_file_options |= FO_DEFLATE_HINT; - - // meta-bytes, if any, immediately follow archive header - //band_headers.readData(band_headers_size); - ensure_input(band_headers_size); - if (input_remaining() < (size_t)band_headers_size) { - abort("EOF reading band headers"); - return; - } - bytes band_headers; - // The "1+" allows an initial byte to be pushed on the front. - band_headers.set(1+U_NEW(byte, 1+band_headers_size+C_SLOP), - band_headers_size); - CHECK; - // Start scanning band headers here: - band_headers.copyFrom(rp, band_headers.len); - rp += band_headers.len; - assert(rp <= rplimit); - meta_rp = band_headers.ptr; - // Put evil meta-codes at the end of the band headers, - // so we are sure to throw an error if we run off the end. - bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error); -} - -void unpacker::finish() { - if (verbose >= 1) { - fprintf(errstrm, - "A total of " - LONG_LONG_FORMAT " bytes were read in %d segment(s).\n", - (bytes_read_before_reset+bytes_read), - segments_read_before_reset+1); - fprintf(errstrm, - "A total of " - LONG_LONG_FORMAT " file content bytes were written.\n", - (bytes_written_before_reset+bytes_written)); - fprintf(errstrm, - "A total of %d files (of which %d are classes) were written to output.\n", - files_written_before_reset+files_written, - classes_written_before_reset+classes_written); - } - if (jarout != null) - jarout->closeJarFile(true); - if (errstrm != null) { - if (errstrm == stdout || errstrm == stderr) { - fflush(errstrm); - } else { - fclose(errstrm); - } - errstrm = null; - errstrm_name = null; - } -} - - -// Cf. PackageReader.readConstantPoolCounts -void cpool::init(unpacker* u_, int counts[CONSTANT_Limit]) { - this->u = u_; - - // Fill-pointer for CP. - int next_entry = 0; - - // Size the constant pool: - for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++) { - byte tag = TAGS_IN_ORDER[k]; - int len = counts[k]; - tag_count[tag] = len; - tag_base[tag] = next_entry; - next_entry += len; - // Detect and defend against constant pool size overflow. - // (Pack200 forbids the sum of CP counts to exceed 2^29-1.) - enum { - CP_SIZE_LIMIT = (1<<29), - IMPLICIT_ENTRY_COUNT = 1 // empty Utf8 string - }; - if (len >= (1<<29) || len < 0 - || next_entry >= CP_SIZE_LIMIT+IMPLICIT_ENTRY_COUNT) { - abort("archive too large: constant pool limit exceeded"); - return; - } - } - - // Close off the end of the CP: - nentries = next_entry; - - // place a limit on future CP growth: - size_t generous = 0; - generous = add_size(generous, u->ic_count); // implicit name - generous = add_size(generous, u->ic_count); // outer - generous = add_size(generous, u->ic_count); // outer.utf8 - generous = add_size(generous, 40); // WKUs, misc - generous = add_size(generous, u->class_count); // implicit SourceFile strings - maxentries = (uint)add_size(nentries, generous); - - // Note that this CP does not include "empty" entries - // for longs and doubles. Those are introduced when - // the entries are renumbered for classfile output. - - entries = U_NEW(entry, maxentries); - CHECK; - - first_extra_entry = &entries[nentries]; - - // Initialize the standard indexes. - for (int tag = 0; tag < CONSTANT_Limit; tag++) { - entry* cpMap = &entries[tag_base[tag]]; - tag_index[tag].init(tag_count[tag], cpMap, tag); - } - - // Initialize *all* our entries once - for (uint i = 0 ; i < maxentries ; i++) { - entries[i].outputIndex = REQUESTED_NONE; - } - - initGroupIndexes(); - // Initialize hashTab to a generous power-of-two size. - uint pow2 = 1; - uint target = maxentries + maxentries/2; // 60% full - while (pow2 < target) pow2 <<= 1; - hashTab = U_NEW(entry*, hashTabLength = pow2); -} - -static byte* store_Utf8_char(byte* cp, unsigned short ch) { - if (ch >= 0x001 && ch <= 0x007F) { - *cp++ = (byte) ch; - } else if (ch <= 0x07FF) { - *cp++ = (byte) (0xC0 | ((ch >> 6) & 0x1F)); - *cp++ = (byte) (0x80 | ((ch >> 0) & 0x3F)); - } else { - *cp++ = (byte) (0xE0 | ((ch >> 12) & 0x0F)); - *cp++ = (byte) (0x80 | ((ch >> 6) & 0x3F)); - *cp++ = (byte) (0x80 | ((ch >> 0) & 0x3F)); - } - return cp; -} - -static byte* skip_Utf8_chars(byte* cp, int len) { - for (;; cp++) { - int ch = *cp & 0xFF; - if ((ch & 0xC0) != 0x80) { - if (len-- == 0) - return cp; - if (ch < 0x80 && len == 0) - return cp+1; - } - } -} - -static int compare_Utf8_chars(bytes& b1, bytes& b2) { - int l1 = (int)b1.len; - int l2 = (int)b2.len; - int l0 = (l1 < l2) ? l1 : l2; - byte* p1 = b1.ptr; - byte* p2 = b2.ptr; - int c0 = 0; - for (int i = 0; i < l0; i++) { - int c1 = p1[i] & 0xFF; - int c2 = p2[i] & 0xFF; - if (c1 != c2) { - // Before returning the obvious answer, - // check to see if c1 or c2 is part of a 0x0000, - // which encodes as {0xC0,0x80}. The 0x0000 is the - // lowest-sorting Java char value, and yet it encodes - // as if it were the first char after 0x7F, which causes - // strings containing nulls to sort too high. All other - // comparisons are consistent between Utf8 and Java chars. - if (c1 == 0xC0 && (p1[i+1] & 0xFF) == 0x80) c1 = 0; - if (c2 == 0xC0 && (p2[i+1] & 0xFF) == 0x80) c2 = 0; - if (c0 == 0xC0) { - assert(((c1|c2) & 0xC0) == 0x80); // c1 & c2 are extension chars - if (c1 == 0x80) c1 = 0; // will sort below c2 - if (c2 == 0x80) c2 = 0; // will sort below c1 - } - return c1 - c2; - } - c0 = c1; // save away previous char - } - // common prefix is identical; return length difference if any - return l1 - l2; -} - -// Cf. PackageReader.readUtf8Bands -local_inline -void unpacker::read_Utf8_values(entry* cpMap, int len) { - // Implicit first Utf8 string is the empty string. - enum { - // certain bands begin with implicit zeroes - PREFIX_SKIP_2 = 2, - SUFFIX_SKIP_1 = 1 - }; - - int i; - - // First band: Read lengths of shared prefixes. - if (len > PREFIX_SKIP_2) - cp_Utf8_prefix.readData(len - PREFIX_SKIP_2); - NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts - - // Second band: Read lengths of unshared suffixes: - if (len > SUFFIX_SKIP_1) - cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1); - NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts - - bytes* allsuffixes = T_NEW(bytes, len); - CHECK; - - int nbigsuf = 0; - fillbytes charbuf; // buffer to allocate small strings - charbuf.init(); - - // Third band: Read the char values in the unshared suffixes: - cp_Utf8_chars.readData(cp_Utf8_suffix.getIntTotal()); - for (i = 0; i < len; i++) { - int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); - if (suffix < 0) { - abort("bad utf8 suffix"); - return; - } - if (suffix == 0 && i >= SUFFIX_SKIP_1) { - // chars are packed in cp_Utf8_big_chars - nbigsuf += 1; - continue; - } - bytes& chars = allsuffixes[i]; - uint size3 = suffix * 3; // max Utf8 length - bool isMalloc = (suffix > SMALL); - if (isMalloc) { - chars.malloc(size3); - } else { - if (!charbuf.canAppend(size3+1)) { - assert(charbuf.allocated == 0 || tmallocs.contains(charbuf.base())); - charbuf.init(CHUNK); // Reset to new buffer. - tmallocs.add(charbuf.base()); - } - chars.set(charbuf.grow(size3+1), size3); - } - CHECK; - byte* chp = chars.ptr; - for (int j = 0; j < suffix; j++) { - unsigned short ch = cp_Utf8_chars.getInt(); - chp = store_Utf8_char(chp, ch); - } - // shrink to fit: - if (isMalloc) { - chars.realloc(chp - chars.ptr); - CHECK; - tmallocs.add(chars.ptr); // free it later - } else { - int shrink = (int)(chars.limit() - chp); - chars.len -= shrink; - charbuf.b.len -= shrink; // ungrow to reclaim buffer space - // Note that we did not reclaim the final '\0'. - assert(chars.limit() == charbuf.limit()-1); - assert(strlen((char*)chars.ptr) == chars.len); - } - } - //cp_Utf8_chars.done(); -#ifndef PRODUCT - charbuf.b.set(null, 0); // tidy -#endif - - // Fourth band: Go back and size the specially packed strings. - int maxlen = 0; - cp_Utf8_big_suffix.readData(nbigsuf); - cp_Utf8_suffix.rewind(); - for (i = 0; i < len; i++) { - int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); - int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); - if (prefix < 0 || prefix+suffix < 0) { - abort("bad utf8 prefix"); - return; - } - bytes& chars = allsuffixes[i]; - if (suffix == 0 && i >= SUFFIX_SKIP_1) { - suffix = cp_Utf8_big_suffix.getInt(); - assert(chars.ptr == null); - chars.len = suffix; // just a momentary hack - } else { - assert(chars.ptr != null); - } - if (maxlen < prefix + suffix) { - maxlen = prefix + suffix; - } - } - //cp_Utf8_suffix.done(); // will use allsuffixes[i].len (ptr!=null) - //cp_Utf8_big_suffix.done(); // will use allsuffixes[i].len - - // Fifth band(s): Get the specially packed characters. - cp_Utf8_big_suffix.rewind(); - for (i = 0; i < len; i++) { - bytes& chars = allsuffixes[i]; - if (chars.ptr != null) continue; // already input - int suffix = (int)chars.len; // pick up the hack - uint size3 = suffix * 3; - if (suffix == 0) continue; // done with empty string - chars.malloc(size3); - CHECK; - byte* chp = chars.ptr; - band saved_band = cp_Utf8_big_chars; - cp_Utf8_big_chars.readData(suffix); - CHECK; - for (int j = 0; j < suffix; j++) { - unsigned short ch = cp_Utf8_big_chars.getInt(); - CHECK; - chp = store_Utf8_char(chp, ch); - } - chars.realloc(chp - chars.ptr); - CHECK; - tmallocs.add(chars.ptr); // free it later - //cp_Utf8_big_chars.done(); - cp_Utf8_big_chars = saved_band; // reset the band for the next string - } - cp_Utf8_big_chars.readData(0); // zero chars - //cp_Utf8_big_chars.done(); - - // Finally, sew together all the prefixes and suffixes. - bytes bigbuf; - bigbuf.malloc(maxlen * 3 + 1); // max Utf8 length, plus slop for null - CHECK; - int prevlen = 0; // previous string length (in chars) - tmallocs.add(bigbuf.ptr); // free after this block - CHECK; - cp_Utf8_prefix.rewind(); - for (i = 0; i < len; i++) { - bytes& chars = allsuffixes[i]; - int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); - CHECK; - int suffix = (int)chars.len; - byte* fillp; - // by induction, the buffer is already filled with the prefix - // make sure the prefix value is not corrupted, though: - if (prefix > prevlen) { - abort("utf8 prefix overflow"); - return; - } - fillp = skip_Utf8_chars(bigbuf.ptr, prefix); - // copy the suffix into the same buffer: - fillp = chars.writeTo(fillp); - assert(bigbuf.inBounds(fillp)); - *fillp = 0; // bigbuf must contain a well-formed Utf8 string - int length = (int)(fillp - bigbuf.ptr); - bytes& value = cpMap[i].value.b; - value.set(U_NEW(byte, add_size(length,1)), length); - value.copyFrom(bigbuf.ptr, length); - CHECK; - // Index all Utf8 strings - entry* &htref = cp.hashTabRef(CONSTANT_Utf8, value); - if (htref == null) { - // Note that if two identical strings are transmitted, - // the first is taken to be the canonical one. - htref = &cpMap[i]; - } - prevlen = prefix + suffix; - } - //cp_Utf8_prefix.done(); - - // Free intermediate buffers. - free_temps(); -} - -local_inline -void unpacker::read_single_words(band& cp_band, entry* cpMap, int len) { - cp_band.readData(len); - for (int i = 0; i < len; i++) { - cpMap[i].value.i = cp_band.getInt(); // coding handles signs OK - } -} - -maybe_inline -void unpacker::read_double_words(band& cp_bands, entry* cpMap, int len) { - band& cp_band_hi = cp_bands; - band& cp_band_lo = cp_bands.nextBand(); - cp_band_hi.readData(len); - cp_band_lo.readData(len); - for (int i = 0; i < len; i++) { - cpMap[i].value.l = cp_band_hi.getLong(cp_band_lo, true); - } - //cp_band_hi.done(); - //cp_band_lo.done(); -} - -maybe_inline -void unpacker::read_single_refs(band& cp_band, byte refTag, entry* cpMap, int len) { - assert(refTag == CONSTANT_Utf8); - cp_band.setIndexByTag(refTag); - cp_band.readData(len); - CHECK; - int indexTag = (cp_band.bn == e_cp_Class) ? CONSTANT_Class : 0; - for (int i = 0; i < len; i++) { - entry& e = cpMap[i]; - e.refs = U_NEW(entry*, e.nrefs = 1); - entry* utf = cp_band.getRef(); - CHECK; - e.refs[0] = utf; - e.value.b = utf->value.b; // copy value of Utf8 string to self - if (indexTag != 0) { - // Maintain cross-reference: - entry* &htref = cp.hashTabRef(indexTag, e.value.b); - if (htref == null) { - // Note that if two identical classes are transmitted, - // the first is taken to be the canonical one. - htref = &e; - } - } - } - //cp_band.done(); -} - -maybe_inline -void unpacker::read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, - entry* cpMap, int len) { - band& cp_band1 = cp_band; - band& cp_band2 = cp_band.nextBand(); - cp_band1.setIndexByTag(ref1Tag); - cp_band2.setIndexByTag(ref2Tag); - cp_band1.readData(len); - cp_band2.readData(len); - CHECK; - for (int i = 0; i < len; i++) { - entry& e = cpMap[i]; - e.refs = U_NEW(entry*, e.nrefs = 2); - e.refs[0] = cp_band1.getRef(); - CHECK; - e.refs[1] = cp_band2.getRef(); - CHECK; - } - //cp_band1.done(); - //cp_band2.done(); -} - -// Cf. PackageReader.readSignatureBands -maybe_inline -void unpacker::read_signature_values(entry* cpMap, int len) { - cp_Signature_form.setIndexByTag(CONSTANT_Utf8); - cp_Signature_form.readData(len); - CHECK; - int ncTotal = 0; - int i; - for (i = 0; i < len; i++) { - entry& e = cpMap[i]; - entry& form = *cp_Signature_form.getRef(); - CHECK; - int nc = 0; - - for (int j = 0; j < (int)form.value.b.len; j++) { - int c = form.value.b.ptr[j]; - if (c == 'L') nc++; - } - ncTotal += nc; - e.refs = U_NEW(entry*, cpMap[i].nrefs = 1 + nc); - CHECK; - e.refs[0] = &form; - } - //cp_Signature_form.done(); - cp_Signature_classes.setIndexByTag(CONSTANT_Class); - cp_Signature_classes.readData(ncTotal); - for (i = 0; i < len; i++) { - entry& e = cpMap[i]; - for (int j = 1; j < e.nrefs; j++) { - e.refs[j] = cp_Signature_classes.getRef(); - CHECK; - } - } - //cp_Signature_classes.done(); -} - -maybe_inline -void unpacker::checkLegacy(const char* name) { - if (u->majver < JAVA7_PACKAGE_MAJOR_VERSION) { - char message[100]; - snprintf(message, 99, "unexpected band %s\n", name); - abort(message); - } -} - -maybe_inline -void unpacker::read_method_handle(entry* cpMap, int len) { - if (len > 0) { - checkLegacy(cp_MethodHandle_refkind.name); - } - cp_MethodHandle_refkind.readData(len); - cp_MethodHandle_member.setIndexByTag(CONSTANT_AnyMember); - cp_MethodHandle_member.readData(len); - for (int i = 0 ; i < len ; i++) { - entry& e = cpMap[i]; - e.value.i = cp_MethodHandle_refkind.getInt(); - e.refs = U_NEW(entry*, e.nrefs = 1); - e.refs[0] = cp_MethodHandle_member.getRef(); - CHECK; - } -} - -maybe_inline -void unpacker::read_method_type(entry* cpMap, int len) { - if (len > 0) { - checkLegacy(cp_MethodType.name); - } - cp_MethodType.setIndexByTag(CONSTANT_Signature); - cp_MethodType.readData(len); - for (int i = 0 ; i < len ; i++) { - entry& e = cpMap[i]; - e.refs = U_NEW(entry*, e.nrefs = 1); - e.refs[0] = cp_MethodType.getRef(); - CHECK; - } -} - -maybe_inline -void unpacker::read_bootstrap_methods(entry* cpMap, int len) { - if (len > 0) { - checkLegacy(cp_BootstrapMethod_ref.name); - } - cp_BootstrapMethod_ref.setIndexByTag(CONSTANT_MethodHandle); - cp_BootstrapMethod_ref.readData(len); - - cp_BootstrapMethod_arg_count.readData(len); - int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal(); - cp_BootstrapMethod_arg.setIndexByTag(CONSTANT_LoadableValue); - cp_BootstrapMethod_arg.readData(totalArgCount); - for (int i = 0; i < len; i++) { - entry& e = cpMap[i]; - int argc = cp_BootstrapMethod_arg_count.getInt(); - e.value.i = argc; - e.refs = U_NEW(entry*, e.nrefs = argc + 1); - e.refs[0] = cp_BootstrapMethod_ref.getRef(); - for (int j = 1 ; j < e.nrefs ; j++) { - e.refs[j] = cp_BootstrapMethod_arg.getRef(); - CHECK; - } - } -} -// Cf. PackageReader.readConstantPool -void unpacker::read_cp() { - byte* rp0 = rp; - - int i; - - for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++) { - byte tag = TAGS_IN_ORDER[k]; - int len = cp.tag_count[tag]; - int base = cp.tag_base[tag]; - - PRINTCR((1,"Reading %d %s entries...", len, NOT_PRODUCT(TAG_NAME[tag])+0)); - entry* cpMap = &cp.entries[base]; - for (i = 0; i < len; i++) { - cpMap[i].tag = tag; - cpMap[i].inord = i; - } - // Initialize the tag's CP index right away, since it might be needed - // in the next pass to initialize the CP for another tag. -#ifndef PRODUCT - cpindex* ix = &cp.tag_index[tag]; - assert(ix->ixTag == tag); - assert((int)ix->len == len); - assert(ix->base1 == cpMap); -#endif - - switch (tag) { - case CONSTANT_Utf8: - read_Utf8_values(cpMap, len); - break; - case CONSTANT_Integer: - read_single_words(cp_Int, cpMap, len); - break; - case CONSTANT_Float: - read_single_words(cp_Float, cpMap, len); - break; - case CONSTANT_Long: - read_double_words(cp_Long_hi /*& cp_Long_lo*/, cpMap, len); - break; - case CONSTANT_Double: - read_double_words(cp_Double_hi /*& cp_Double_lo*/, cpMap, len); - break; - case CONSTANT_String: - read_single_refs(cp_String, CONSTANT_Utf8, cpMap, len); - break; - case CONSTANT_Class: - read_single_refs(cp_Class, CONSTANT_Utf8, cpMap, len); - break; - case CONSTANT_Signature: - read_signature_values(cpMap, len); - break; - case CONSTANT_NameandType: - read_double_refs(cp_Descr_name /*& cp_Descr_type*/, - CONSTANT_Utf8, CONSTANT_Signature, - cpMap, len); - break; - case CONSTANT_Fieldref: - read_double_refs(cp_Field_class /*& cp_Field_desc*/, - CONSTANT_Class, CONSTANT_NameandType, - cpMap, len); - break; - case CONSTANT_Methodref: - read_double_refs(cp_Method_class /*& cp_Method_desc*/, - CONSTANT_Class, CONSTANT_NameandType, - cpMap, len); - break; - case CONSTANT_InterfaceMethodref: - read_double_refs(cp_Imethod_class /*& cp_Imethod_desc*/, - CONSTANT_Class, CONSTANT_NameandType, - cpMap, len); - break; - case CONSTANT_MethodHandle: - // consumes cp_MethodHandle_refkind and cp_MethodHandle_member - read_method_handle(cpMap, len); - break; - case CONSTANT_MethodType: - // consumes cp_MethodType - read_method_type(cpMap, len); - break; - case CONSTANT_InvokeDynamic: - read_double_refs(cp_InvokeDynamic_spec, CONSTANT_BootstrapMethod, - CONSTANT_NameandType, - cpMap, len); - break; - case CONSTANT_BootstrapMethod: - // consumes cp_BootstrapMethod_ref, cp_BootstrapMethod_arg_count and cp_BootstrapMethod_arg - read_bootstrap_methods(cpMap, len); - break; - default: - assert(false); - break; - } - CHECK; - } - - cp.expandSignatures(); - CHECK; - cp.initMemberIndexes(); - CHECK; - - PRINTCR((1,"parsed %d constant pool entries in %d bytes", cp.nentries, (rp - rp0))); - - #define SNAME(n,s) #s "\0" - const char* symNames = ( - ALL_ATTR_DO(SNAME) - "" - ); - #undef SNAME - - for (int sn = 0; sn < cpool::s_LIMIT; sn++) { - assert(symNames[0] >= '0' && symNames[0] <= 'Z'); // sanity - bytes name; name.set(symNames); - if (name.len > 0 && name.ptr[0] != '0') { - cp.sym[sn] = cp.ensureUtf8(name); - PRINTCR((4, "well-known sym %d=%s", sn, cp.sym[sn]->string())); - } - symNames += name.len + 1; // skip trailing null to next name - } - - band::initIndexes(this); -} - -static band* no_bands[] = { null }; // shared empty body - -inline -band& unpacker::attr_definitions::fixed_band(int e_class_xxx) { - return u->all_bands[xxx_flags_hi_bn + (e_class_xxx-e_class_flags_hi)]; -} -inline band& unpacker::attr_definitions::xxx_flags_hi() - { return fixed_band(e_class_flags_hi); } -inline band& unpacker::attr_definitions::xxx_flags_lo() - { return fixed_band(e_class_flags_lo); } -inline band& unpacker::attr_definitions::xxx_attr_count() - { return fixed_band(e_class_attr_count); } -inline band& unpacker::attr_definitions::xxx_attr_indexes() - { return fixed_band(e_class_attr_indexes); } -inline band& unpacker::attr_definitions::xxx_attr_calls() - { return fixed_band(e_class_attr_calls); } - - -inline -unpacker::layout_definition* -unpacker::attr_definitions::defineLayout(int idx, - entry* nameEntry, - const char* layout) { - const char* name = nameEntry->value.b.strval(); - layout_definition* lo = defineLayout(idx, name, layout); - CHECK_0; - lo->nameEntry = nameEntry; - return lo; -} - -unpacker::layout_definition* -unpacker::attr_definitions::defineLayout(int idx, - const char* name, - const char* layout) { - assert(flag_limit != 0); // must be set up already - if (idx >= 0) { - // Fixed attr. - if (idx >= (int)flag_limit) - abort("attribute index too large"); - if (isRedefined(idx)) - abort("redefined attribute index"); - redef |= ((julong)1<idx = idx; - lo->name = name; - lo->layout = layout; - for (int adds = (idx+1) - layouts.length(); adds > 0; adds--) { - layouts.add(null); - } - CHECK_0; - layouts.get(idx) = lo; - return lo; -} - -band** -unpacker::attr_definitions::buildBands(unpacker::layout_definition* lo) { - int i; - if (lo->elems != null) - return lo->bands(); - if (lo->layout[0] == '\0') { - lo->elems = no_bands; - } else { - // Create bands for this attribute by parsing the layout. - bool hasCallables = lo->hasCallables(); - bands_made = 0x10000; // base number for bands made - const char* lp = lo->layout; - lp = parseLayout(lp, lo->elems, -1); - CHECK_0; - if (lp[0] != '\0' || band_stack.length() > 0) { - abort("garbage at end of layout"); - } - band_stack.popTo(0); - CHECK_0; - - // Fix up callables to point at their callees. - band** bands = lo->elems; - assert(bands == lo->bands()); - int num_callables = 0; - if (hasCallables) { - while (bands[num_callables] != null) { - if (bands[num_callables]->le_kind != EK_CBLE) { - abort("garbage mixed with callables"); - break; - } - num_callables += 1; - } - } - for (i = 0; i < calls_to_link.length(); i++) { - band& call = *(band*) calls_to_link.get(i); - assert(call.le_kind == EK_CALL); - // Determine the callee. - int call_num = call.le_len; - if (call_num < 0 || call_num >= num_callables) { - abort("bad call in layout"); - break; - } - band& cble = *bands[call_num]; - // Link the call to it. - call.le_body[0] = &cble; - // Distinguish backward calls and callables: - assert(cble.le_kind == EK_CBLE); - assert(cble.le_len == call_num); - cble.le_back |= call.le_back; - } - calls_to_link.popTo(0); - } - return lo->elems; -} - -/* attribute layout language parser - - attribute_layout: - ( layout_element )* | ( callable )+ - layout_element: - ( integral | replication | union | call | reference ) - - callable: - '[' body ']' - body: - ( layout_element )+ - - integral: - ( unsigned_int | signed_int | bc_index | bc_offset | flag ) - unsigned_int: - uint_type - signed_int: - 'S' uint_type - any_int: - ( unsigned_int | signed_int ) - bc_index: - ( 'P' uint_type | 'PO' uint_type ) - bc_offset: - 'O' any_int - flag: - 'F' uint_type - uint_type: - ( 'B' | 'H' | 'I' | 'V' ) - - replication: - 'N' uint_type '[' body ']' - - union: - 'T' any_int (union_case)* '(' ')' '[' (body)? ']' - union_case: - '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']' - union_case_tag: - ( numeral | numeral '-' numeral ) - call: - '(' numeral ')' - - reference: - reference_type ( 'N' )? uint_type - reference_type: - ( constant_ref | schema_ref | utf8_ref | untyped_ref ) - constant_ref: - ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' ) - schema_ref: - ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' ) - utf8_ref: - 'RU' - untyped_ref: - 'RQ' - - numeral: - '(' ('-')? (digit)+ ')' - digit: - ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) - -*/ - -const char* -unpacker::attr_definitions::parseIntLayout(const char* lp, band* &res, - byte le_kind, bool can_be_signed) { - const char* lp0 = lp; - band* b = U_NEW(band, 1); - CHECK_(lp); - char le = *lp++; - int spec = UNSIGNED5_spec; - if (le == 'S' && can_be_signed) { - // Note: This is the last use of sign. There is no 'EF_SIGN'. - spec = SIGNED5_spec; - le = *lp++; - } else if (le == 'B') { - spec = BYTE1_spec; // unsigned byte - } - b->init(u, bands_made++, spec); - b->le_kind = le_kind; - int le_len = 0; - switch (le) { - case 'B': le_len = 1; break; - case 'H': le_len = 2; break; - case 'I': le_len = 4; break; - case 'V': le_len = 0; break; - default: abort("bad layout element"); - } - b->le_len = le_len; - band_stack.add(b); - res = b; - return lp; -} - -const char* -unpacker::attr_definitions::parseNumeral(const char* lp, int &res) { - const char* lp0 = lp; - bool sgn = false; - if (*lp == '0') { res = 0; return lp+1; } // special case '0' - if (*lp == '-') { sgn = true; lp++; } - const char* dp = lp; - int con = 0; - while (*dp >= '0' && *dp <= '9') { - int con0 = con; - con *= 10; - con += (*dp++) - '0'; - if (con <= con0) { con = -1; break; } // numeral overflow - } - if (lp == dp) { - abort("missing numeral in layout"); - return ""; - } - lp = dp; - if (con < 0 && !(sgn && con == -con)) { - // (Portability note: Misses the error if int is not 32 bits.) - abort("numeral overflow"); - return "" ; - } - if (sgn) con = -con; - res = con; - return lp; -} - -band** -unpacker::attr_definitions::popBody(int bs_base) { - // Return everything that was pushed, as a null-terminated pointer array. - int bs_limit = band_stack.length(); - if (bs_base == bs_limit) { - return no_bands; - } else { - int nb = bs_limit - bs_base; - band** res = U_NEW(band*, add_size(nb, 1)); - CHECK_(no_bands); - for (int i = 0; i < nb; i++) { - band* b = (band*) band_stack.get(bs_base + i); - res[i] = b; - } - band_stack.popTo(bs_base); - return res; - } -} - -const char* -unpacker::attr_definitions::parseLayout(const char* lp, band** &res, - int curCble) { - const char* lp0 = lp; - int bs_base = band_stack.length(); - bool top_level = (bs_base == 0); - band* b; - enum { can_be_signed = true }; // optional arg to parseIntLayout - - for (bool done = false; !done; ) { - switch (*lp++) { - case 'B': case 'H': case 'I': case 'V': // unsigned_int - case 'S': // signed_int - --lp; // reparse - /* fall through */ - case 'F': - lp = parseIntLayout(lp, b, EK_INT); - break; - case 'P': - { - int le_bci = EK_BCI; - if (*lp == 'O') { - ++lp; - le_bci = EK_BCID; - } - assert(*lp != 'S'); // no PSH, etc. - lp = parseIntLayout(lp, b, EK_INT); - b->le_bci = le_bci; - if (le_bci == EK_BCI) - b->defc = coding::findBySpec(BCI5_spec); - else - b->defc = coding::findBySpec(BRANCH5_spec); - } - break; - case 'O': - lp = parseIntLayout(lp, b, EK_INT, can_be_signed); - b->le_bci = EK_BCO; - b->defc = coding::findBySpec(BRANCH5_spec); - break; - case 'N': // replication: 'N' uint '[' elem ... ']' - lp = parseIntLayout(lp, b, EK_REPL); - assert(*lp == '['); - ++lp; - lp = parseLayout(lp, b->le_body, curCble); - CHECK_(lp); - break; - case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']' - lp = parseIntLayout(lp, b, EK_UN, can_be_signed); - { - int union_base = band_stack.length(); - for (;;) { // for each case - band& k_case = *U_NEW(band, 1); - CHECK_(lp); - band_stack.add(&k_case); - k_case.le_kind = EK_CASE; - k_case.bn = bands_made++; - if (*lp++ != '(') { - abort("bad union case"); - return ""; - } - if (*lp++ != ')') { - --lp; // reparse - // Read some case values. (Use band_stack for temp. storage.) - int case_base = band_stack.length(); - for (;;) { - int caseval = 0; - lp = parseNumeral(lp, caseval); - band_stack.add((void*)(size_t)caseval); - if (*lp == '-') { - // new in version 160, allow (1-5) for (1,2,3,4,5) - if (u->majver < JAVA6_PACKAGE_MAJOR_VERSION) { - abort("bad range in union case label (old archive format)"); - return ""; - } - int caselimit = caseval; - lp++; - lp = parseNumeral(lp, caselimit); - if (caseval >= caselimit - || (uint)(caselimit - caseval) > 0x10000) { - // Note: 0x10000 is arbitrary implementation restriction. - // We can remove it later if it's important to. - abort("bad range in union case label"); - return ""; - } - for (;;) { - ++caseval; - band_stack.add((void*)(size_t)caseval); - if (caseval == caselimit) break; - } - } - if (*lp != ',') break; - lp++; - } - if (*lp++ != ')') { - abort("bad case label"); - return ""; - } - // save away the case labels - int ntags = band_stack.length() - case_base; - int* tags = U_NEW(int, add_size(ntags, 1)); - CHECK_(lp); - k_case.le_casetags = tags; - *tags++ = ntags; - for (int i = 0; i < ntags; i++) { - *tags++ = ptrlowbits(band_stack.get(case_base+i)); - } - band_stack.popTo(case_base); - CHECK_(lp); - } - // Got le_casetags. Now grab the body. - assert(*lp == '['); - ++lp; - lp = parseLayout(lp, k_case.le_body, curCble); - CHECK_(lp); - if (k_case.le_casetags == null) break; // done - } - b->le_body = popBody(union_base); - } - break; - case '(': // call: '(' -?NN* ')' - { - band& call = *U_NEW(band, 1); - CHECK_(lp); - band_stack.add(&call); - call.le_kind = EK_CALL; - call.bn = bands_made++; - call.le_body = U_NEW(band*, 2); // fill in later - int call_num = 0; - lp = parseNumeral(lp, call_num); - call.le_back = (call_num <= 0); - call_num += curCble; // numeral is self-relative offset - call.le_len = call_num; //use le_len as scratch - calls_to_link.add(&call); - CHECK_(lp); - if (*lp++ != ')') { - abort("bad call label"); - return ""; - } - } - break; - case 'K': // reference_type: constant_ref - case 'R': // reference_type: schema_ref - { - int ixTag = CONSTANT_None; - if (lp[-1] == 'K') { - switch (*lp++) { - case 'I': ixTag = CONSTANT_Integer; break; - case 'J': ixTag = CONSTANT_Long; break; - case 'F': ixTag = CONSTANT_Float; break; - case 'D': ixTag = CONSTANT_Double; break; - case 'S': ixTag = CONSTANT_String; break; - case 'Q': ixTag = CONSTANT_FieldSpecific; break; - - // new in 1.7 - case 'M': ixTag = CONSTANT_MethodHandle; break; - case 'T': ixTag = CONSTANT_MethodType; break; - case 'L': ixTag = CONSTANT_LoadableValue; break; - } - } else { - switch (*lp++) { - case 'C': ixTag = CONSTANT_Class; break; - case 'S': ixTag = CONSTANT_Signature; break; - case 'D': ixTag = CONSTANT_NameandType; break; - case 'F': ixTag = CONSTANT_Fieldref; break; - case 'M': ixTag = CONSTANT_Methodref; break; - case 'I': ixTag = CONSTANT_InterfaceMethodref; break; - case 'U': ixTag = CONSTANT_Utf8; break; //utf8_ref - case 'Q': ixTag = CONSTANT_All; break; //untyped_ref - - // new in 1.7 - case 'Y': ixTag = CONSTANT_InvokeDynamic; break; - case 'B': ixTag = CONSTANT_BootstrapMethod; break; - case 'N': ixTag = CONSTANT_AnyMember; break; - } - } - if (ixTag == CONSTANT_None) { - abort("bad reference layout"); - break; - } - bool nullOK = false; - if (*lp == 'N') { - nullOK = true; - lp++; - } - lp = parseIntLayout(lp, b, EK_REF); - b->defc = coding::findBySpec(UNSIGNED5_spec); - b->initRef(ixTag, nullOK); - } - break; - case '[': - { - // [callable1][callable2]... - if (!top_level) { - abort("bad nested callable"); - break; - } - curCble += 1; - NOT_PRODUCT(int call_num = band_stack.length() - bs_base); - band& cble = *U_NEW(band, 1); - CHECK_(lp); - band_stack.add(&cble); - cble.le_kind = EK_CBLE; - NOT_PRODUCT(cble.le_len = call_num); - cble.bn = bands_made++; - lp = parseLayout(lp, cble.le_body, curCble); - } - break; - case ']': - // Hit a closing brace. This ends whatever body we were in. - done = true; - break; - case '\0': - // Hit a null. Also ends the (top-level) body. - --lp; // back up, so caller can see the null also - done = true; - break; - default: - abort("bad layout"); - break; - } - CHECK_(lp); - } - - // Return the accumulated bands: - res = popBody(bs_base); - return lp; -} - -void unpacker::read_attr_defs() { - int i; - - // Tell each AD which attrc it is and where its fixed flags are: - attr_defs[ATTR_CONTEXT_CLASS].attrc = ATTR_CONTEXT_CLASS; - attr_defs[ATTR_CONTEXT_CLASS].xxx_flags_hi_bn = e_class_flags_hi; - attr_defs[ATTR_CONTEXT_FIELD].attrc = ATTR_CONTEXT_FIELD; - attr_defs[ATTR_CONTEXT_FIELD].xxx_flags_hi_bn = e_field_flags_hi; - attr_defs[ATTR_CONTEXT_METHOD].attrc = ATTR_CONTEXT_METHOD; - attr_defs[ATTR_CONTEXT_METHOD].xxx_flags_hi_bn = e_method_flags_hi; - attr_defs[ATTR_CONTEXT_CODE].attrc = ATTR_CONTEXT_CODE; - attr_defs[ATTR_CONTEXT_CODE].xxx_flags_hi_bn = e_code_flags_hi; - - // Decide whether bands for the optional high flag words are present. - attr_defs[ATTR_CONTEXT_CLASS] - .setHaveLongFlags(testBit(archive_options, AO_HAVE_CLASS_FLAGS_HI)); - attr_defs[ATTR_CONTEXT_FIELD] - .setHaveLongFlags(testBit(archive_options, AO_HAVE_FIELD_FLAGS_HI)); - attr_defs[ATTR_CONTEXT_METHOD] - .setHaveLongFlags(testBit(archive_options, AO_HAVE_METHOD_FLAGS_HI)); - attr_defs[ATTR_CONTEXT_CODE] - .setHaveLongFlags(testBit(archive_options, AO_HAVE_CODE_FLAGS_HI)); - - // Set up built-in attrs. - // (The simple ones are hard-coded. The metadata layouts are not.) - const char* md_layout = ( - // parameter annotations: -#define MDL0 \ - "[NB[(1)]]" - MDL0 - // annotations: -#define MDL1 \ - "[NH[(1)]]" - MDL1 -#define MDL2 \ - "[RSHNH[RUH(1)]]" - MDL2 - // element_value: -#define MDL3 \ - "[TB" \ - "(66,67,73,83,90)[KIH]" \ - "(68)[KDH]" \ - "(70)[KFH]" \ - "(74)[KJH]" \ - "(99)[RSH]" \ - "(101)[RSHRUH]" \ - "(115)[RUH]" \ - "(91)[NH[(0)]]" \ - "(64)[" \ - /* nested annotation: */ \ - "RSH" \ - "NH[RUH(0)]" \ - "]" \ - "()[]" \ - "]" - MDL3 - ); - - const char* md_layout_P = md_layout; - const char* md_layout_A = md_layout+strlen(MDL0); - const char* md_layout_V = md_layout+strlen(MDL0 MDL1 MDL2); - assert(0 == strncmp(&md_layout_A[-3], ")]][", 4)); - assert(0 == strncmp(&md_layout_V[-3], ")]][", 4)); - -const char* type_md_layout( - "[NH[(1)(2)(3)]]" - // target-type + target_info - "[TB" - "(0,1)[B]" - "(16)[FH]" - "(17,18)[BB]" - "(19,20,21)[]" - "(22)[B]" - "(23)[H]" - "(64,65)[NH[PHOHH]]" - "(66)[H]" - "(67,68,69,70)[PH]" - "(71,72,73,74,75)[PHB]" - "()[]]" - // target-path - "[NB[BB]]" - // annotation + element_value - MDL2 - MDL3 -); - - for (i = 0; i < ATTR_CONTEXT_LIMIT; i++) { - attr_definitions& ad = attr_defs[i]; - if (i != ATTR_CONTEXT_CODE) { - ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, - "RuntimeVisibleAnnotations", md_layout_A); - ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, - "RuntimeInvisibleAnnotations", md_layout_A); - if (i == ATTR_CONTEXT_METHOD) { - ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations, - "RuntimeVisibleParameterAnnotations", md_layout_P); - ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, - "RuntimeInvisibleParameterAnnotations", md_layout_P); - ad.defineLayout(METHOD_ATTR_AnnotationDefault, - "AnnotationDefault", md_layout_V); - } - } - ad.defineLayout(X_ATTR_RuntimeVisibleTypeAnnotations, - "RuntimeVisibleTypeAnnotations", type_md_layout); - ad.defineLayout(X_ATTR_RuntimeInvisibleTypeAnnotations, - "RuntimeInvisibleTypeAnnotations", type_md_layout); - } - - attr_definition_headers.readData(attr_definition_count); - attr_definition_name.readData(attr_definition_count); - attr_definition_layout.readData(attr_definition_count); - - CHECK; - - // Initialize correct predef bits, to distinguish predefs from new defs. -#define ORBIT(n,s) |((julong)1<value.b.strval()); - } -} - -#define NO_ENTRY_YET ((entry*)-1) - -static bool isDigitString(bytes& x, int beg, int end) { - if (beg == end) return false; // null string - byte* xptr = x.ptr; - for (int i = beg; i < end; i++) { - char ch = xptr[i]; - if (!(ch >= '0' && ch <= '9')) return false; - } - return true; -} - -enum { // constants for parsing class names - SLASH_MIN = '.', - SLASH_MAX = '/', - DOLLAR_MIN = 0, - DOLLAR_MAX = '-' -}; - -static int lastIndexOf(int chmin, int chmax, bytes& x, int pos) { - byte* ptr = x.ptr; - for (byte* cp = ptr + pos; --cp >= ptr; ) { - assert(x.inBounds(cp)); - if (*cp >= chmin && *cp <= chmax) - return (int)(cp - ptr); - } - return -1; -} - -maybe_inline -inner_class* cpool::getIC(entry* inner) { - if (inner == null) return null; - assert(inner->tag == CONSTANT_Class); - if (inner->inord == NO_INORD) return null; - inner_class* ic = ic_index[inner->inord]; - assert(ic == null || ic->inner == inner); - return ic; -} - -maybe_inline -inner_class* cpool::getFirstChildIC(entry* outer) { - if (outer == null) return null; - assert(outer->tag == CONSTANT_Class); - if (outer->inord == NO_INORD) return null; - inner_class* ic = ic_child_index[outer->inord]; - assert(ic == null || ic->outer == outer); - return ic; -} - -maybe_inline -inner_class* cpool::getNextChildIC(inner_class* child) { - inner_class* ic = child->next_sibling; - assert(ic == null || ic->outer == child->outer); - return ic; -} - -void unpacker::read_ics() { - int i; - int index_size = cp.tag_count[CONSTANT_Class]; - inner_class** ic_index = U_NEW(inner_class*, index_size); - inner_class** ic_child_index = U_NEW(inner_class*, index_size); - cp.ic_index = ic_index; - cp.ic_child_index = ic_child_index; - ics = U_NEW(inner_class, ic_count); - ic_this_class.readData(ic_count); - ic_flags.readData(ic_count); - CHECK; - // Scan flags to get count of long-form bands. - int long_forms = 0; - for (i = 0; i < ic_count; i++) { - int flags = ic_flags.getInt(); // may be long form! - if ((flags & ACC_IC_LONG_FORM) != 0) { - long_forms += 1; - ics[i].name = NO_ENTRY_YET; - } - flags &= ~ACC_IC_LONG_FORM; - entry* inner = ic_this_class.getRef(); - CHECK; - uint inord = inner->inord; - assert(inord < (uint)cp.tag_count[CONSTANT_Class]); - if (ic_index[inord] != null) { - abort("identical inner class"); - break; - } - ic_index[inord] = &ics[i]; - ics[i].inner = inner; - ics[i].flags = flags; - assert(cp.getIC(inner) == &ics[i]); - } - CHECK; - //ic_this_class.done(); - //ic_flags.done(); - ic_outer_class.readData(long_forms); - ic_name.readData(long_forms); - for (i = 0; i < ic_count; i++) { - if (ics[i].name == NO_ENTRY_YET) { - // Long form. - ics[i].outer = ic_outer_class.getRefN(); - CHECK; - ics[i].name = ic_name.getRefN(); - CHECK; - } else { - // Fill in outer and name based on inner. - bytes& n = ics[i].inner->value.b; - bytes pkgOuter; - bytes number; - bytes name; - // Parse n into pkgOuter and name (and number). - PRINTCR((5, "parse short IC name %s", n.ptr)); - int dollar1, dollar2; // pointers to $ in the pattern - // parse n = (/)*($)?($)? - int nlen = (int)n.len; - int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, nlen) + 1; - dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, nlen); - if (dollar2 < 0) { - abort(); - return; - } - assert(dollar2 >= pkglen); - if (isDigitString(n, dollar2+1, nlen)) { - // n = (/)*$ - number = n.slice(dollar2+1, nlen); - name.set(null,0); - dollar1 = dollar2; - } else if (pkglen < (dollar1 - = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2-1)) - && isDigitString(n, dollar1+1, dollar2)) { - // n = (/)*$$ - number = n.slice(dollar1+1, dollar2); - name = n.slice(dollar2+1, nlen); - } else { - // n = (/)*$ - dollar1 = dollar2; - number.set(null,0); - name = n.slice(dollar2+1, nlen); - } - if (number.ptr == null) { - if (dollar1 < 0) { - abort(); - return; - } - pkgOuter = n.slice(0, dollar1); - } else { - pkgOuter.set(null,0); - } - PRINTCR((5,"=> %s$ 0%s $%s", - pkgOuter.string(), number.string(), name.string())); - - if (pkgOuter.ptr != null) - ics[i].outer = cp.ensureClass(pkgOuter); - - if (name.ptr != null) - ics[i].name = cp.ensureUtf8(name); - } - - // update child/sibling list - if (ics[i].outer != null) { - uint outord = ics[i].outer->inord; - if (outord != NO_INORD) { - assert(outord < (uint)cp.tag_count[CONSTANT_Class]); - ics[i].next_sibling = ic_child_index[outord]; - ic_child_index[outord] = &ics[i]; - } - } - } - //ic_outer_class.done(); - //ic_name.done(); -} - -void unpacker::read_classes() { - PRINTCR((1," ...scanning %d classes...", class_count)); - class_this.readData(class_count); - class_super.readData(class_count); - class_interface_count.readData(class_count); - class_interface.readData(class_interface_count.getIntTotal()); - - CHECK; - - #if 0 - int i; - // Make a little mark on super-classes. - for (i = 0; i < class_count; i++) { - entry* e = class_super.getRefN(); - if (e != null) e->bits |= entry::EB_SUPER; - } - class_super.rewind(); - #endif - - // Members. - class_field_count.readData(class_count); - class_method_count.readData(class_count); - - CHECK; - - int field_count = class_field_count.getIntTotal(); - int method_count = class_method_count.getIntTotal(); - - field_descr.readData(field_count); - read_attrs(ATTR_CONTEXT_FIELD, field_count); - CHECK; - - method_descr.readData(method_count); - read_attrs(ATTR_CONTEXT_METHOD, method_count); - - CHECK; - - read_attrs(ATTR_CONTEXT_CLASS, class_count); - CHECK; - - read_code_headers(); - - PRINTCR((1,"scanned %d classes, %d fields, %d methods, %d code headers", - class_count, field_count, method_count, code_count)); -} - -maybe_inline -int unpacker::attr_definitions::predefCount(uint idx) { - return isPredefined(idx) ? flag_count[idx] : 0; -} - -void unpacker::read_attrs(int attrc, int obj_count) { - attr_definitions& ad = attr_defs[attrc]; - assert(ad.attrc == attrc); - - int i, idx, count; - - CHECK; - - bool haveLongFlags = ad.haveLongFlags(); - - band& xxx_flags_hi = ad.xxx_flags_hi(); - assert(endsWith(xxx_flags_hi.name, "_flags_hi")); - if (haveLongFlags) - xxx_flags_hi.readData(obj_count); - CHECK; - - band& xxx_flags_lo = ad.xxx_flags_lo(); - assert(endsWith(xxx_flags_lo.name, "_flags_lo")); - xxx_flags_lo.readData(obj_count); - CHECK; - - // pre-scan flags, counting occurrences of each index bit - julong indexMask = ad.flagIndexMask(); // which flag bits are index bits? - for (i = 0; i < obj_count; i++) { - julong indexBits = xxx_flags_hi.getLong(xxx_flags_lo, haveLongFlags); - if ((indexBits & ~indexMask) > (ushort)-1) { - abort("undefined attribute flag bit"); - return; - } - indexBits &= indexMask; // ignore classfile flag bits - for (idx = 0; indexBits != 0; idx++, indexBits >>= 1) { - ad.flag_count[idx] += (int)(indexBits & 1); - } - } - // we'll scan these again later for output: - xxx_flags_lo.rewind(); - xxx_flags_hi.rewind(); - - band& xxx_attr_count = ad.xxx_attr_count(); - assert(endsWith(xxx_attr_count.name, "_attr_count")); - // There is one count element for each 1<<16 bit set in flags: - xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW)); - CHECK; - - band& xxx_attr_indexes = ad.xxx_attr_indexes(); - assert(endsWith(xxx_attr_indexes.name, "_attr_indexes")); - int overflowIndexCount = xxx_attr_count.getIntTotal(); - xxx_attr_indexes.readData(overflowIndexCount); - CHECK; - // pre-scan attr indexes, counting occurrences of each value - for (i = 0; i < overflowIndexCount; i++) { - idx = xxx_attr_indexes.getInt(); - if (!ad.isIndex(idx)) { - abort("attribute index out of bounds"); - return; - } - ad.getCount(idx) += 1; - } - xxx_attr_indexes.rewind(); // we'll scan it again later for output - - // We will need a backward call count for each used backward callable. - int backwardCounts = 0; - for (idx = 0; idx < ad.layouts.length(); idx++) { - layout_definition* lo = ad.getLayout(idx); - if (lo != null && ad.getCount(idx) != 0) { - // Build the bands lazily, only when they are used. - band** bands = ad.buildBands(lo); - CHECK; - if (lo->hasCallables()) { - for (i = 0; bands[i] != null; i++) { - if (bands[i]->le_back) { - assert(bands[i]->le_kind == EK_CBLE); - backwardCounts += 1; - } - } - } - } - } - ad.xxx_attr_calls().readData(backwardCounts); - CHECK; - - // Read built-in bands. - // Mostly, these are hand-coded equivalents to readBandData(). - switch (attrc) { - case ATTR_CONTEXT_CLASS: - - count = ad.predefCount(CLASS_ATTR_SourceFile); - class_SourceFile_RUN.readData(count); - CHECK; - - count = ad.predefCount(CLASS_ATTR_EnclosingMethod); - class_EnclosingMethod_RC.readData(count); - class_EnclosingMethod_RDN.readData(count); - CHECK; - - count = ad.predefCount(X_ATTR_Signature); - class_Signature_RS.readData(count); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); - CHECK; - - count = ad.predefCount(CLASS_ATTR_InnerClasses); - class_InnerClasses_N.readData(count); - CHECK; - - count = class_InnerClasses_N.getIntTotal(); - class_InnerClasses_RC.readData(count); - class_InnerClasses_F.readData(count); - CHECK; - // Drop remaining columns wherever flags are zero: - count -= class_InnerClasses_F.getIntCount(0); - class_InnerClasses_outer_RCN.readData(count); - class_InnerClasses_name_RUN.readData(count); - CHECK; - - count = ad.predefCount(CLASS_ATTR_ClassFile_version); - class_ClassFile_version_minor_H.readData(count); - class_ClassFile_version_major_H.readData(count); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); - CHECK; - break; - - case ATTR_CONTEXT_FIELD: - - count = ad.predefCount(FIELD_ATTR_ConstantValue); - field_ConstantValue_KQ.readData(count); - CHECK; - - count = ad.predefCount(X_ATTR_Signature); - field_Signature_RS.readData(count); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); - CHECK; - break; - - case ATTR_CONTEXT_METHOD: - - code_count = ad.predefCount(METHOD_ATTR_Code); - // Code attrs are handled very specially below... - - count = ad.predefCount(METHOD_ATTR_Exceptions); - method_Exceptions_N.readData(count); - count = method_Exceptions_N.getIntTotal(); - method_Exceptions_RC.readData(count); - CHECK; - - count = ad.predefCount(X_ATTR_Signature); - method_Signature_RS.readData(count); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); - ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations); - ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations); - ad.readBandData(METHOD_ATTR_AnnotationDefault); - CHECK; - - count = ad.predefCount(METHOD_ATTR_MethodParameters); - method_MethodParameters_NB.readData(count); - count = method_MethodParameters_NB.getIntTotal(); - method_MethodParameters_name_RUN.readData(count); - method_MethodParameters_flag_FH.readData(count); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); - CHECK; - - break; - - case ATTR_CONTEXT_CODE: - // (keep this code aligned with its brother in unpacker::write_attrs) - count = ad.predefCount(CODE_ATTR_StackMapTable); - // disable this feature in old archives! - if (count != 0 && majver < JAVA6_PACKAGE_MAJOR_VERSION) { - abort("undefined StackMapTable attribute (old archive format)"); - return; - } - code_StackMapTable_N.readData(count); - CHECK; - count = code_StackMapTable_N.getIntTotal(); - code_StackMapTable_frame_T.readData(count); - CHECK; - // the rest of it depends in a complicated way on frame tags - { - int fat_frame_count = 0; - int offset_count = 0; - int type_count = 0; - for (int k = 0; k < count; k++) { - int tag = code_StackMapTable_frame_T.getByte(); - if (tag <= 127) { - // (64-127) [(2)] - if (tag >= 64) type_count++; - } else if (tag <= 251) { - // (247) [(1)(2)] - // (248-251) [(1)] - if (tag >= 247) offset_count++; - if (tag == 247) type_count++; - } else if (tag <= 254) { - // (252) [(1)(2)] - // (253) [(1)(2)(2)] - // (254) [(1)(2)(2)(2)] - offset_count++; - type_count += (tag - 251); - } else { - // (255) [(1)NH[(2)]NH[(2)]] - fat_frame_count++; - } - } - - // done pre-scanning frame tags: - code_StackMapTable_frame_T.rewind(); - - // deal completely with fat frames: - offset_count += fat_frame_count; - code_StackMapTable_local_N.readData(fat_frame_count); - CHECK; - type_count += code_StackMapTable_local_N.getIntTotal(); - code_StackMapTable_stack_N.readData(fat_frame_count); - type_count += code_StackMapTable_stack_N.getIntTotal(); - CHECK; - // read the rest: - code_StackMapTable_offset.readData(offset_count); - code_StackMapTable_T.readData(type_count); - CHECK; - // (7) [RCH] - count = code_StackMapTable_T.getIntCount(7); - code_StackMapTable_RC.readData(count); - CHECK; - // (8) [PH] - count = code_StackMapTable_T.getIntCount(8); - code_StackMapTable_P.readData(count); - CHECK; - } - - count = ad.predefCount(CODE_ATTR_LineNumberTable); - code_LineNumberTable_N.readData(count); - CHECK; - count = code_LineNumberTable_N.getIntTotal(); - code_LineNumberTable_bci_P.readData(count); - code_LineNumberTable_line.readData(count); - CHECK; - - count = ad.predefCount(CODE_ATTR_LocalVariableTable); - code_LocalVariableTable_N.readData(count); - CHECK; - count = code_LocalVariableTable_N.getIntTotal(); - code_LocalVariableTable_bci_P.readData(count); - code_LocalVariableTable_span_O.readData(count); - code_LocalVariableTable_name_RU.readData(count); - code_LocalVariableTable_type_RS.readData(count); - code_LocalVariableTable_slot.readData(count); - CHECK; - - count = ad.predefCount(CODE_ATTR_LocalVariableTypeTable); - code_LocalVariableTypeTable_N.readData(count); - count = code_LocalVariableTypeTable_N.getIntTotal(); - code_LocalVariableTypeTable_bci_P.readData(count); - code_LocalVariableTypeTable_span_O.readData(count); - code_LocalVariableTypeTable_name_RU.readData(count); - code_LocalVariableTypeTable_type_RS.readData(count); - code_LocalVariableTypeTable_slot.readData(count); - CHECK; - - ad.readBandData(X_ATTR_RuntimeVisibleTypeAnnotations); - ad.readBandData(X_ATTR_RuntimeInvisibleTypeAnnotations); - CHECK; - - break; - } - - // Read compressor-defined bands. - for (idx = 0; idx < ad.layouts.length(); idx++) { - if (ad.getLayout(idx) == null) - continue; // none at this fixed index <32 - if (idx < (int)ad.flag_limit && ad.isPredefined(idx)) - continue; // already handled - if (ad.getCount(idx) == 0) - continue; // no attributes of this type (then why transmit layouts?) - ad.readBandData(idx); - } -} - -void unpacker::attr_definitions::readBandData(int idx) { - int j; - uint count = getCount(idx); - if (count == 0) return; - layout_definition* lo = getLayout(idx); - if (lo != null) { - PRINTCR((1, "counted %d [redefined = %d predefined = %d] attributes of type %s.%s", - count, isRedefined(idx), isPredefined(idx), - ATTR_CONTEXT_NAME[attrc], lo->name)); - } else { - abort("layout_definition pointer must not be NULL"); - return; - } - bool hasCallables = lo->hasCallables(); - band** bands = lo->bands(); - if (!hasCallables) { - // Read through the rest of the bands in a regular way. - readBandData(bands, count); - } else { - // Deal with the callables. - // First set up the forward entry count for each callable. - // This is stored on band::length of the callable. - bands[0]->expectMoreLength(count); - for (j = 0; bands[j] != null; j++) { - band& j_cble = *bands[j]; - assert(j_cble.le_kind == EK_CBLE); - if (j_cble.le_back) { - // Add in the predicted effects of backward calls, too. - int back_calls = xxx_attr_calls().getInt(); - j_cble.expectMoreLength(back_calls); - // In a moment, more forward calls may increment j_cble.length. - } - } - // Now consult whichever callables have non-zero entry counts. - readBandData(bands, (uint)-1); - } -} - -// Recursive helper to the previous function: -void unpacker::attr_definitions::readBandData(band** body, uint count) { - int j, k; - for (j = 0; body[j] != null; j++) { - band& b = *body[j]; - if (b.defc != null) { - // It has data, so read it. - b.readData(count); - } - switch (b.le_kind) { - case EK_REPL: - { - int reps = b.getIntTotal(); - readBandData(b.le_body, reps); - } - break; - case EK_UN: - { - int remaining = count; - for (k = 0; b.le_body[k] != null; k++) { - band& k_case = *b.le_body[k]; - int k_count = 0; - if (k_case.le_casetags == null) { - k_count = remaining; // last (empty) case - } else { - int* tags = k_case.le_casetags; - int ntags = *tags++; // 1st element is length (why not?) - while (ntags-- > 0) { - int tag = *tags++; - k_count += b.getIntCount(tag); - } - } - readBandData(k_case.le_body, k_count); - remaining -= k_count; - } - assert(remaining == 0); - } - break; - case EK_CALL: - // Push the count forward, if it is not a backward call. - if (!b.le_back) { - band& cble = *b.le_body[0]; - assert(cble.le_kind == EK_CBLE); - cble.expectMoreLength(count); - } - break; - case EK_CBLE: - assert((int)count == -1); // incoming count is meaningless - k = b.length; - assert(k >= 0); - // This is intended and required for non production mode. - assert((b.length = -1)); // make it unable to accept more calls now. - readBandData(b.le_body, k); - break; - } - } -} - -static inline -band** findMatchingCase(int matchTag, band** cases) { - for (int k = 0; cases[k] != null; k++) { - band& k_case = *cases[k]; - if (k_case.le_casetags != null) { - // If it has tags, it must match a tag. - int* tags = k_case.le_casetags; - int ntags = *tags++; // 1st element is length - for (; ntags > 0; ntags--) { - int tag = *tags++; - if (tag == matchTag) - break; - } - if (ntags == 0) - continue; // does not match - } - return k_case.le_body; - } - return null; -} - -// write attribute band data: -void unpacker::putlayout(band** body) { - int i; - int prevBII = -1; - int prevBCI = -1; - if (body == NULL) { - abort("putlayout: unexpected NULL for body"); - return; - } - for (i = 0; body[i] != null; i++) { - band& b = *body[i]; - byte le_kind = b.le_kind; - - // Handle scalar part, if any. - int x = 0; - entry* e = null; - if (b.defc != null) { - // It has data, so unparse an element. - if (b.ixTag != CONSTANT_None) { - assert(le_kind == EK_REF); - if (b.ixTag == CONSTANT_FieldSpecific) - e = b.getRefUsing(cp.getKQIndex()); - else - e = b.getRefN(); - CHECK; - switch (b.le_len) { - case 0: break; - case 1: putu1ref(e); break; - case 2: putref(e); break; - case 4: putu2(0); putref(e); break; - default: assert(false); - } - } else { - assert(le_kind == EK_INT || le_kind == EK_REPL || le_kind == EK_UN); - x = b.getInt(); - - assert(!b.le_bci || prevBCI == (int)to_bci(prevBII)); - switch (b.le_bci) { - case EK_BCI: // PH: transmit R(bci), store bci - x = to_bci(prevBII = x); - prevBCI = x; - break; - case EK_BCID: // POH: transmit D(R(bci)), store bci - x = to_bci(prevBII += x); - prevBCI = x; - break; - case EK_BCO: // OH: transmit D(R(bci)), store D(bci) - x = to_bci(prevBII += x) - prevBCI; - prevBCI += x; - break; - } - assert(!b.le_bci || prevBCI == (int)to_bci(prevBII)); - - CHECK; - switch (b.le_len) { - case 0: break; - case 1: putu1(x); break; - case 2: putu2(x); break; - case 4: putu4(x); break; - default: assert(false); - } - } - } - - // Handle subparts, if any. - switch (le_kind) { - case EK_REPL: - // x is the repeat count - while (x-- > 0) { - putlayout(b.le_body); - } - break; - case EK_UN: - // x is the tag - putlayout(findMatchingCase(x, b.le_body)); - break; - case EK_CALL: - { - band& cble = *b.le_body[0]; - assert(cble.le_kind == EK_CBLE); - assert(cble.le_len == b.le_len); - putlayout(cble.le_body); - } - break; - - #ifndef PRODUCT - case EK_CBLE: - case EK_CASE: - assert(false); // should not reach here - #endif - } - } -} - -void unpacker::read_files() { - file_name.readData(file_count); - if (testBit(archive_options, AO_HAVE_FILE_SIZE_HI)) - file_size_hi.readData(file_count); - file_size_lo.readData(file_count); - if (testBit(archive_options, AO_HAVE_FILE_MODTIME)) - file_modtime.readData(file_count); - int allFiles = file_count + class_count; - if (testBit(archive_options, AO_HAVE_FILE_OPTIONS)) { - file_options.readData(file_count); - // FO_IS_CLASS_STUB might be set, causing overlap between classes and files - for (int i = 0; i < file_count; i++) { - if ((file_options.getInt() & FO_IS_CLASS_STUB) != 0) { - allFiles -= 1; // this one counts as both class and file - } - } - file_options.rewind(); - } - assert((default_file_options & FO_IS_CLASS_STUB) == 0); - files_remaining = allFiles; -} - -maybe_inline -void unpacker::get_code_header(int& max_stack, - int& max_na_locals, - int& handler_count, - int& cflags) { - int sc = code_headers.getByte(); - if (sc == 0) { - max_stack = max_na_locals = handler_count = cflags = -1; - return; - } - // Short code header is the usual case: - int nh; - int mod; - if (sc < 1 + 12*12) { - sc -= 1; - nh = 0; - mod = 12; - } else if (sc < 1 + 12*12 + 8*8) { - sc -= 1 + 12*12; - nh = 1; - mod = 8; - } else { - assert(sc < 1 + 12*12 + 8*8 + 7*7); - sc -= 1 + 12*12 + 8*8; - nh = 2; - mod = 7; - } - max_stack = sc % mod; - max_na_locals = sc / mod; // caller must add static, siglen - handler_count = nh; - if (testBit(archive_options, AO_HAVE_ALL_CODE_FLAGS)) - cflags = -1; - else - cflags = 0; // this one has no attributes -} - -// Cf. PackageReader.readCodeHeaders -void unpacker::read_code_headers() { - code_headers.readData(code_count); - CHECK; - int totalHandlerCount = 0; - int totalFlagsCount = 0; - for (int i = 0; i < code_count; i++) { - int max_stack, max_locals, handler_count, cflags; - get_code_header(max_stack, max_locals, handler_count, cflags); - if (max_stack < 0) code_max_stack.expectMoreLength(1); - if (max_locals < 0) code_max_na_locals.expectMoreLength(1); - if (handler_count < 0) code_handler_count.expectMoreLength(1); - else totalHandlerCount += handler_count; - if (cflags < 0) totalFlagsCount += 1; - } - code_headers.rewind(); // replay later during writing - - code_max_stack.readData(); - code_max_na_locals.readData(); - code_handler_count.readData(); - totalHandlerCount += code_handler_count.getIntTotal(); - CHECK; - - // Read handler specifications. - // Cf. PackageReader.readCodeHandlers. - code_handler_start_P.readData(totalHandlerCount); - code_handler_end_PO.readData(totalHandlerCount); - code_handler_catch_PO.readData(totalHandlerCount); - code_handler_class_RCN.readData(totalHandlerCount); - CHECK; - - read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount); - CHECK; -} - -static inline bool is_in_range(uint n, uint min, uint max) { - return n - min <= max - min; // unsigned arithmetic! -} -static inline bool is_field_op(int bc) { - return is_in_range(bc, bc_getstatic, bc_putfield); -} -static inline bool is_invoke_init_op(int bc) { - return is_in_range(bc, _invokeinit_op, _invokeinit_limit-1); -} -static inline bool is_self_linker_op(int bc) { - return is_in_range(bc, _self_linker_op, _self_linker_limit-1); -} -static bool is_branch_op(int bc) { - return is_in_range(bc, bc_ifeq, bc_jsr) - || is_in_range(bc, bc_ifnull, bc_jsr_w); -} -static bool is_local_slot_op(int bc) { - return is_in_range(bc, bc_iload, bc_aload) - || is_in_range(bc, bc_istore, bc_astore) - || bc == bc_iinc || bc == bc_ret; -} -band* unpacker::ref_band_for_op(int bc) { - switch (bc) { - case bc_ildc: - case bc_ildc_w: - return &bc_intref; - case bc_fldc: - case bc_fldc_w: - return &bc_floatref; - case bc_lldc2_w: - return &bc_longref; - case bc_dldc2_w: - return &bc_doubleref; - case bc_sldc: - case bc_sldc_w: - return &bc_stringref; - case bc_cldc: - case bc_cldc_w: - return &bc_classref; - case bc_qldc: case bc_qldc_w: - return &bc_loadablevalueref; - - case bc_getstatic: - case bc_putstatic: - case bc_getfield: - case bc_putfield: - return &bc_fieldref; - - case _invokespecial_int: - case _invokestatic_int: - return &bc_imethodref; - case bc_invokevirtual: - case bc_invokespecial: - case bc_invokestatic: - return &bc_methodref; - case bc_invokeinterface: - return &bc_imethodref; - case bc_invokedynamic: - return &bc_indyref; - - case bc_new: - case bc_anewarray: - case bc_checkcast: - case bc_instanceof: - case bc_multianewarray: - return &bc_classref; - } - return null; -} - -maybe_inline -band* unpacker::ref_band_for_self_op(int bc, bool& isAloadVar, int& origBCVar) { - if (!is_self_linker_op(bc)) return null; - int idx = (bc - _self_linker_op); - bool isSuper = (idx >= _self_linker_super_flag); - if (isSuper) idx -= _self_linker_super_flag; - bool isAload = (idx >= _self_linker_aload_flag); - if (isAload) idx -= _self_linker_aload_flag; - int origBC = _first_linker_op + idx; - bool isField = is_field_op(origBC); - isAloadVar = isAload; - origBCVar = _first_linker_op + idx; - if (!isSuper) - return isField? &bc_thisfield: &bc_thismethod; - else - return isField? &bc_superfield: &bc_supermethod; -} - -// Cf. PackageReader.readByteCodes -inline // called exactly once => inline -void unpacker::read_bcs() { - PRINTCR((3, "reading compressed bytecodes and operands for %d codes...", - code_count)); - - // read from bc_codes and bc_case_count - fillbytes all_switch_ops; - all_switch_ops.init(); - CHECK; - - // Read directly from rp/rplimit. - //Do this later: bc_codes.readData(...) - byte* rp0 = rp; - - band* bc_which; - byte* opptr = rp; - byte* oplimit = rplimit; - - bool isAload; // passed by ref and then ignored - int junkBC; // passed by ref and then ignored - for (int k = 0; k < code_count; k++) { - // Scan one method: - for (;;) { - if (opptr+2 > oplimit) { - rp = opptr; - ensure_input(2); - oplimit = rplimit; - rp = rp0; // back up - } - if (opptr == oplimit) { abort(); break; } - int bc = *opptr++ & 0xFF; - bool isWide = false; - if (bc == bc_wide) { - if (opptr == oplimit) { abort(); break; } - bc = *opptr++ & 0xFF; - isWide = true; - } - // Adjust expectations of various band sizes. - switch (bc) { - case bc_tableswitch: - case bc_lookupswitch: - all_switch_ops.addByte(bc); - break; - case bc_iinc: - bc_local.expectMoreLength(1); - bc_which = isWide ? &bc_short : &bc_byte; - bc_which->expectMoreLength(1); - break; - case bc_sipush: - bc_short.expectMoreLength(1); - break; - case bc_bipush: - bc_byte.expectMoreLength(1); - break; - case bc_newarray: - bc_byte.expectMoreLength(1); - break; - case bc_multianewarray: - assert(ref_band_for_op(bc) == &bc_classref); - bc_classref.expectMoreLength(1); - bc_byte.expectMoreLength(1); - break; - case bc_ref_escape: - bc_escrefsize.expectMoreLength(1); - bc_escref.expectMoreLength(1); - break; - case bc_byte_escape: - bc_escsize.expectMoreLength(1); - // bc_escbyte will have to be counted too - break; - default: - if (is_invoke_init_op(bc)) { - bc_initref.expectMoreLength(1); - break; - } - bc_which = ref_band_for_self_op(bc, isAload, junkBC); - if (bc_which != null) { - bc_which->expectMoreLength(1); - break; - } - if (is_branch_op(bc)) { - bc_label.expectMoreLength(1); - break; - } - bc_which = ref_band_for_op(bc); - if (bc_which != null) { - bc_which->expectMoreLength(1); - assert(bc != bc_multianewarray); // handled elsewhere - break; - } - if (is_local_slot_op(bc)) { - bc_local.expectMoreLength(1); - break; - } - break; - case bc_end_marker: - // Increment k and test against code_count. - goto doneScanningMethod; - } - } - doneScanningMethod:{} - if (aborting()) break; - } - - // Go through the formality, so we can use it in a regular fashion later: - assert(rp == rp0); - bc_codes.readData((int)(opptr - rp)); - - int i = 0; - - // To size instruction bands correctly, we need info on switches: - bc_case_count.readData((int)all_switch_ops.size()); - for (i = 0; i < (int)all_switch_ops.size(); i++) { - int caseCount = bc_case_count.getInt(); - int bc = all_switch_ops.getByte(i); - bc_label.expectMoreLength(1+caseCount); // default label + cases - bc_case_value.expectMoreLength(bc == bc_tableswitch ? 1 : caseCount); - PRINTCR((2, "switch bc=%d caseCount=%d", bc, caseCount)); - } - bc_case_count.rewind(); // uses again for output - - all_switch_ops.free(); - - for (i = e_bc_case_value; i <= e_bc_escsize; i++) { - all_bands[i].readData(); - } - - // The bc_escbyte band is counted by the immediately previous band. - bc_escbyte.readData(bc_escsize.getIntTotal()); - - PRINTCR((3, "scanned %d opcode and %d operand bytes for %d codes...", - (int)(bc_codes.size()), - (int)(bc_escsize.maxRP() - bc_case_value.minRP()), - code_count)); -} - -void unpacker::read_bands() { - byte* rp0 = rp; - CHECK; - read_file_header(); - CHECK; - - if (cp.nentries == 0) { - // read_file_header failed to read a CP, because it copied a JAR. - return; - } - - // Do this after the file header has been read: - check_options(); - - read_cp(); - CHECK; - read_attr_defs(); - CHECK; - read_ics(); - CHECK; - read_classes(); - CHECK; - read_bcs(); - CHECK; - read_files(); -} - -/// CP routines - -entry*& cpool::hashTabRef(byte tag, bytes& b) { - PRINTCR((5, "hashTabRef tag=%d %s[%d]", tag, b.string(), b.len)); - uint hash = tag + (int)b.len; - for (int i = 0; i < (int)b.len; i++) { - hash = hash * 31 + (0xFF & b.ptr[i]); - } - entry** ht = hashTab; - int hlen = hashTabLength; - assert((hlen & (hlen-1)) == 0); // must be power of 2 - uint hash1 = hash & (hlen-1); // == hash % hlen - uint hash2 = 0; // lazily computed (requires mod op.) - int probes = 0; - while (ht[hash1] != null) { - entry& e = *ht[hash1]; - if (e.value.b.equals(b) && e.tag == tag) - break; - if (hash2 == 0) - // Note: hash2 must be relatively prime to hlen, hence the "|1". - hash2 = (((hash % 499) & (hlen-1)) | 1); - hash1 += hash2; - if (hash1 >= (uint)hlen) hash1 -= hlen; - assert(hash1 < (uint)hlen); - assert(++probes < hlen); - } - #ifndef PRODUCT - hash_probes[0] += 1; - hash_probes[1] += probes; - #endif - PRINTCR((5, " => @%d %p", hash1, ht[hash1])); - return ht[hash1]; -} - -maybe_inline -static void insert_extra(entry* e, ptrlist& extras) { - // This ordering helps implement the Pack200 requirement - // of a predictable CP order in the class files produced. - e->inord = NO_INORD; // mark as an "extra" - extras.add(e); - // Note: We will sort the list (by string-name) later. -} - -entry* cpool::ensureUtf8(bytes& b) { - entry*& ix = hashTabRef(CONSTANT_Utf8, b); - if (ix != null) return ix; - // Make one. - if (nentries == maxentries) { - abort("cp utf8 overflow"); - return &entries[tag_base[CONSTANT_Utf8]]; // return something - } - entry& e = entries[nentries++]; - e.tag = CONSTANT_Utf8; - u->saveTo(e.value.b, b); - assert(&e >= first_extra_entry); - insert_extra(&e, tag_extras[CONSTANT_Utf8]); - PRINTCR((4,"ensureUtf8 miss %s", e.string())); - return ix = &e; -} - -entry* cpool::ensureClass(bytes& b) { - entry*& ix = hashTabRef(CONSTANT_Class, b); - if (ix != null) return ix; - // Make one. - if (nentries == maxentries) { - abort("cp class overflow"); - return &entries[tag_base[CONSTANT_Class]]; // return something - } - entry& e = entries[nentries++]; - e.tag = CONSTANT_Class; - e.nrefs = 1; - e.refs = U_NEW(entry*, 1); - ix = &e; // hold my spot in the index - entry* utf = ensureUtf8(b); - e.refs[0] = utf; - e.value.b = utf->value.b; - assert(&e >= first_extra_entry); - insert_extra(&e, tag_extras[CONSTANT_Class]); - PRINTCR((4,"ensureClass miss %s", e.string())); - return &e; -} - -void cpool::expandSignatures() { - int i; - int nsigs = 0; - int nreused = 0; - int first_sig = tag_base[CONSTANT_Signature]; - int sig_limit = tag_count[CONSTANT_Signature] + first_sig; - fillbytes buf; - buf.init(1<<10); - CHECK; - for (i = first_sig; i < sig_limit; i++) { - entry& e = entries[i]; - assert(e.tag == CONSTANT_Signature); - int refnum = 0; - bytes form = e.refs[refnum++]->asUtf8(); - buf.empty(); - for (int j = 0; j < (int)form.len; j++) { - int c = form.ptr[j]; - buf.addByte(c); - if (c == 'L') { - entry* cls = e.refs[refnum++]; - buf.append(cls->className()->asUtf8()); - } - } - assert(refnum == e.nrefs); - bytes& sig = buf.b; - PRINTCR((5,"signature %d %s -> %s", i, form.ptr, sig.ptr)); - - // try to find a pre-existing Utf8: - entry* &e2 = hashTabRef(CONSTANT_Utf8, sig); - if (e2 != null) { - assert(e2->isUtf8(sig)); - e.value.b = e2->value.b; - e.refs[0] = e2; - e.nrefs = 1; - PRINTCR((5,"signature replaced %d => %s", i, e.string())); - nreused++; - } else { - // there is no other replacement; reuse this CP entry as a Utf8 - u->saveTo(e.value.b, sig); - e.tag = CONSTANT_Utf8; - e.nrefs = 0; - e2 = &e; - PRINTCR((5,"signature changed %d => %s", e.inord, e.string())); - } - nsigs++; - } - PRINTCR((1,"expanded %d signatures (reused %d utfs)", nsigs, nreused)); - buf.free(); - - // go expunge all references to remaining signatures: - for (i = 0; i < (int)nentries; i++) { - entry& e = entries[i]; - for (int j = 0; j < e.nrefs; j++) { - entry*& e2 = e.refs[j]; - if (e2 != null && e2->tag == CONSTANT_Signature) - e2 = e2->refs[0]; - } - } -} - -bool isLoadableValue(int tag) { - switch(tag) { - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_Long: - case CONSTANT_Double: - case CONSTANT_String: - case CONSTANT_Class: - case CONSTANT_MethodHandle: - case CONSTANT_MethodType: - return true; - default: - return false; - } -} -/* - * this method can be used to size an array using null as the parameter, - * thereafter can be reused to initialize the array using a valid pointer - * as a parameter. - */ -int cpool::initLoadableValues(entry** loadable_entries) { - int loadable_count = 0; - for (int i = 0; i < (int)N_TAGS_IN_ORDER; i++) { - int tag = TAGS_IN_ORDER[i]; - if (!isLoadableValue(tag)) - continue; - if (loadable_entries != NULL) { - for (int n = 0 ; n < tag_count[tag] ; n++) { - loadable_entries[loadable_count + n] = &entries[tag_base[tag] + n]; - } - } - loadable_count += tag_count[tag]; - } - return loadable_count; -} - -// Initialize various views into the constant pool. -void cpool::initGroupIndexes() { - // Initialize All - int all_count = 0; - for (int tag = CONSTANT_None ; tag < CONSTANT_Limit ; tag++) { - all_count += tag_count[tag]; - } - entry* all_entries = &entries[tag_base[CONSTANT_None]]; - tag_group_count[CONSTANT_All - CONSTANT_All] = all_count; - tag_group_index[CONSTANT_All - CONSTANT_All].init(all_count, all_entries, CONSTANT_All); - - // Initialize LoadableValues - int loadable_count = initLoadableValues(NULL); - entry** loadable_entries = U_NEW(entry*, loadable_count); - initLoadableValues(loadable_entries); - tag_group_count[CONSTANT_LoadableValue - CONSTANT_All] = loadable_count; - tag_group_index[CONSTANT_LoadableValue - CONSTANT_All].init(loadable_count, - loadable_entries, CONSTANT_LoadableValue); - -// Initialize AnyMembers - int any_count = tag_count[CONSTANT_Fieldref] + - tag_count[CONSTANT_Methodref] + - tag_count[CONSTANT_InterfaceMethodref]; - entry *any_entries = &entries[tag_base[CONSTANT_Fieldref]]; - tag_group_count[CONSTANT_AnyMember - CONSTANT_All] = any_count; - tag_group_index[CONSTANT_AnyMember - CONSTANT_All].init(any_count, - any_entries, CONSTANT_AnyMember); -} - -void cpool::initMemberIndexes() { - // This function does NOT refer to any class schema. - // It is totally internal to the cpool. - int i, j; - - // Get the pre-existing indexes: - int nclasses = tag_count[CONSTANT_Class]; - entry* classes = tag_base[CONSTANT_Class] + entries; - int nfields = tag_count[CONSTANT_Fieldref]; - entry* fields = tag_base[CONSTANT_Fieldref] + entries; - int nmethods = tag_count[CONSTANT_Methodref]; - entry* methods = tag_base[CONSTANT_Methodref] + entries; - - int* field_counts = T_NEW(int, nclasses); - int* method_counts = T_NEW(int, nclasses); - cpindex* all_indexes = U_NEW(cpindex, nclasses*2); - entry** field_ix = U_NEW(entry*, add_size(nfields, nclasses)); - entry** method_ix = U_NEW(entry*, add_size(nmethods, nclasses)); - - for (j = 0; j < nfields; j++) { - entry& f = fields[j]; - i = f.memberClass()->inord; - assert(i < nclasses); - field_counts[i]++; - } - for (j = 0; j < nmethods; j++) { - entry& m = methods[j]; - i = m.memberClass()->inord; - assert(i < nclasses); - method_counts[i]++; - } - - int fbase = 0, mbase = 0; - for (i = 0; i < nclasses; i++) { - int fc = field_counts[i]; - int mc = method_counts[i]; - all_indexes[i*2+0].init(fc, field_ix+fbase, - CONSTANT_Fieldref + SUBINDEX_BIT); - all_indexes[i*2+1].init(mc, method_ix+mbase, - CONSTANT_Methodref + SUBINDEX_BIT); - // reuse field_counts and member_counts as fill pointers: - field_counts[i] = fbase; - method_counts[i] = mbase; - PRINTCR((3, "class %d fields @%d[%d] methods @%d[%d]", - i, fbase, fc, mbase, mc)); - fbase += fc+1; - mbase += mc+1; - // (the +1 leaves a space between every subarray) - } - assert(fbase == nfields+nclasses); - assert(mbase == nmethods+nclasses); - - for (j = 0; j < nfields; j++) { - entry& f = fields[j]; - i = f.memberClass()->inord; - field_ix[field_counts[i]++] = &f; - } - for (j = 0; j < nmethods; j++) { - entry& m = methods[j]; - i = m.memberClass()->inord; - method_ix[method_counts[i]++] = &m; - } - - member_indexes = all_indexes; - -#ifndef PRODUCT - // Test the result immediately on every class and field. - int fvisited = 0, mvisited = 0; - int prevord, len; - for (i = 0; i < nclasses; i++) { - entry* cls = &classes[i]; - cpindex* fix = getFieldIndex(cls); - cpindex* mix = getMethodIndex(cls); - PRINTCR((2, "field and method index for %s [%d] [%d]", - cls->string(), mix->len, fix->len)); - prevord = -1; - for (j = 0, len = fix->len; j < len; j++) { - entry* f = fix->get(j); - assert(f != null); - PRINTCR((3, "- field %s", f->string())); - assert(f->memberClass() == cls); - assert(prevord < (int)f->inord); - prevord = f->inord; - fvisited++; - } - assert(fix->base2[j] == null); - prevord = -1; - for (j = 0, len = mix->len; j < len; j++) { - entry* m = mix->get(j); - assert(m != null); - PRINTCR((3, "- method %s", m->string())); - assert(m->memberClass() == cls); - assert(prevord < (int)m->inord); - prevord = m->inord; - mvisited++; - } - assert(mix->base2[j] == null); - } - assert(fvisited == nfields); - assert(mvisited == nmethods); -#endif - - // Free intermediate buffers. - u->free_temps(); -} - -void entry::requestOutputIndex(cpool& cp, int req) { - assert(outputIndex <= REQUESTED_NONE); // must not have assigned indexes yet - if (tag == CONSTANT_Signature) { - ref(0)->requestOutputIndex(cp, req); - return; - } - assert(req == REQUESTED || req == REQUESTED_LDC); - if (outputIndex != REQUESTED_NONE) { - if (req == REQUESTED_LDC) - outputIndex = req; // this kind has precedence - return; - } - outputIndex = req; - //assert(!cp.outputEntries.contains(this)); - assert(tag != CONSTANT_Signature); - // The BSMs are jetisoned to a side table, however all references - // that the BSMs refer to, need to be considered. - if (tag == CONSTANT_BootstrapMethod) { - // this is a a pseudo-op entry; an attribute will be generated later on - cp.requested_bsms.add(this); - } else { - // all other tag types go into real output file CP: - cp.outputEntries.add(this); - } - for (int j = 0; j < nrefs; j++) { - ref(j)->requestOutputIndex(cp); - } -} - -void cpool::resetOutputIndexes() { - /* - * reset those few entries that are being used in the current class - * (Caution since this method is called after every class written, a loop - * over every global constant pool entry would be a quadratic cost.) - */ - - int noes = outputEntries.length(); - entry** oes = (entry**) outputEntries.base(); - for (int i = 0 ; i < noes ; i++) { - entry& e = *oes[i]; - e.outputIndex = REQUESTED_NONE; - } - - // do the same for bsms and reset them if required - int nbsms = requested_bsms.length(); - entry** boes = (entry**) requested_bsms.base(); - for (int i = 0 ; i < nbsms ; i++) { - entry& e = *boes[i]; - e.outputIndex = REQUESTED_NONE; - } - outputIndexLimit = 0; - outputEntries.empty(); -#ifndef PRODUCT - // ensure things are cleared out - for (int i = 0; i < (int)maxentries; i++) - assert(entries[i].outputIndex == REQUESTED_NONE); -#endif -} - -static const byte TAG_ORDER[CONSTANT_Limit] = { - 0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8, 0, 13, 14, 15, 16 -}; - -extern "C" -int outputEntry_cmp(const void* e1p, const void* e2p) { - // Sort entries according to the Pack200 rules for deterministic - // constant pool ordering. - // - // The four sort keys as follows, in order of decreasing importance: - // 1. ldc first, then non-ldc guys - // 2. normal cp_All entries by input order (i.e., address order) - // 3. after that, extra entries by lexical order (as in tag_extras[*]) - entry& e1 = *(entry*) *(void**) e1p; - entry& e2 = *(entry*) *(void**) e2p; - int oi1 = e1.outputIndex; - int oi2 = e2.outputIndex; - assert(oi1 == REQUESTED || oi1 == REQUESTED_LDC); - assert(oi2 == REQUESTED || oi2 == REQUESTED_LDC); - if (oi1 != oi2) { - if (oi1 == REQUESTED_LDC) return 0-1; - if (oi2 == REQUESTED_LDC) return 1-0; - // Else fall through; neither is an ldc request. - } - if (e1.inord != NO_INORD || e2.inord != NO_INORD) { - // One or both is normal. Use input order. - if (&e1 > &e2) return 1-0; - if (&e1 < &e2) return 0-1; - return 0; // equal pointers - } - // Both are extras. Sort by tag and then by value. - if (e1.tag != e2.tag) { - return TAG_ORDER[e1.tag] - TAG_ORDER[e2.tag]; - } - // If the tags are the same, use string comparison. - return compare_Utf8_chars(e1.value.b, e2.value.b); -} - -void cpool::computeOutputIndexes() { - int i; - -#ifndef PRODUCT - // outputEntries must be a complete list of those requested: - static uint checkStart = 0; - int checkStep = 1; - if (nentries > 100) checkStep = nentries / 100; - for (i = (int)(checkStart++ % checkStep); i < (int)nentries; i += checkStep) { - entry& e = entries[i]; - if (e.tag == CONSTANT_BootstrapMethod) { - if (e.outputIndex != REQUESTED_NONE) { - assert(requested_bsms.contains(&e)); - } else { - assert(!requested_bsms.contains(&e)); - } - } else { - if (e.outputIndex != REQUESTED_NONE) { - assert(outputEntries.contains(&e)); - } else { - assert(!outputEntries.contains(&e)); - } - } - } - - // check hand-initialization of TAG_ORDER - for (i = 0; i < (int)N_TAGS_IN_ORDER; i++) { - byte tag = TAGS_IN_ORDER[i]; - assert(TAG_ORDER[tag] == i+1); - } -#endif - - int noes = outputEntries.length(); - entry** oes = (entry**) outputEntries.base(); - - // Sort the output constant pool into the order required by Pack200. - PTRLIST_QSORT(outputEntries, outputEntry_cmp); - - // Allocate a new index for each entry that needs one. - // We do this in two passes, one for LDC entries and one for the rest. - int nextIndex = 1; // always skip index #0 in output cpool - for (i = 0; i < noes; i++) { - entry& e = *oes[i]; - assert(e.outputIndex >= REQUESTED_LDC); - e.outputIndex = nextIndex++; - if (e.isDoubleWord()) nextIndex++; // do not use the next index - } - outputIndexLimit = nextIndex; - PRINTCR((3,"renumbering CP to %d entries", outputIndexLimit)); -} - -#ifndef PRODUCT -// debugging goo - -unpacker* debug_u; - -static bytes& getbuf(size_t len) { // for debugging only! - static int bn = 0; - static bytes bufs[8]; - bytes& buf = bufs[bn++ & 7]; - while (buf.len < len + 10) { - buf.realloc(buf.len ? buf.len * 2 : 1000); - } - buf.ptr[0] = 0; // for the sake of strcat - return buf; -} - -const char* entry::string() { - bytes buf; - switch (tag) { - case CONSTANT_None: - return ""; - case CONSTANT_Signature: - if (value.b.ptr == null) - return ref(0)->string(); - /* fall through */ - case CONSTANT_Utf8: - buf = value.b; - break; - case CONSTANT_Integer: - case CONSTANT_Float: - buf = getbuf(12); - sprintf((char*)buf.ptr, "0x%08x", value.i); - break; - case CONSTANT_Long: - case CONSTANT_Double: - buf = getbuf(24); - sprintf((char*)buf.ptr, "0x" LONG_LONG_HEX_FORMAT, value.l); - break; - default: - if (nrefs == 0) { - return TAG_NAME[tag]; - } else if (nrefs == 1) { - return refs[0]->string(); - } else { - const char* s1 = refs[0]->string(); - const char* s2 = refs[1]->string(); - buf = getbuf(strlen(s1) + 1 + strlen(s2) + 4 + 1); - buf.strcat(s1).strcat(" ").strcat(s2); - if (nrefs > 2) buf.strcat(" ..."); - } - } - return (const char*)buf.ptr; -} - -void print_cp_entry(int i) { - entry& e = debug_u->cp.entries[i]; - - if ((uint)e.tag < CONSTANT_Limit) { - printf(" %d\t%s %s\n", i, TAG_NAME[e.tag], e.string()); - } else { - printf(" %d\t%d %s\n", i, e.tag, e.string()); - } -} - -void print_cp_entries(int beg, int end) { - for (int i = beg; i < end; i++) - print_cp_entry(i); -} - -void print_cp() { - print_cp_entries(0, debug_u->cp.nentries); -} - -#endif - -// Unpacker Start - -const char str_tf[] = "true\0false"; -#undef STR_TRUE -#undef STR_FALSE -#define STR_TRUE (&str_tf[0]) -#define STR_FALSE (&str_tf[5]) - -const char* unpacker::get_option(const char* prop) { - if (prop == null ) return null; - if (strcmp(prop, UNPACK_DEFLATE_HINT) == 0) { - return deflate_hint_or_zero == 0? null : STR_TF(deflate_hint_or_zero > 0); -#ifdef HAVE_STRIP - } else if (strcmp(prop, UNPACK_STRIP_COMPILE) == 0) { - return STR_TF(strip_compile); - } else if (strcmp(prop, UNPACK_STRIP_DEBUG) == 0) { - return STR_TF(strip_debug); - } else if (strcmp(prop, UNPACK_STRIP_JCOV) == 0) { - return STR_TF(strip_jcov); -#endif /*HAVE_STRIP*/ - } else if (strcmp(prop, UNPACK_REMOVE_PACKFILE) == 0) { - return STR_TF(remove_packfile); - } else if (strcmp(prop, DEBUG_VERBOSE) == 0) { - return saveIntStr(verbose); - } else if (strcmp(prop, UNPACK_MODIFICATION_TIME) == 0) { - return (modification_time_or_zero == 0)? null: - saveIntStr(modification_time_or_zero); - } else if (strcmp(prop, UNPACK_LOG_FILE) == 0) { - return log_file; - } else { - return NULL; // unknown option ignore - } -} - -bool unpacker::set_option(const char* prop, const char* value) { - if (prop == NULL) return false; - if (strcmp(prop, UNPACK_DEFLATE_HINT) == 0) { - deflate_hint_or_zero = ( (value == null || strcmp(value, "keep") == 0) - ? 0: BOOL_TF(value) ? +1: -1); -#ifdef HAVE_STRIP - } else if (strcmp(prop, UNPACK_STRIP_COMPILE) == 0) { - strip_compile = STR_TF(value); - } else if (strcmp(prop, UNPACK_STRIP_DEBUG) == 0) { - strip_debug = STR_TF(value); - } else if (strcmp(prop, UNPACK_STRIP_JCOV) == 0) { - strip_jcov = STR_TF(value); -#endif /*HAVE_STRIP*/ - } else if (strcmp(prop, UNPACK_REMOVE_PACKFILE) == 0) { - remove_packfile = STR_TF(value); - } else if (strcmp(prop, DEBUG_VERBOSE) == 0) { - verbose = (value == null)? 0: atoi(value); - } else if (strcmp(prop, DEBUG_VERBOSE ".bands") == 0) { -#ifndef PRODUCT - verbose_bands = (value == null)? 0: atoi(value); -#endif - } else if (strcmp(prop, UNPACK_MODIFICATION_TIME) == 0) { - if (value == null || (strcmp(value, "keep") == 0)) { - modification_time_or_zero = 0; - } else if (strcmp(value, "now") == 0) { - time_t now; - time(&now); - modification_time_or_zero = (int) now; - } else { - modification_time_or_zero = atoi(value); - if (modification_time_or_zero == 0) - modification_time_or_zero = 1; // make non-zero - } - } else if (strcmp(prop, UNPACK_LOG_FILE) == 0) { - log_file = (value == null)? value: saveStr(value); - } else { - return false; // unknown option ignore - } - return true; -} - -// Deallocate all internal storage and reset to a clean state. -// Do not disturb any input or output connections, including -// infileptr, infileno, inbytes, read_input_fn, jarout, or errstrm. -// Do not reset any unpack options. -void unpacker::reset() { - bytes_read_before_reset += bytes_read; - bytes_written_before_reset += bytes_written; - files_written_before_reset += files_written; - classes_written_before_reset += classes_written; - segments_read_before_reset += 1; - if (verbose >= 2) { - fprintf(errstrm, - "After segment %d, " - LONG_LONG_FORMAT " bytes read and " - LONG_LONG_FORMAT " bytes written.\n", - segments_read_before_reset-1, - bytes_read_before_reset, bytes_written_before_reset); - fprintf(errstrm, - "After segment %d, %d files (of which %d are classes) written to output.\n", - segments_read_before_reset-1, - files_written_before_reset, classes_written_before_reset); - if (archive_next_count != 0) { - fprintf(errstrm, - "After segment %d, %d segment%s remaining (estimated).\n", - segments_read_before_reset-1, - archive_next_count, archive_next_count==1?"":"s"); - } - } - - unpacker save_u = (*this); // save bytewise image - infileptr = null; // make asserts happy - jniobj = null; // make asserts happy - jarout = null; // do not close the output jar - gzin = null; // do not close the input gzip stream - bytes esn; - if (errstrm_name != null) { - esn.saveFrom(errstrm_name); - } else { - esn.set(null, 0); - } - this->free(); - mtrace('s', 0, 0); // note the boundary between segments - this->init(read_input_fn); - - // restore selected interface state: -#define SAVE(x) this->x = save_u.x - SAVE(jniobj); - SAVE(jnienv); - SAVE(infileptr); // buffered - SAVE(infileno); // unbuffered - SAVE(inbytes); // direct - SAVE(jarout); - SAVE(gzin); - //SAVE(read_input_fn); - SAVE(errstrm); - SAVE(verbose); // verbose level, 0 means no output - SAVE(strip_compile); - SAVE(strip_debug); - SAVE(strip_jcov); - SAVE(remove_packfile); - SAVE(deflate_hint_or_zero); // ==0 means not set, otherwise -1 or 1 - SAVE(modification_time_or_zero); - SAVE(bytes_read_before_reset); - SAVE(bytes_written_before_reset); - SAVE(files_written_before_reset); - SAVE(classes_written_before_reset); - SAVE(segments_read_before_reset); -#undef SAVE - if (esn.len > 0) { - errstrm_name = saveStr(esn.strval()); - esn.free(); - } - log_file = errstrm_name; - // Note: If we use strip_names, watch out: They get nuked here. -} - -void unpacker::init(read_input_fn_t input_fn) { - int i; - NOT_PRODUCT(debug_u = this); - BYTES_OF(*this).clear(); -#ifndef PRODUCT - free(); // just to make sure freeing is idempotent -#endif - this->u = this; // self-reference for U_NEW macro - errstrm = stdout; // default error-output - log_file = LOGFILE_STDOUT; - read_input_fn = input_fn; - all_bands = band::makeBands(this); - // Make a default jar buffer; caller may safely overwrite it. - jarout = U_NEW(jar, 1); - jarout->init(this); - for (i = 0; i < ATTR_CONTEXT_LIMIT; i++) - attr_defs[i].u = u; // set up outer ptr -} - -const char* unpacker::get_abort_message() { - return abort_message; -} - -void unpacker::dump_options() { - static const char* opts[] = { - UNPACK_LOG_FILE, - UNPACK_DEFLATE_HINT, -#ifdef HAVE_STRIP - UNPACK_STRIP_COMPILE, - UNPACK_STRIP_DEBUG, - UNPACK_STRIP_JCOV, -#endif /*HAVE_STRIP*/ - UNPACK_REMOVE_PACKFILE, - DEBUG_VERBOSE, - UNPACK_MODIFICATION_TIME, - null - }; - for (int i = 0; opts[i] != null; i++) { - const char* str = get_option(opts[i]); - if (str == null) { - if (verbose == 0) continue; - str = "(not set)"; - } - fprintf(errstrm, "%s=%s\n", opts[i], str); - } -} - - -// Usage: unpack a byte buffer -// packptr is a reference to byte buffer containing a -// packed file and len is the length of the buffer. -// If null, the callback is used to fill an internal buffer. -void unpacker::start(void* packptr, size_t len) { - CHECK; - NOT_PRODUCT(debug_u = this); - if (packptr != null && len != 0) { - inbytes.set((byte*) packptr, len); - } - CHECK; - read_bands(); -} - -void unpacker::check_options() { - const char* strue = "true"; - const char* sfalse = "false"; - if (deflate_hint_or_zero != 0) { - bool force_deflate_hint = (deflate_hint_or_zero > 0); - if (force_deflate_hint) - default_file_options |= FO_DEFLATE_HINT; - else - default_file_options &= ~FO_DEFLATE_HINT; - // Turn off per-file deflate hint by force. - suppress_file_options |= FO_DEFLATE_HINT; - } - if (modification_time_or_zero != 0) { - default_file_modtime = modification_time_or_zero; - // Turn off per-file modtime by force. - archive_options &= ~AO_HAVE_FILE_MODTIME; - } - // %%% strip_compile, etc... -} - -// classfile writing - -void unpacker::reset_cur_classfile() { - // set defaults - cur_class_minver = default_class_minver; - cur_class_majver = default_class_majver; - - // reset constant pool state - cp.resetOutputIndexes(); - - // reset fixups - class_fixup_type.empty(); - class_fixup_offset.empty(); - class_fixup_ref.empty(); - requested_ics.empty(); - cp.requested_bsms.empty(); -} - -cpindex* cpool::getKQIndex() { - char ch = '?'; - if (u->cur_descr != null) { - entry* type = u->cur_descr->descrType(); - ch = type->value.b.ptr[0]; - } - byte tag = CONSTANT_Integer; - switch (ch) { - case 'L': tag = CONSTANT_String; break; - case 'I': tag = CONSTANT_Integer; break; - case 'J': tag = CONSTANT_Long; break; - case 'F': tag = CONSTANT_Float; break; - case 'D': tag = CONSTANT_Double; break; - case 'B': case 'S': case 'C': - case 'Z': tag = CONSTANT_Integer; break; - default: abort("bad KQ reference"); break; - } - return getIndex(tag); -} - -uint unpacker::to_bci(uint bii) { - uint len = bcimap.length(); - uint* map = (uint*) bcimap.base(); - assert(len > 0); // must be initialized before using to_bci - if (len == 0) { - abort("bad bcimap"); - return 0; - } - if (bii < len) - return map[bii]; - // Else it's a fractional or out-of-range BCI. - uint key = bii-len; - for (int i = len; ; i--) { - if (map[i-1]-(i-1) <= key) - break; - else - --bii; - } - return bii; -} - -void unpacker::put_stackmap_type() { - int tag = code_StackMapTable_T.getByte(); - putu1(tag); - switch (tag) { - case 7: // (7) [RCH] - putref(code_StackMapTable_RC.getRef()); - break; - case 8: // (8) [PH] - putu2(to_bci(code_StackMapTable_P.getInt())); - CHECK; - break; - } -} - -// Functions for writing code. - -maybe_inline -void unpacker::put_label(int curIP, int size) { - code_fixup_type.addByte(size); - code_fixup_offset.add((int)put_empty(size)); - code_fixup_source.add(curIP); -} - -inline // called exactly once => inline -void unpacker::write_bc_ops() { - bcimap.empty(); - code_fixup_type.empty(); - code_fixup_offset.empty(); - code_fixup_source.empty(); - - band* bc_which; - - byte* opptr = bc_codes.curRP(); - // No need for oplimit, since the codes are pre-counted. - - size_t codeBase = wpoffset(); - - bool isAload; // copy-out result - int origBC; - - entry* thisClass = cur_class; - entry* superClass = cur_super; - entry* newClass = null; // class of last _new opcode - - // overwrite any prior index on these bands; it changes w/ current class: - bc_thisfield.setIndex( cp.getFieldIndex( thisClass)); - bc_thismethod.setIndex( cp.getMethodIndex(thisClass)); - if (superClass != null) { - bc_superfield.setIndex( cp.getFieldIndex( superClass)); - bc_supermethod.setIndex(cp.getMethodIndex(superClass)); - } else { - NOT_PRODUCT(bc_superfield.setIndex(null)); - NOT_PRODUCT(bc_supermethod.setIndex(null)); - } - CHECK; - - for (int curIP = 0; ; curIP++) { - CHECK; - int curPC = (int)(wpoffset() - codeBase); - bcimap.add(curPC); - ensure_put_space(10); // covers most instrs w/o further bounds check - int bc = *opptr++ & 0xFF; - - putu1_fast(bc); - // Note: See '--wp' below for pseudo-bytecodes like bc_end_marker. - - bool isWide = false; - if (bc == bc_wide) { - bc = *opptr++ & 0xFF; - putu1_fast(bc); - isWide = true; - } - switch (bc) { - case bc_end_marker: - --wp; // not really part of the code - assert(opptr <= bc_codes.maxRP()); - bc_codes.curRP() = opptr; // advance over this in bc_codes - goto doneScanningMethod; - case bc_tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) - case bc_lookupswitch: // apc: (df, nc, nc*(case, label)) - { - int caseCount = bc_case_count.getInt(); - while (((wpoffset() - codeBase) % 4) != 0) putu1_fast(0); - ensure_put_space(30 + caseCount*8); - put_label(curIP, 4); //int df = bc_label.getInt(); - if (bc == bc_tableswitch) { - int lo = bc_case_value.getInt(); - int hi = lo + caseCount-1; - putu4(lo); - putu4(hi); - for (int j = 0; j < caseCount; j++) { - put_label(curIP, 4); //int lVal = bc_label.getInt(); - //int cVal = lo + j; - } - } else { - putu4(caseCount); - for (int j = 0; j < caseCount; j++) { - int cVal = bc_case_value.getInt(); - putu4(cVal); - put_label(curIP, 4); //int lVal = bc_label.getInt(); - } - } - assert((int)to_bci(curIP) == curPC); - continue; - } - case bc_iinc: - { - int local = bc_local.getInt(); - int delta = (isWide ? bc_short : bc_byte).getInt(); - if (isWide) { - putu2(local); - putu2(delta); - } else { - putu1_fast(local); - putu1_fast(delta); - } - continue; - } - case bc_sipush: - { - int val = bc_short.getInt(); - putu2(val); - continue; - } - case bc_bipush: - case bc_newarray: - { - int val = bc_byte.getByte(); - putu1_fast(val); - continue; - } - case bc_ref_escape: - { - // Note that insnMap has one entry for this. - --wp; // not really part of the code - int size = bc_escrefsize.getInt(); - entry* ref = bc_escref.getRefN(); - CHECK; - switch (size) { - case 1: putu1ref(ref); break; - case 2: putref(ref); break; - default: assert(false); - } - continue; - } - case bc_byte_escape: - { - // Note that insnMap has one entry for all these bytes. - --wp; // not really part of the code - int size = bc_escsize.getInt(); - if (size < 0) { assert(false); continue; } - ensure_put_space(size); - for (int j = 0; j < size; j++) - putu1_fast(bc_escbyte.getByte()); - continue; - } - default: - if (is_invoke_init_op(bc)) { - origBC = bc_invokespecial; - entry* classRef; - switch (bc - _invokeinit_op) { - case _invokeinit_self_option: classRef = thisClass; break; - case _invokeinit_super_option: classRef = superClass; break; - default: assert(bc == _invokeinit_op+_invokeinit_new_option); - /* fall through */ - case _invokeinit_new_option: classRef = newClass; break; - } - wp[-1] = origBC; // overwrite with origBC - int coding = bc_initref.getInt(); - // Find the nth overloading of in classRef. - entry* ref = null; - cpindex* ix = cp.getMethodIndex(classRef); - CHECK; - for (int j = 0, which_init = 0; ; j++) { - ref = (ix == null)? null: ix->get(j); - if (ref == null) break; // oops, bad input - assert(ref->tag == CONSTANT_Methodref); - if (ref->memberDescr()->descrName() == cp.sym[cpool::s_lt_init_gt]) { - if (which_init++ == coding) break; - } - } - putref(ref); - continue; - } - bc_which = ref_band_for_self_op(bc, isAload, origBC); - if (bc_which != null) { - if (!isAload) { - wp[-1] = origBC; // overwrite with origBC - } else { - wp[-1] = bc_aload_0; // overwrite with _aload_0 - // Note: insnMap keeps the _aload_0 separate. - bcimap.add(++curPC); - ++curIP; - putu1_fast(origBC); - } - entry* ref = bc_which->getRef(); - CHECK; - putref(ref); - continue; - } - if (is_branch_op(bc)) { - //int lVal = bc_label.getInt(); - if (bc < bc_goto_w) { - put_label(curIP, 2); //putu2(lVal & 0xFFFF); - } else { - assert(bc <= bc_jsr_w); - put_label(curIP, 4); //putu4(lVal); - } - assert((int)to_bci(curIP) == curPC); - continue; - } - bc_which = ref_band_for_op(bc); - if (bc_which != null) { - entry* ref = bc_which->getRefCommon(bc_which->ix, bc_which->nullOK); - CHECK; - if (ref == null && bc_which == &bc_classref) { - // Shorthand for class self-references. - ref = thisClass; - } - origBC = bc; - switch (bc) { - case _invokestatic_int: - origBC = bc_invokestatic; - break; - case _invokespecial_int: - origBC = bc_invokespecial; - break; - case bc_ildc: - case bc_cldc: - case bc_fldc: - case bc_sldc: - case bc_qldc: - origBC = bc_ldc; - break; - case bc_ildc_w: - case bc_cldc_w: - case bc_fldc_w: - case bc_sldc_w: - case bc_qldc_w: - origBC = bc_ldc_w; - break; - case bc_lldc2_w: - case bc_dldc2_w: - origBC = bc_ldc2_w; - break; - case bc_new: - newClass = ref; - break; - } - wp[-1] = origBC; // overwrite with origBC - if (origBC == bc_ldc) { - putu1ref(ref); - } else { - putref(ref); - } - if (origBC == bc_multianewarray) { - // Copy the trailing byte also. - int val = bc_byte.getByte(); - putu1_fast(val); - } else if (origBC == bc_invokeinterface) { - int argSize = ref->memberDescr()->descrType()->typeSize(); - putu1_fast(1 + argSize); - putu1_fast(0); - } else if (origBC == bc_invokedynamic) { - // pad the next two byte - putu1_fast(0); - putu1_fast(0); - } - continue; - } - if (is_local_slot_op(bc)) { - int local = bc_local.getInt(); - if (isWide) { - putu2(local); - if (bc == bc_iinc) { - int iVal = bc_short.getInt(); - putu2(iVal); - } - } else { - putu1_fast(local); - if (bc == bc_iinc) { - int iVal = bc_byte.getByte(); - putu1_fast(iVal); - } - } - continue; - } - // Random bytecode. Just copy it. - assert(bc < bc_bytecode_limit); - } - } - doneScanningMethod:{} - //bcimap.add(curPC); // PC limit is already also in map, from bc_end_marker - - // Armed with a bcimap, we can now fix up all the labels. - for (int i = 0; i < (int)code_fixup_type.size(); i++) { - int type = code_fixup_type.getByte(i); - byte* bp = wp_at(code_fixup_offset.get(i)); - int curIP = code_fixup_source.get(i); - int destIP = curIP + bc_label.getInt(); - int span = to_bci(destIP) - to_bci(curIP); - CHECK; - switch (type) { - case 2: putu2_at(bp, (ushort)span); break; - case 4: putu4_at(bp, span); break; - default: assert(false); - } - } -} - -inline // called exactly once => inline -void unpacker::write_code() { - int j; - - int max_stack, max_locals, handler_count, cflags; - get_code_header(max_stack, max_locals, handler_count, cflags); - - if (max_stack < 0) max_stack = code_max_stack.getInt(); - if (max_locals < 0) max_locals = code_max_na_locals.getInt(); - if (handler_count < 0) handler_count = code_handler_count.getInt(); - - int siglen = cur_descr->descrType()->typeSize(); - CHECK; - if ((cur_descr_flags & ACC_STATIC) == 0) siglen++; - max_locals += siglen; - - putu2(max_stack); - putu2(max_locals); - size_t bcbase = put_empty(4); - - // Write the bytecodes themselves. - write_bc_ops(); - CHECK; - - byte* bcbasewp = wp_at(bcbase); - putu4_at(bcbasewp, (int)(wp - (bcbasewp+4))); // size of code attr - - putu2(handler_count); - for (j = 0; j < handler_count; j++) { - int bii = code_handler_start_P.getInt(); - putu2(to_bci(bii)); - bii += code_handler_end_PO.getInt(); - putu2(to_bci(bii)); - bii += code_handler_catch_PO.getInt(); - putu2(to_bci(bii)); - putref(code_handler_class_RCN.getRefN()); - CHECK; - } - - julong indexBits = cflags; - if (cflags < 0) { - bool haveLongFlags = attr_defs[ATTR_CONTEXT_CODE].haveLongFlags(); - indexBits = code_flags_hi.getLong(code_flags_lo, haveLongFlags); - } - write_attrs(ATTR_CONTEXT_CODE, indexBits); -} - -int unpacker::write_attrs(int attrc, julong indexBits) { - CHECK_0; - if (indexBits == 0) { - // Quick short-circuit. - putu2(0); - return 0; - } - - attr_definitions& ad = attr_defs[attrc]; - - int i, j, j2, idx, count; - - int oiCount = 0; - if (ad.isPredefined(X_ATTR_OVERFLOW) - && (indexBits & ((julong)1<>= 1) { - if ((indexBits & 1) != 0) - bitIndexes[biCount++] = idx; - } - assert(biCount <= (int)lengthof(bitIndexes)); - - // Write a provisional attribute count, perhaps to be corrected later. - int naOffset = (int)wpoffset(); - int na0 = biCount + oiCount; - putu2(na0); - - int na = 0; - for (i = 0; i < na0; i++) { - if (i < biCount) - idx = bitIndexes[i]; - else - idx = ad.xxx_attr_indexes().getInt(); - assert(ad.isIndex(idx)); - entry* aname = null; - entry* ref; // scratch - size_t abase = put_empty(2+4); - CHECK_0; - if (idx < (int)ad.flag_limit && ad.isPredefined(idx)) { - // Switch on the attrc and idx simultaneously. - switch (ADH_BYTE(attrc, idx)) { - - case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_OVERFLOW): - case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_OVERFLOW): - case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_OVERFLOW): - case ADH_BYTE(ATTR_CONTEXT_CODE, X_ATTR_OVERFLOW): - // no attribute at all, so back up on this one - wp = wp_at(abase); - continue; - - case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_ClassFile_version): - cur_class_minver = class_ClassFile_version_minor_H.getInt(); - cur_class_majver = class_ClassFile_version_major_H.getInt(); - // back up; not a real attribute - wp = wp_at(abase); - continue; - - case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_InnerClasses): - // note the existence of this attr, but save for later - if (cur_class_has_local_ics) - abort("too many InnerClasses attrs"); - cur_class_has_local_ics = true; - wp = wp_at(abase); - continue; - - case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_SourceFile): - aname = cp.sym[cpool::s_SourceFile]; - ref = class_SourceFile_RUN.getRefN(); - CHECK_0; - if (ref == null) { - bytes& n = cur_class->ref(0)->value.b; - // parse n = (/)*?($)* - int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, (int)n.len)+1; - bytes prefix = n.slice(pkglen, n.len); - for (;;) { - // Work backwards, finding all '$', '#', etc. - int dollar = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, prefix, (int)prefix.len); - if (dollar < 0) break; - prefix = prefix.slice(0, dollar); - } - const char* suffix = ".java"; - int len = (int)(prefix.len + strlen(suffix)); - bytes name; name.set(T_NEW(byte, add_size(len, 1)), len); - name.strcat(prefix).strcat(suffix); - ref = cp.ensureUtf8(name); - } - putref(ref); - break; - - case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod): - aname = cp.sym[cpool::s_EnclosingMethod]; - putref(class_EnclosingMethod_RC.getRefN()); - CHECK_0; - putref(class_EnclosingMethod_RDN.getRefN()); - break; - - case ADH_BYTE(ATTR_CONTEXT_FIELD, FIELD_ATTR_ConstantValue): - aname = cp.sym[cpool::s_ConstantValue]; - putref(field_ConstantValue_KQ.getRefUsing(cp.getKQIndex())); - break; - - case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Code): - aname = cp.sym[cpool::s_Code]; - write_code(); - break; - - case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Exceptions): - aname = cp.sym[cpool::s_Exceptions]; - putu2(count = method_Exceptions_N.getInt()); - for (j = 0; j < count; j++) { - putref(method_Exceptions_RC.getRefN()); - CHECK_0; - } - break; - - case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_MethodParameters): - aname = cp.sym[cpool::s_MethodParameters]; - putu1(count = method_MethodParameters_NB.getByte()); - for (j = 0; j < count; j++) { - putref(method_MethodParameters_name_RUN.getRefN()); - putu2(method_MethodParameters_flag_FH.getInt()); - } - break; - - case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_StackMapTable): - aname = cp.sym[cpool::s_StackMapTable]; - // (keep this code aligned with its brother in unpacker::read_attrs) - putu2(count = code_StackMapTable_N.getInt()); - for (j = 0; j < count; j++) { - int tag = code_StackMapTable_frame_T.getByte(); - putu1(tag); - if (tag <= 127) { - // (64-127) [(2)] - if (tag >= 64) put_stackmap_type(); - CHECK_0; - } else if (tag <= 251) { - // (247) [(1)(2)] - // (248-251) [(1)] - if (tag >= 247) putu2(code_StackMapTable_offset.getInt()); - if (tag == 247) put_stackmap_type(); - CHECK_0; - } else if (tag <= 254) { - // (252) [(1)(2)] - // (253) [(1)(2)(2)] - // (254) [(1)(2)(2)(2)] - putu2(code_StackMapTable_offset.getInt()); - CHECK_0; - for (int k = (tag - 251); k > 0; k--) { - put_stackmap_type(); - CHECK_0; - } - } else { - // (255) [(1)NH[(2)]NH[(2)]] - putu2(code_StackMapTable_offset.getInt()); - putu2(j2 = code_StackMapTable_local_N.getInt()); - while (j2-- > 0) {put_stackmap_type(); CHECK_0;} - putu2(j2 = code_StackMapTable_stack_N.getInt()); - while (j2-- > 0) {put_stackmap_type(); CHECK_0;} - } - } - break; - - case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LineNumberTable): - aname = cp.sym[cpool::s_LineNumberTable]; - putu2(count = code_LineNumberTable_N.getInt()); - for (j = 0; j < count; j++) { - putu2(to_bci(code_LineNumberTable_bci_P.getInt())); - CHECK_0; - putu2(code_LineNumberTable_line.getInt()); - } - break; - - case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTable): - aname = cp.sym[cpool::s_LocalVariableTable]; - putu2(count = code_LocalVariableTable_N.getInt()); - for (j = 0; j < count; j++) { - int bii = code_LocalVariableTable_bci_P.getInt(); - int bci = to_bci(bii); - CHECK_0; - putu2(bci); - bii += code_LocalVariableTable_span_O.getInt(); - putu2(to_bci(bii) - bci); - CHECK_0; - putref(code_LocalVariableTable_name_RU.getRefN()); - CHECK_0; - putref(code_LocalVariableTable_type_RS.getRefN()); - CHECK_0; - putu2(code_LocalVariableTable_slot.getInt()); - } - break; - - case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTypeTable): - aname = cp.sym[cpool::s_LocalVariableTypeTable]; - putu2(count = code_LocalVariableTypeTable_N.getInt()); - for (j = 0; j < count; j++) { - int bii = code_LocalVariableTypeTable_bci_P.getInt(); - int bci = to_bci(bii); - CHECK_0; - putu2(bci); - bii += code_LocalVariableTypeTable_span_O.getInt(); - putu2(to_bci(bii) - bci); - CHECK_0; - putref(code_LocalVariableTypeTable_name_RU.getRefN()); - CHECK_0; - putref(code_LocalVariableTypeTable_type_RS.getRefN()); - CHECK_0; - putu2(code_LocalVariableTypeTable_slot.getInt()); - } - break; - - case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Signature): - aname = cp.sym[cpool::s_Signature]; - putref(class_Signature_RS.getRefN()); - break; - - case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Signature): - aname = cp.sym[cpool::s_Signature]; - putref(field_Signature_RS.getRefN()); - break; - - case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Signature): - aname = cp.sym[cpool::s_Signature]; - putref(method_Signature_RS.getRefN()); - break; - - case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Deprecated): - case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Deprecated): - case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Deprecated): - aname = cp.sym[cpool::s_Deprecated]; - // no data - break; - } - } - CHECK_0; - if (aname == null) { - // Unparse a compressor-defined attribute. - layout_definition* lo = ad.getLayout(idx); - if (lo == null) { - abort("bad layout index"); - break; - } - assert((int)lo->idx == idx); - aname = lo->nameEntry; - if (aname == null) { - bytes nameb; nameb.set(lo->name); - aname = cp.ensureUtf8(nameb); - // Cache the name entry for next time. - lo->nameEntry = aname; - } - // Execute all the layout elements. - band** bands = lo->bands(); - if (lo->hasCallables()) { - band& cble = *bands[0]; - assert(cble.le_kind == EK_CBLE); - bands = cble.le_body; - } - putlayout(bands); - } - - if (aname == null) - abort("bad attribute index"); - CHECK_0; - - byte* wp1 = wp; - wp = wp_at(abase); - - // DTRT if this attr is on the strip-list. - // (Note that we emptied the data out of the band first.) - if (ad.strip_names.contains(aname)) { - continue; - } - - // patch the name and length - putref(aname); - putu4((int)(wp1 - (wp+4))); // put the attr size - wp = wp1; - na++; // count the attrs actually written - } - - if (na != na0) - // Refresh changed count. - putu2_at(wp_at(naOffset), na); - return na; -} - -void unpacker::write_members(int num, int attrc) { - CHECK; - attr_definitions& ad = attr_defs[attrc]; - band& member_flags_hi = ad.xxx_flags_hi(); - band& member_flags_lo = ad.xxx_flags_lo(); - band& member_descr = (&member_flags_hi)[e_field_descr-e_field_flags_hi]; - assert(endsWith(member_descr.name, "_descr")); - assert(endsWith(member_flags_lo.name, "_flags_lo")); - assert(endsWith(member_flags_lo.name, "_flags_lo")); - bool haveLongFlags = ad.haveLongFlags(); - - putu2(num); - julong indexMask = attr_defs[attrc].flagIndexMask(); - for (int i = 0; i < num; i++) { - julong mflags = member_flags_hi.getLong(member_flags_lo, haveLongFlags); - entry* mdescr = member_descr.getRef(); - cur_descr = mdescr; - putu2(cur_descr_flags = (ushort)(mflags & ~indexMask)); - CHECK; - putref(mdescr->descrName()); - putref(mdescr->descrType()); - write_attrs(attrc, (mflags & indexMask)); - CHECK; - } - cur_descr = null; -} - -extern "C" -int raw_address_cmp(const void* p1p, const void* p2p) { - void* p1 = *(void**) p1p; - void* p2 = *(void**) p2p; - return (p1 > p2)? 1: (p1 < p2)? -1: 0; -} - -/* - * writes the InnerClass attributes and returns the updated attribute - */ -int unpacker::write_ics(int naOffset, int na) { -#ifdef ASSERT - for (int i = 0; i < ic_count; i++) { - assert(!ics[i].requested); - } -#endif - // First, consult the global table and the local constant pool, - // and decide on the globally implied inner classes. - // (Note that we read the cpool's outputIndex fields, but we - // do not yet write them, since the local IC attribute might - // reverse a global decision to declare an IC.) - assert(requested_ics.length() == 0); // must start out empty - // Always include all members of the current class. - for (inner_class* child = cp.getFirstChildIC(cur_class); - child != null; - child = cp.getNextChildIC(child)) { - child->requested = true; - requested_ics.add(child); - } - // And, for each inner class mentioned in the constant pool, - // include it and all its outers. - int noes = cp.outputEntries.length(); - entry** oes = (entry**) cp.outputEntries.base(); - for (int i = 0; i < noes; i++) { - entry& e = *oes[i]; - if (e.tag != CONSTANT_Class) continue; // wrong sort - for (inner_class* ic = cp.getIC(&e); - ic != null; - ic = cp.getIC(ic->outer)) { - if (ic->requested) break; // already processed - ic->requested = true; - requested_ics.add(ic); - } - } - int local_ics = requested_ics.length(); - // Second, consult a local attribute (if any) and adjust the global set. - inner_class* extra_ics = null; - int num_extra_ics = 0; - if (cur_class_has_local_ics) { - // adjust the set of ICs by symmetric set difference w/ the locals - num_extra_ics = class_InnerClasses_N.getInt(); - if (num_extra_ics == 0) { - // Explicit zero count has an irregular meaning: It deletes the attr. - local_ics = 0; // (short-circuit all tests of requested bits) - } else { - extra_ics = T_NEW(inner_class, num_extra_ics); - // Note: extra_ics will be freed up by next call to get_next_file(). - } - } - for (int i = 0; i < num_extra_ics; i++) { - inner_class& extra_ic = extra_ics[i]; - extra_ic.inner = class_InnerClasses_RC.getRef(); - CHECK_0; - // Find the corresponding equivalent global IC: - inner_class* global_ic = cp.getIC(extra_ic.inner); - int flags = class_InnerClasses_F.getInt(); - if (flags == 0) { - // The extra IC is simply a copy of a global IC. - if (global_ic == null) { - abort("bad reference to inner class"); - break; - } - extra_ic = (*global_ic); // fill in rest of fields - } else { - flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero - extra_ic.flags = flags; - extra_ic.outer = class_InnerClasses_outer_RCN.getRefN(); - CHECK_0; - extra_ic.name = class_InnerClasses_name_RUN.getRefN(); - CHECK_0; - // Detect if this is an exact copy of the global tuple. - if (global_ic != null) { - if (global_ic->flags != extra_ic.flags || - global_ic->outer != extra_ic.outer || - global_ic->name != extra_ic.name) { - global_ic = null; // not really the same, so break the link - } - } - } - if (global_ic != null && global_ic->requested) { - // This local repetition reverses the globally implied request. - global_ic->requested = false; - extra_ic.requested = false; - local_ics -= 1; - } else { - // The global either does not exist, or is not yet requested. - extra_ic.requested = true; - local_ics += 1; - } - } - // Finally, if there are any that survived, put them into an attribute. - // (Note that a zero-count attribute is always deleted.) - // The putref calls below will tell the constant pool to add any - // necessary local CP references to support the InnerClasses attribute. - // This step must be the last round of additions to the local CP. - if (local_ics > 0) { - // append the new attribute: - putref(cp.sym[cpool::s_InnerClasses]); - putu4(2 + 2*4*local_ics); - putu2(local_ics); - PTRLIST_QSORT(requested_ics, raw_address_cmp); - int num_global_ics = requested_ics.length(); - for (int i = -num_global_ics; i < num_extra_ics; i++) { - inner_class* ic; - if (i < 0) - ic = (inner_class*) requested_ics.get(num_global_ics+i); - else - ic = &extra_ics[i]; - if (ic->requested) { - putref(ic->inner); - putref(ic->outer); - putref(ic->name); - putu2(ic->flags); - NOT_PRODUCT(local_ics--); - } - } - assert(local_ics == 0); // must balance - putu2_at(wp_at(naOffset), ++na); // increment class attr count - } - - // Tidy up global 'requested' bits: - for (int i = requested_ics.length(); --i >= 0; ) { - inner_class* ic = (inner_class*) requested_ics.get(i); - ic->requested = false; - } - requested_ics.empty(); - return na; -} - -/* - * Writes the BootstrapMethods attribute and returns the updated attribute count - */ -int unpacker::write_bsms(int naOffset, int na) { - cur_class_local_bsm_count = cp.requested_bsms.length(); - if (cur_class_local_bsm_count > 0) { - int noes = cp.outputEntries.length(); - entry** oes = (entry**) cp.outputEntries.base(); - PTRLIST_QSORT(cp.requested_bsms, outputEntry_cmp); - // append the BootstrapMethods attribute (after the InnerClasses attr): - putref(cp.sym[cpool::s_BootstrapMethods]); - // make a note of the offset, for lazy patching - int sizeOffset = (int)wpoffset(); - putu4(-99); // attr size will be patched - putu2(cur_class_local_bsm_count); - int written_bsms = 0; - for (int i = 0 ; i < cur_class_local_bsm_count ; i++) { - entry* e = (entry*)cp.requested_bsms.get(i); - assert(e->outputIndex != REQUESTED_NONE); - // output index is the index within the array - e->outputIndex = i; - putref(e->refs[0]); // bsm - putu2(e->nrefs-1); // number of args after bsm - for (int j = 1; j < e->nrefs; j++) { - putref(e->refs[j]); - } - written_bsms += 1; - } - assert(written_bsms == cur_class_local_bsm_count); // else insane - byte* sizewp = wp_at(sizeOffset); - putu4_at(sizewp, (int)(wp - (sizewp+4))); // size of code attr - putu2_at(wp_at(naOffset), ++na); // increment class attr count - } - return na; -} - -void unpacker::write_classfile_tail() { - - cur_classfile_tail.empty(); - set_output(&cur_classfile_tail); - - int i, num; - - attr_definitions& ad = attr_defs[ATTR_CONTEXT_CLASS]; - - bool haveLongFlags = ad.haveLongFlags(); - julong kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags); - julong indexMask = ad.flagIndexMask(); - - cur_class = class_this.getRef(); - CHECK; - cur_super = class_super.getRef(); - CHECK; - - if (cur_super == cur_class) cur_super = null; - // special representation for java/lang/Object - - putu2((ushort)(kflags & ~indexMask)); - putref(cur_class); - putref(cur_super); - - putu2(num = class_interface_count.getInt()); - for (i = 0; i < num; i++) { - putref(class_interface.getRef()); - CHECK; - } - - write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); - write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD); - CHECK; - - cur_class_has_local_ics = false; // may be set true by write_attrs - - int naOffset = (int)wpoffset(); // note the attr count location - int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask)); - CHECK; - - na = write_bsms(naOffset, na); - CHECK; - - // choose which inner classes (if any) pertain to k: - na = write_ics(naOffset, na); - CHECK; - - close_output(); - cp.computeOutputIndexes(); - - // rewrite CP references in the tail - int nextref = 0; - for (i = 0; i < (int)class_fixup_type.size(); i++) { - int type = class_fixup_type.getByte(i); - byte* fixp = wp_at(class_fixup_offset.get(i)); - entry* e = (entry*)class_fixup_ref.get(nextref++); - int idx = e->getOutputIndex(); - switch (type) { - case 1: putu1_at(fixp, idx); break; - case 2: putu2_at(fixp, idx); break; - default: assert(false); // should not reach here - } - } - CHECK; -} - -void unpacker::write_classfile_head() { - cur_classfile_head.empty(); - set_output(&cur_classfile_head); - - putu4(JAVA_MAGIC); - putu2(cur_class_minver); - putu2(cur_class_majver); - putu2(cp.outputIndexLimit); - - int checkIndex = 1; - int noes = cp.outputEntries.length(); - entry** oes = (entry**) cp.outputEntries.base(); - for (int i = 0; i < noes; i++) { - entry& e = *oes[i]; - assert(e.getOutputIndex() == checkIndex++); - byte tag = e.tag; - assert(tag != CONSTANT_Signature); - putu1(tag); - switch (tag) { - case CONSTANT_Utf8: - putu2((int)e.value.b.len); - put_bytes(e.value.b); - break; - case CONSTANT_Integer: - case CONSTANT_Float: - putu4(e.value.i); - break; - case CONSTANT_Long: - case CONSTANT_Double: - putu8(e.value.l); - assert(checkIndex++); - break; - case CONSTANT_Class: - case CONSTANT_String: - // just write the ref - putu2(e.refs[0]->getOutputIndex()); - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - case CONSTANT_NameandType: - case CONSTANT_InvokeDynamic: - putu2(e.refs[0]->getOutputIndex()); - putu2(e.refs[1]->getOutputIndex()); - break; - case CONSTANT_MethodHandle: - putu1(e.value.i); - putu2(e.refs[0]->getOutputIndex()); - break; - case CONSTANT_MethodType: - putu2(e.refs[0]->getOutputIndex()); - break; - case CONSTANT_BootstrapMethod: // should not happen - default: - abort(ERROR_INTERNAL); - } - } - -#ifndef PRODUCT - total_cp_size[0] += cp.outputIndexLimit; - total_cp_size[1] += (int)cur_classfile_head.size(); -#endif - close_output(); -} - -unpacker::file* unpacker::get_next_file() { - CHECK_0; - free_temps(); - if (files_remaining == 0) { - // Leave a clue that we're exhausted. - cur_file.name = null; - cur_file.size = null; - if (archive_size != 0) { - julong predicted_size = unsized_bytes_read + archive_size; - if (predicted_size != bytes_read) - abort("archive header had incorrect size"); - } - return null; - } - files_remaining -= 1; - assert(files_written < file_count || classes_written < class_count); - cur_file.name = ""; - cur_file.size = 0; - cur_file.modtime = default_file_modtime; - cur_file.options = default_file_options; - cur_file.data[0].set(null, 0); - cur_file.data[1].set(null, 0); - if (files_written < file_count) { - entry* e = file_name.getRef(); - CHECK_0; - cur_file.name = e->utf8String(); - CHECK_0; - bool haveLongSize = (testBit(archive_options, AO_HAVE_FILE_SIZE_HI)); - cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize); - if (testBit(archive_options, AO_HAVE_FILE_MODTIME)) - cur_file.modtime += file_modtime.getInt(); //relative to archive modtime - if (testBit(archive_options, AO_HAVE_FILE_OPTIONS)) - cur_file.options |= file_options.getInt() & ~suppress_file_options; - } else if (classes_written < class_count) { - // there is a class for a missing file record - cur_file.options |= FO_IS_CLASS_STUB; - } - if ((cur_file.options & FO_IS_CLASS_STUB) != 0) { - assert(classes_written < class_count); - classes_written += 1; - if (cur_file.size != 0) { - abort("class file size transmitted"); - return null; - } - reset_cur_classfile(); - - // write the meat of the classfile: - write_classfile_tail(); - cur_file.data[1] = cur_classfile_tail.b; - CHECK_0; - - // write the CP of the classfile, second: - write_classfile_head(); - cur_file.data[0] = cur_classfile_head.b; - CHECK_0; - - cur_file.size += cur_file.data[0].len; - cur_file.size += cur_file.data[1].len; - if (cur_file.name[0] == '\0') { - bytes& prefix = cur_class->ref(0)->value.b; - const char* suffix = ".class"; - int len = (int)(prefix.len + strlen(suffix)); - bytes name; name.set(T_NEW(byte, add_size(len, 1)), len); - cur_file.name = name.strcat(prefix).strcat(suffix).strval(); - } - } else { - // If there is buffered file data, produce a pointer to it. - if (cur_file.size != (size_t) cur_file.size) { - // Silly size specified. - abort("resource file too large"); - return null; - } - size_t rpleft = input_remaining(); - if (rpleft > 0) { - if (rpleft > cur_file.size) - rpleft = (size_t) cur_file.size; - cur_file.data[0].set(rp, rpleft); - rp += rpleft; - } - if (rpleft < cur_file.size) { - // Caller must read the rest. - size_t fleft = (size_t)cur_file.size - rpleft; - bytes_read += fleft; // Credit it to the overall archive size. - } - } - CHECK_0; - bytes_written += cur_file.size; - files_written += 1; - return &cur_file; -} - -// Write a file to jarout. -void unpacker::write_file_to_jar(unpacker::file* f) { - size_t htsize = f->data[0].len + f->data[1].len; - julong fsize = f->size; -#ifndef PRODUCT - if (nowrite NOT_PRODUCT(|| skipfiles-- > 0)) { - PRINTCR((2,"would write %d bytes to %s", (int) fsize, f->name)); - return; - } -#endif - if (htsize == fsize) { - jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, - f->data[0], f->data[1]); - } else { - assert(input_remaining() == 0); - bytes part1, part2; - part1.len = f->data[0].len; - part1.set(T_NEW(byte, part1.len), part1.len); - part1.copyFrom(f->data[0]); - assert(f->data[1].len == 0); - part2.set(null, 0); - size_t fleft = (size_t) fsize - part1.len; - assert(bytes_read > fleft); // part2 already credited by get_next_file - bytes_read -= fleft; - if (fleft > 0) { - // Must read some more. - if (live_input) { - // Stop using the input buffer. Make a new one: - if (free_input) input.free(); - input.init(fleft > (1<<12) ? fleft : (1<<12)); - free_input = true; - live_input = false; - } else { - // Make it large enough. - assert(free_input); // must be reallocable - input.ensureSize(fleft); - } - rplimit = rp = input.base(); - CHECK; - input.setLimit(rp + fleft); - if (!ensure_input(fleft)) - abort("EOF reading resource file"); - part2.ptr = input_scan(); - part2.len = input_remaining(); - rplimit = rp = input.base(); - } - jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, - part1, part2); - } - if (verbose >= 3) { - fprintf(errstrm, "Wrote " - LONG_LONG_FORMAT " bytes to: %s\n", fsize, f->name); - } -} - -// Redirect the stdio to the specified file in the unpack.log.file option -void unpacker::redirect_stdio() { - if (log_file == null) { - log_file = LOGFILE_STDOUT; - } - if (log_file == errstrm_name) - // Nothing more to be done. - return; - errstrm_name = log_file; - if (strcmp(log_file, LOGFILE_STDERR) == 0) { - errstrm = stderr; - return; - } else if (strcmp(log_file, LOGFILE_STDOUT) == 0) { - errstrm = stdout; - return; - } else if (log_file[0] != '\0' && (errstrm = fopen(log_file,"a+")) != NULL) { - return; - } else { - fprintf(stderr, "Can not open log file %s\n", log_file); - // Last resort - // (Do not use stdout, since it might be jarout->jarfp.) - errstrm = stderr; - log_file = errstrm_name = LOGFILE_STDERR; - } -} - -#ifndef PRODUCT -int unpacker::printcr_if_verbose(int level, const char* fmt ...) { - if (verbose < level) return 0; - va_list vl; - va_start(vl, fmt); - char fmtbuf[300]; - strcpy(fmtbuf+100, fmt); - strcat(fmtbuf+100, "\n"); - char* fmt2 = fmtbuf+100; - while (level-- > 0) *--fmt2 = ' '; - vfprintf(errstrm, fmt2, vl); - return 1; // for ?: usage -} -#endif - -void unpacker::abort(const char* message) { - if (message == null) message = "error unpacking archive"; -#ifdef UNPACK_JNI - if (message[0] == '@') { // secret convention for sprintf - bytes saved; - saved.saveFrom(message+1); - mallocs.add(message = saved.strval()); - } - abort_message = message; - return; -#else - if (message[0] == '@') ++message; - fprintf(errstrm, "%s\n", message); -#ifndef PRODUCT - fflush(errstrm); - ::abort(); -#else - exit(-1); -#endif -#endif // JNI -} diff --git a/src/jdk.pack/share/native/common-unpack/unpack.h b/src/jdk.pack/share/native/common-unpack/unpack.h deleted file mode 100644 index 0357ff457b1..00000000000 --- a/src/jdk.pack/share/native/common-unpack/unpack.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -// Global Structures -struct jar; -struct gunzip; -struct band; -struct cpool; -struct entry; -struct cpindex; -struct inner_class; -struct value_stream; - -struct cpindex { - uint len; - entry* base1; // base of primary index - entry** base2; // base of secondary index - byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index - enum { SUB_TAG = 64 }; - - entry* get(uint i); - - void init(int len_, entry* base1_, int ixTag_) { - len = len_; - base1 = base1_; - base2 = null; - ixTag = ixTag_; - } - void init(int len_, entry** base2_, int ixTag_) { - len = len_; - base1 = null; - base2 = base2_; - ixTag = ixTag_; - } -}; - -struct cpool { - uint nentries; - entry* entries; - entry* first_extra_entry; - uint maxentries; // total allocated size of entries - - // Position and size of each homogeneous subrange: - int tag_count[CONSTANT_Limit]; - int tag_base[CONSTANT_Limit]; - cpindex tag_index[CONSTANT_Limit]; - ptrlist tag_extras[CONSTANT_Limit]; - - int tag_group_count[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; - cpindex tag_group_index[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; - - cpindex* member_indexes; // indexed by 2*CONSTANT_Class.inord - cpindex* getFieldIndex(entry* classRef); - cpindex* getMethodIndex(entry* classRef); - - inner_class** ic_index; - inner_class** ic_child_index; - inner_class* getIC(entry* inner); - inner_class* getFirstChildIC(entry* outer); - inner_class* getNextChildIC(inner_class* child); - - int outputIndexLimit; // index limit after renumbering - ptrlist outputEntries; // list of entry* needing output idx assigned - ptrlist requested_bsms; // which bsms need output? - - entry** hashTab; - uint hashTabLength; - entry*& hashTabRef(byte tag, bytes& b); - entry* ensureUtf8(bytes& b); - entry* ensureClass(bytes& b); - - // Well-known Utf8 symbols. - enum { - #define SNAME(n,s) s_##s, - ALL_ATTR_DO(SNAME) - #undef SNAME - s_lt_init_gt, // - s_LIMIT - }; - entry* sym[s_LIMIT]; - - // read counts from hdr, allocate main arrays - void init(unpacker* u, int counts[CONSTANT_Limit]); - - // pointer to outer unpacker, for error checks etc. - unpacker* u; - - int getCount(byte tag) { - if ((uint)tag >= CONSTANT_GroupFirst) { - assert((uint)tag < CONSTANT_GroupLimit); - return tag_group_count[(uint)tag - CONSTANT_GroupFirst]; - } else { - assert((uint)tag < CONSTANT_Limit); - return tag_count[(uint)tag]; - } - } - cpindex* getIndex(byte tag) { - if ((uint)tag >= CONSTANT_GroupFirst) { - assert((uint)tag < CONSTANT_GroupLimit); - return &tag_group_index[(uint)tag - CONSTANT_GroupFirst]; - } else { - assert((uint)tag < CONSTANT_Limit); - return &tag_index[(uint)tag]; - } - } - - cpindex* getKQIndex(); // uses cur_descr - - void expandSignatures(); - void initGroupIndexes(); - void initMemberIndexes(); - int initLoadableValues(entry** loadable_entries); - - void computeOutputOrder(); - void computeOutputIndexes(); - void resetOutputIndexes(); - - // error handling - inline void abort(const char* msg); - inline bool aborting(); -}; - -/* - * The unpacker provides the entry points to the unpack engine, - * as well as maintains the state of the engine. - */ -struct unpacker { - // One element of the resulting JAR. - struct file { - const char* name; - julong size; - int modtime; - int options; - bytes data[2]; - // Note: If Sum(data[*].len) < size, - // remaining bytes must be read directly from the input stream. - bool deflate_hint() { return ((options & FO_DEFLATE_HINT) != 0); } - }; - - // back pointer to NativeUnpacker obj and Java environment - void* jniobj; - void* jnienv; - - // global pointer to self, if not running under JNI (not multi-thread safe) - static unpacker* non_mt_current; - - // if running Unix-style, here are the inputs and outputs - FILE* infileptr; // buffered - int infileno; // unbuffered - bytes inbytes; // direct - gunzip* gzin; // gunzip filter, if any - jar* jarout; // output JAR file - -#ifndef PRODUCT - int nowrite; - int skipfiles; - int verbose_bands; -#endif - - // pointer to self, for U_NEW macro - unpacker* u; - - // private abort message string, allocated to PATH_MAX*2 - const char* abort_message; - ptrlist mallocs; // list of guys to free when we are all done - ptrlist tmallocs; // list of guys to free on next client request - fillbytes smallbuf; // supplies small alloc requests - fillbytes tsmallbuf; // supplies temporary small alloc requests - - // option management members - int verbose; // verbose level, 0 means no output - bool strip_compile; - bool strip_debug; - bool strip_jcov; - bool remove_packfile; - int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1 - int modification_time_or_zero; - - FILE* errstrm; - const char* errstrm_name; - - const char* log_file; - - // input stream - fillbytes input; // the whole block (size is predicted, has slop too) - bool live_input; // is the data in this block live? - bool free_input; // must the input buffer be freed? - byte* rp; // read pointer (< rplimit <= input.limit()) - byte* rplimit; // how much of the input block has been read? - julong bytes_read; - size_t unsized_bytes_read; - - // callback to read at least one byte, up to available input - typedef jlong (*read_input_fn_t)(unpacker* self, void* buf, jlong minlen, jlong maxlen); - read_input_fn_t read_input_fn; - - // archive header fields - int magic, minver, majver; - size_t archive_size; - int archive_next_count, archive_options, archive_modtime; - int band_headers_size; - int file_count, attr_definition_count, ic_count, class_count; - int default_class_minver, default_class_majver; - int default_file_options, suppress_file_options; // not header fields - int default_archive_modtime, default_file_modtime; // not header fields - int code_count; // not a header field - int files_remaining; // not a header field - - // engine state - band* all_bands; // indexed by band_number - byte* meta_rp; // read-pointer into (copy of) band_headers - cpool cp; // all constant pool information - inner_class* ics; // InnerClasses - - // output stream - bytes output; // output block (either classfile head or tail) - byte* wp; // write pointer (< wplimit == output.limit()) - byte* wpbase; // write pointer starting address (<= wp) - byte* wplimit; // how much of the output block has been written? - - // output state - file cur_file; - entry* cur_class; // CONSTANT_Class entry - entry* cur_super; // CONSTANT_Class entry or null - entry* cur_descr; // CONSTANT_NameandType entry - int cur_descr_flags; // flags corresponding to cur_descr - int cur_class_minver, cur_class_majver; - bool cur_class_has_local_ics; - int cur_class_local_bsm_count; - fillbytes cur_classfile_head; - fillbytes cur_classfile_tail; - int files_written; // also tells which file we're working on - int classes_written; // also tells which class we're working on - julong bytes_written; - intlist bcimap; - fillbytes class_fixup_type; - intlist class_fixup_offset; - ptrlist class_fixup_ref; - fillbytes code_fixup_type; // which format of branch operand? - intlist code_fixup_offset; // location of operand needing fixup - intlist code_fixup_source; // encoded ID of branch insn - ptrlist requested_ics; // which ics need output? - - // stats pertaining to multiple segments (updated on reset) - julong bytes_read_before_reset; - julong bytes_written_before_reset; - int files_written_before_reset; - int classes_written_before_reset; - int segments_read_before_reset; - - // attribute state - struct layout_definition { - uint idx; // index (0..31...) which identifies this layout - const char* name; // name of layout - entry* nameEntry; - const char* layout; // string of layout (not yet parsed) - band** elems; // array of top-level layout elems (or callables) - - bool hasCallables() { return layout[0] == '['; } - band** bands() { assert(elems != null); return elems; } - }; - struct attr_definitions { - unpacker* u; // pointer to self, for U_NEW macro - int xxx_flags_hi_bn;// locator for flags, count, indexes, calls bands - int attrc; // ATTR_CONTEXT_CLASS, etc. - uint flag_limit; // 32 or 63, depending on archive_options bit - julong predef; // mask of built-in definitions - julong redef; // mask of local flag definitions or redefinitions - ptrlist layouts; // local (compressor-defined) defs, in index order - int flag_count[X_ATTR_LIMIT_FLAGS_HI]; - intlist overflow_count; - ptrlist strip_names; // what attribute names are being stripped? - ptrlist band_stack; // Temp., used during layout parsing. - ptrlist calls_to_link; // (ditto) - int bands_made; // (ditto) - - void free() { - layouts.free(); - overflow_count.free(); - strip_names.free(); - band_stack.free(); - calls_to_link.free(); - } - - // Locate the five fixed bands. - band& xxx_flags_hi(); - band& xxx_flags_lo(); - band& xxx_attr_count(); - band& xxx_attr_indexes(); - band& xxx_attr_calls(); - band& fixed_band(int e_class_xxx); - - // Register a new layout, and make bands for it. - layout_definition* defineLayout(int idx, const char* name, const char* layout); - layout_definition* defineLayout(int idx, entry* nameEntry, const char* layout); - band** buildBands(layout_definition* lo); - - // Parse a layout string or part of one, recursively if necessary. - const char* parseLayout(const char* lp, band** &res, int curCble); - const char* parseNumeral(const char* lp, int &res); - const char* parseIntLayout(const char* lp, band* &res, byte le_kind, - bool can_be_signed = false); - band** popBody(int band_stack_base); // pops a body off band_stack - - // Read data into the bands of the idx-th layout. - void readBandData(int idx); // parse layout, make bands, read data - void readBandData(band** body, uint count); // recursive helper - - layout_definition* getLayout(uint idx) { - if (idx >= (uint)layouts.length()) return null; - return (layout_definition*) layouts.get(idx); - } - - void setHaveLongFlags(bool z) { - assert(flag_limit == 0); // not set up yet - flag_limit = (z? X_ATTR_LIMIT_FLAGS_HI: X_ATTR_LIMIT_NO_FLAGS_HI); - } - bool haveLongFlags() { - assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI || - flag_limit == X_ATTR_LIMIT_FLAGS_HI); - return flag_limit == X_ATTR_LIMIT_FLAGS_HI; - } - - // Return flag_count if idx is predef and not redef, else zero. - int predefCount(uint idx); - - bool isRedefined(uint idx) { - if (idx >= flag_limit) return false; - return (bool)((redef >> idx) & 1); - } - bool isPredefined(uint idx) { - if (idx >= flag_limit) return false; - return (bool)(((predef & ~redef) >> idx) & 1); - } - julong flagIndexMask() { - return (predef | redef); - } - bool isIndex(uint idx) { - assert(flag_limit != 0); // must be set up already - if (idx < flag_limit) - return (bool)(((predef | redef) >> idx) & 1); - else - return (idx - flag_limit < (uint)overflow_count.length()); - } - int& getCount(uint idx) { - assert(isIndex(idx)); - if (idx < flag_limit) - return flag_count[idx]; - else - return overflow_count.get(idx - flag_limit); - } - bool aborting() { return u->aborting(); } - void abort(const char* msg) { u->abort(msg); } - }; - - attr_definitions attr_defs[ATTR_CONTEXT_LIMIT]; - - // Initialization - void init(read_input_fn_t input_fn = null); - // Resets to a known sane state - void reset(); - // Deallocates all storage. - void free(); - // Deallocates temporary storage (volatile after next client call). - void free_temps() { tsmallbuf.init(); tmallocs.freeAll(); } - - // Option management methods - bool set_option(const char* option, const char* value); - const char* get_option(const char* option); - - void dump_options(); - - // Fetching input. - bool ensure_input(jlong more); - byte* input_scan() { return rp; } - size_t input_remaining() { return rplimit - rp; } - size_t input_consumed() { return rp - input.base(); } - - // Entry points to the unpack engine - static int run(int argc, char **argv); // Unix-style entry point. - void check_options(); - void start(void* packptr = null, size_t len = 0); - void redirect_stdio(); - void write_file_to_jar(file* f); - void finish(); - - // Public post unpack methods - int get_files_remaining() { return files_remaining; } - int get_segments_remaining() { return archive_next_count; } - file* get_next_file(); // returns null on last file - - // General purpose methods - void* alloc(size_t size) { return alloc_heap(size, true); } - void* temp_alloc(size_t size) { return alloc_heap(size, true, true); } - void* alloc_heap(size_t size, bool smallOK = false, bool temp = false); - void saveTo(bytes& b, const char* str) { saveTo(b, (byte*)str, strlen(str)); } - void saveTo(bytes& b, bytes& data) { saveTo(b, data.ptr, data.len); } - void saveTo(bytes& b, byte* ptr, size_t len); //{ b.ptr = U_NEW...} - const char* saveStr(const char* str) { bytes buf; saveTo(buf, str); return buf.strval(); } - const char* saveIntStr(int num) { char buf[30]; sprintf(buf, "%d", num); return saveStr(buf); } -#ifndef PRODUCT - int printcr_if_verbose(int level, const char* fmt,...); -#endif - const char* get_abort_message(); - void abort(const char* s = null); - bool aborting() { return abort_message != null; } - static unpacker* current(); // find current instance - void checkLegacy(const char* name); - // Output management - void set_output(fillbytes* which) { - assert(wp == null); - which->ensureSize(1 << 12); // covers the average classfile - wpbase = which->base(); - wp = which->limit(); - wplimit = which->end(); - } - fillbytes* close_output(fillbytes* which = null); // inverse of set_output - - // These take an implicit parameter of wp/wplimit, and resize as necessary: - byte* put_space(size_t len); // allocates space at wp, returns pointer - size_t put_empty(size_t s) { byte* p = put_space(s); return p - wpbase; } - void ensure_put_space(size_t len); - void put_bytes(bytes& b) { b.writeTo(put_space(b.len)); } - void putu1(int n) { putu1_at(put_space(1), n); } - void putu1_fast(int n) { putu1_at(wp++, n); } - void putu2(int n); // { putu2_at(put_space(2), n); } - void putu4(int n); // { putu4_at(put_space(4), n); } - void putu8(jlong n); // { putu8_at(put_space(8), n); } - void putref(entry* e); // { putu2_at(put_space(2), putref_index(e, 2)); } - void putu1ref(entry* e); // { putu1_at(put_space(1), putref_index(e, 1)); } - int putref_index(entry* e, int size); // size in [1..2] - void put_label(int curIP, int size); // size in {2,4} - void putlayout(band** body); - void put_stackmap_type(); - - size_t wpoffset() { return (size_t)(wp - wpbase); } // (unvariant across overflow) - byte* wp_at(size_t offset) { return wpbase + offset; } - uint to_bci(uint bii); - void get_code_header(int& max_stack, - int& max_na_locals, - int& handler_count, - int& cflags); - band* ref_band_for_self_op(int bc, bool& isAloadVar, int& origBCVar); - band* ref_band_for_op(int bc); - - // Definitions of standard classfile int formats: - static void putu1_at(byte* wp, int n) { assert(n == (n & 0xFF)); wp[0] = n; } - static void putu2_at(byte* wp, int n); - static void putu4_at(byte* wp, int n); - static void putu8_at(byte* wp, jlong n); - - // Private stuff - void reset_cur_classfile(); - void write_classfile_tail(); - void write_classfile_head(); - void write_code(); - void write_bc_ops(); - void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD - int write_attrs(int attrc, julong indexBits); - int write_ics(int naOffset, int na); - int write_bsms(int naOffset, int na); - - // The readers - void read_bands(); - void read_file_header(); - void read_cp(); - void read_cp_counts(value_stream& hdr); - void read_attr_defs(); - void read_ics(); - void read_attrs(int attrc, int obj_count); - void read_classes(); - void read_code_headers(); - void read_bcs(); - void read_bc_ops(); - void read_files(); - void read_Utf8_values(entry* cpMap, int len); - void read_single_words(band& cp_band, entry* cpMap, int len); - void read_double_words(band& cp_bands, entry* cpMap, int len); - void read_single_refs(band& cp_band, byte refTag, entry* cpMap, int len); - void read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry* cpMap, int len); - void read_signature_values(entry* cpMap, int len); - void read_method_handle(entry* cpMap, int len); - void read_method_type(entry* cpMap, int len); - void read_bootstrap_methods(entry* cpMap, int len); -}; - -inline void cpool::abort(const char* msg) { u->abort(msg); } -inline bool cpool::aborting() { return u->aborting(); } diff --git a/src/jdk.pack/share/native/common-unpack/utils.cpp b/src/jdk.pack/share/native/common-unpack/utils.cpp deleted file mode 100644 index a14126c1952..00000000000 --- a/src/jdk.pack/share/native/common-unpack/utils.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include -#include -#include -#include - -#include - -#ifdef _MSC_VER -#include -#include -#include -#else -#include -#endif - -#include "constants.h" -#include "defines.h" -#include "bytes.h" -#include "utils.h" - -#include "unpack.h" - -void* must_malloc(size_t size) { - size_t msize = size; - #ifdef USE_MTRACE - if (msize >= 0 && msize < sizeof(int)) - msize = sizeof(int); // see 0xbaadf00d below - #endif - void* ptr = (msize > PSIZE_MAX || msize <= 0) ? null : malloc(msize); - if (ptr != null) { - memset(ptr, 0, size); - } else { - unpack_abort(ERROR_ENOMEM); - } - mtrace('m', ptr, size); - return ptr; -} - -void mkdirs(int oklen, char* path) { - - if (strlen(path) <= (size_t)oklen) return; - char dir[PATH_MAX]; - - strcpy(dir, path); - char* slash = strrchr(dir, '/'); - if (slash == 0) return; - *slash = 0; - mkdirs(oklen, dir); - MKDIR(dir); -} - - -#ifndef PRODUCT -#ifndef STATIC_BUILD -// use the definition in libjvm when building statically -void breakpoint() { } // hook for debugger -int assert_failed(const char* p) { - char message[1<<12]; - sprintf(message, "@assert failed: %s\n", p); - fprintf(stdout, "%s", 1+message); - breakpoint(); - unpack_abort(message); - return 0; -} -#endif -#endif - -void unpack_abort(const char* msg, unpacker* u) { - if (msg == null) msg = "corrupt pack file or internal error"; - if (u == null) - u = unpacker::current(); - if (u == null) { - fprintf(stderr, "Error: unpacker: %s\n", msg); - ::abort(); - return; - } - u->abort(msg); -} - -bool unpack_aborting(unpacker* u) { - if (u == null) - u = unpacker::current(); - if (u == null) { - fprintf(stderr, "Error: unpacker: no current instance\n"); - ::abort(); - return true; - } - return u->aborting(); -} - -#ifdef USE_MTRACE -// Use this occasionally for detecting storage leaks in unpack. -void mtrace(char c, void* ptr, size_t size) { - if (c == 'f') *(int*)ptr = 0xbaadf00d; - static FILE* mtfp; - if (mtfp == (FILE*)-1) return; - if (mtfp == null) { - if (getenv("USE_MTRACE") == null) { - mtfp = (FILE*)-1; - return; - } - char fname[1024]; - sprintf(fname, "mtr%d.txt", getpid()); - mtfp = fopen(fname, "w"); - if (mtfp == null) - mtfp = stdout; - } - fprintf(mtfp, "%c %p %p\n", c, ptr, (void*)size); -} - -/* # Script for processing memory traces. - # It should report only a limited number (2) of "suspended" blocks, - # even if a large number of archive segments are processed. - # It should report no "leaked" blocks at all. - nawk < mtr*.txt ' - function checkleaks(what) { - nd = 0 - for (ptr in allocated) { - if (allocated[ptr] == 1) { - print NR ": " what " " ptr - #allocated[ptr] = 0 # stop the dangle - nd++ - } - } - if (nd > 0) print NR ": count " what " " nd - } - - /^[mfr]/ { - ptr = $2 - a1 = ($1 == "m")? 1: 0 - a0 = 0+allocated[ptr] - allocated[ptr] = a1 - if (a0 + a1 != 1) { - if (a0 == 0 && a1 == 0) - print NR ": double free " ptr - else if (a0 == 1 && a1 == 1) - print NR ": double malloc " ptr - else - print NR ": oddity " $0 - } - next - } - - /^s/ { - checkleaks("suspended") - next - } - - { - print NR ": unrecognized " $0 - } - END { - checkleaks("leaked") - } -' -*/ -#endif // USE_MTRACE diff --git a/src/jdk.pack/share/native/common-unpack/utils.h b/src/jdk.pack/share/native/common-unpack/utils.h deleted file mode 100644 index 5cd11edd7e9..00000000000 --- a/src/jdk.pack/share/native/common-unpack/utils.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -//Definitions of our util functions - -void* must_malloc(size_t size); -#ifndef USE_MTRACE -#define mtrace(c, ptr, size) -#else -void mtrace(char c, void* ptr, size_t size); -#endif - -// overflow management -#define POVERFLOW ((uint)-1) -#define PSIZE_MAX (POVERFLOW/2) /* normal size limit */ - -inline size_t scale_size(size_t size, size_t scale) { - return (size > PSIZE_MAX / scale) ? POVERFLOW : size * scale; -} - -inline size_t add_size(size_t size1, size_t size2) { - return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) - ? POVERFLOW - : size1 + size2; -} - -inline size_t add_size(size_t size1, size_t size2, int size3) { - return add_size(add_size(size1, size2), size3); -} - -// These may be expensive, because they have to go via Java TSD, -// if the optional u argument is missing. -struct unpacker; -extern void unpack_abort(const char* msg, unpacker* u = null); -extern bool unpack_aborting(unpacker* u = null); - -#ifndef PRODUCT -inline bool endsWith(const char* str, const char* suf) { - size_t len1 = strlen(str); - size_t len2 = strlen(suf); - return (len1 > len2 && 0 == strcmp(str + (len1-len2), suf)); -} -#endif - -void mkdirs(int oklen, char* path); diff --git a/src/jdk.pack/share/native/common-unpack/zip.cpp b/src/jdk.pack/share/native/common-unpack/zip.cpp deleted file mode 100644 index 08f4577870a..00000000000 --- a/src/jdk.pack/share/native/common-unpack/zip.cpp +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * Note: Lifted from uncrunch.c from jdk sources - */ -#include -#include -#include -#include - -#include - -#ifndef _MSC_VER -#include -#endif - -#include "defines.h" -#include "bytes.h" -#include "utils.h" - -#include "constants.h" -#include "unpack.h" - -#include "zip.h" - -#ifdef NO_ZLIB - -inline bool jar::deflate_bytes(bytes& head, bytes& tail) { - return false; -} -inline uint jar::get_crc32(uint c, uchar *ptr, uint len) { return 0; } -#define Z_NULL NULL - -#else // Have ZLIB - -#include - -inline uint jar::get_crc32(uint c, uchar *ptr, uint len) { return crc32(c, ptr, len); } - -#endif // End of ZLIB - -#ifdef _BIG_ENDIAN -#define SWAP_BYTES(a) \ - ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00) -#else -#define SWAP_BYTES(a) (a) -#endif - -#define GET_INT_LO(a) \ - SWAP_BYTES(a & 0xFFFF) - -#define GET_INT_HI(a) \ - SWAP_BYTES((a >> 16) & 0xFFFF) - -static const ushort jarmagic[2] = { SWAP_BYTES(0xCAFE), 0 }; - -void jar::init(unpacker* u_) { - BYTES_OF(*this).clear(); - u = u_; - u->jarout = this; -} - -// Write data to the ZIP output stream. -void jar::write_data(void* buff, size_t len) { - while (len > 0) { - int rc = (int)fwrite(buff, 1, len, jarfp); - if (rc <= 0) { - fprintf(u->errstrm, "Error: write on output file failed err=%d\n",errno); - exit(1); // Called only from the native standalone unpacker - } - output_file_offset += rc; - buff = ((char *)buff) + rc; - len -= rc; - } -} - -void jar::add_to_jar_directory(const char* fname, bool store, int modtime, - int len, int clen, uLong crc) { - uint fname_length = (uint)strlen(fname); - ushort header[23]; - if (modtime == 0) modtime = default_modtime; - uLong dostime = get_dostime(modtime); - - header[0] = (ushort)SWAP_BYTES(0x4B50); - header[1] = (ushort)SWAP_BYTES(0x0201); - header[2] = (ushort)SWAP_BYTES(( store ) ? 0x0A : 0x14); - - // required version - header[3] = (ushort)SWAP_BYTES(( store ) ? 0x0A : 0x14); - - // Flags - UTF-8 compression and separating crc and sizes - // into separate headers for deflated file - header[4] = ( store ) ? SWAP_BYTES(0x0800) : 0x0808; - - // Compression method 8=deflate. - header[5] = ( store ) ? 0x0 : SWAP_BYTES(0x08); - - // Last modified date and time. - header[6] = (ushort)GET_INT_LO(dostime); - header[7] = (ushort)GET_INT_HI(dostime); - - // CRC - header[8] = (ushort)GET_INT_LO(crc); - header[9] = (ushort)GET_INT_HI(crc); - - // Compressed length: - header[10] = (ushort)GET_INT_LO(clen); - header[11] = (ushort)GET_INT_HI(clen); - - // Uncompressed length. - header[12] = (ushort)GET_INT_LO(len); - header[13] = (ushort)GET_INT_HI(len); - - // Filename length - header[14] = (ushort)SWAP_BYTES(fname_length); - // So called "extra field" length. - // If it's the first record we must add JAR magic sequence - header[15] = ( central_directory_count ) ? 0 : (ushort)SWAP_BYTES(4); - // So called "comment" length. - header[16] = 0; - // Disk number start - header[17] = 0; - // File flags => binary - header[18] = 0; - // More file flags - header[19] = 0; - header[20] = 0; - // Offset within ZIP file. - header[21] = (ushort)GET_INT_LO(output_file_offset); - header[22] = (ushort)GET_INT_HI(output_file_offset); - - // Copy the whole thing into the central directory. - central_directory.append(header, sizeof(header)); - - // Copy the fname to the header. - central_directory.append(fname, fname_length); - - // Add jar magic for the first record - if (central_directory_count == 0) { - central_directory.append((void *)jarmagic, sizeof(jarmagic)); - } - - central_directory_count++; -} - -void jar::write_jar_header(const char* fname, bool store, int modtime, - int len, int clen, uint crc) { - uint fname_length = (uint)strlen(fname); - ushort header[15]; - if (modtime == 0) modtime = default_modtime; - uLong dostime = get_dostime(modtime); - - // ZIP LOC magic. - header[0] = (ushort)SWAP_BYTES(0x4B50); - header[1] = (ushort)SWAP_BYTES(0x0403); - - // Version - header[2] = (ushort)SWAP_BYTES(( store ) ? 0x0A : 0x14); - - // General purpose flags - same as in the Central Directory - header[3] = ( store ) ? SWAP_BYTES(0x0800) : 0x0808; - - // Compression method = deflate - header[4] = ( store ) ? 0x0 : SWAP_BYTES(0x08); - - // Last modified date and time. - header[5] = (ushort)GET_INT_LO(dostime); - header[6] = (ushort)GET_INT_HI(dostime); - - // CRC, 0 if deflated, will come separately in extra header - header[7] = ( store ) ? (ushort)GET_INT_LO(crc) : 0; - header[8] = ( store ) ? (ushort)GET_INT_HI(crc) : 0; - - // Compressed length, 0 if deflated - header[9] = ( store ) ? (ushort)GET_INT_LO(clen) : 0; - header[10] = ( store ) ? (ushort)GET_INT_HI(clen) : 0; - - // Uncompressed length, 0 if deflated - header[11] = ( store ) ? (ushort)GET_INT_LO(len) : 0; - header[12] = ( store ) ? (ushort)GET_INT_HI(len) : 0; - - // Filename length - header[13] = (ushort)SWAP_BYTES(fname_length); - // So called "extra field" length. - header[14] = ( central_directory_count - 1 ) ? 0 : (ushort)SWAP_BYTES(4); - - // Write the LOC header to the output file. - write_data(header, (int)sizeof(header)); - - // Copy the fname to the header. - write_data((char*)fname, (int)fname_length); - - if (central_directory_count == 1) { - // Write JAR magic sequence - write_data((void *)jarmagic, (int)sizeof(jarmagic)); - } -} - -void jar::write_jar_extra(int len, int clen, uint crc) { - ushort header[8]; - // Extra field signature - header[0] = (ushort)SWAP_BYTES(0x4B50); - header[1] = (ushort)SWAP_BYTES(0x0807); - // CRC - header[2] = (ushort)GET_INT_LO(crc); - header[3] = (ushort)GET_INT_HI(crc); - // Compressed length - header[4] = (ushort)GET_INT_LO(clen); - header[5] = (ushort)GET_INT_HI(clen); - // Uncompressed length - header[6] = (ushort)GET_INT_LO(len); - header[7] = (ushort)GET_INT_HI(len); - - write_data(header, sizeof(header)); -} - -static const char marker_comment[] = ZIP_ARCHIVE_MARKER_COMMENT; - -void jar::write_central_directory() { - bytes mc; mc.set(marker_comment); - - ushort header[11]; - ushort header64[38]; - - // Create the End of Central Directory structure. - header[0] = (ushort)SWAP_BYTES(0x4B50); - header[1] = (ushort)SWAP_BYTES(0x0605); - // disk numbers - header[2] = 0; - header[3] = 0; - // Number of entries in central directory. - header[4] = ( central_directory_count >= 0xffff ) ? 0xffff : (ushort)SWAP_BYTES(central_directory_count); - header[5] = ( central_directory_count >= 0xffff ) ? 0xffff : (ushort)SWAP_BYTES(central_directory_count); - // Size of the central directory} - header[6] = (ushort)GET_INT_LO((int)central_directory.size()); - header[7] = (ushort)GET_INT_HI((int)central_directory.size()); - // Offset of central directory within disk. - header[8] = (ushort)GET_INT_LO(output_file_offset); - header[9] = (ushort)GET_INT_HI(output_file_offset); - // zipfile comment length; - header[10] = (ushort)SWAP_BYTES((int)mc.len); - - // Write the central directory. - PRINTCR((2, "Central directory at %d\n", output_file_offset)); - write_data(central_directory.b); - - // If number of records exceeds the 0xFFFF we need to prepend extended - // Zip64 End of Central Directory record and its locator to the old - // style ECD record - if (central_directory_count > 0xFFFF) { - // Zip64 END signature - header64[0] = (ushort)SWAP_BYTES(0x4B50); - header64[1] = (ushort)0x0606; - // Size of header (long) - header64[2] = (ushort)SWAP_BYTES(44);; - header64[3] = 0; - header64[4] = 0; - header64[5] = 0; - // Version produced and required (short) - header64[6] = (ushort)SWAP_BYTES(45); - header64[7] = (ushort)SWAP_BYTES(45); - // Current disk number (int) - header64[8] = 0; - header64[9] = 0; - // Central directory start disk (int) - header64[10] = 0; - header64[11] = 0; - // Count of records on disk (long) - header64[12] = (ushort)GET_INT_LO(central_directory_count); - header64[13] = (ushort)GET_INT_HI(central_directory_count); - header64[14] = 0; - header64[15] = 0; - // Count of records totally (long) - header64[16] = (ushort)GET_INT_LO(central_directory_count); - header64[17] = (ushort)GET_INT_HI(central_directory_count); - header64[18] = 0; - header64[19] = 0; - // Length of the central directory (long) - header64[20] = header[6]; - header64[21] = header[7]; - header64[22] = 0; - header64[23] = 0; - // Offset of central directory (long) - header64[24] = header[8]; - header64[25] = header[9]; - header64[26] = 0; - header64[27] = 0; - // Zip64 end of central directory locator - // Locator signature - header64[28] = (ushort)SWAP_BYTES(0x4B50); - header64[29] = (ushort)SWAP_BYTES(0x0706); - // Start disk number (int) - header64[30] = 0; - header64[31] = 0; - // Offset of zip64 END record (long) - header64[32] = (ushort)GET_INT_LO(output_file_offset); - header64[33] = (ushort)GET_INT_HI(output_file_offset); - header64[34] = 0; - header64[35] = 0; - // Total number of disks (int) - header64[36] = (ushort)SWAP_BYTES(1); - header64[37] = 0; - write_data(header64, sizeof(header64)); - } - - // Write the End of Central Directory structure. - PRINTCR((2, "end-of-directory at %d\n", output_file_offset)); - write_data(header, sizeof(header)); - - PRINTCR((2, "writing zip comment\n")); - // Write the comment. - write_data(mc); -} - -// Public API - -// Open a Jar file and initialize. -void jar::openJarFile(const char* fname) { - if (!jarfp) { - PRINTCR((1, "jar::openJarFile: opening %s\n",fname)); - jarname = fname; - jarfp = fopen(fname, "wb"); - if (!jarfp) { - fprintf(u->errstrm, "Error: Could not open jar file: %s\n",fname); - exit(3); // Called only from the native standalone unpacker - } - } -} - -// Add a ZIP entry and copy the file data -void jar::addJarEntry(const char* fname, - bool deflate_hint, int modtime, - bytes& head, bytes& tail) { - int len = (int)(head.len + tail.len); - int clen = 0; - - uint crc = get_crc32(0,Z_NULL,0); - if (head.len != 0) - crc = get_crc32(crc, (uchar *)head.ptr, (uint)head.len); - if (tail.len != 0) - crc = get_crc32(crc, (uchar *)tail.ptr, (uint)tail.len); - - bool deflate = (deflate_hint && len > 0); - - if (deflate) { - if (deflate_bytes(head, tail) == false) { - PRINTCR((2, "Reverting to store fn=%s\t%d -> %d\n", - fname, len, deflated.size())); - deflate = false; - } - } - clen = (int)((deflate) ? deflated.size() : len); - add_to_jar_directory(fname, !deflate, modtime, len, clen, crc); - write_jar_header( fname, !deflate, modtime, len, clen, crc); - - if (deflate) { - write_data(deflated.b); - // Write deflated information in extra header - write_jar_extra(len, clen, crc); - } else { - write_data(head); - write_data(tail); - } -} - -// Add a ZIP entry for a directory name no data -void jar::addDirectoryToJarFile(const char* dir_name) { - bool store = true; - add_to_jar_directory((const char*)dir_name, store, default_modtime, 0, 0, 0); - write_jar_header( (const char*)dir_name, store, default_modtime, 0, 0, 0); -} - -// Write out the central directory and close the jar file. -void jar::closeJarFile(bool central) { - if (jarfp) { - fflush(jarfp); - if (central) write_central_directory(); - fflush(jarfp); - fclose(jarfp); - PRINTCR((2, "jar::closeJarFile:closed jar-file\n")); - } - reset(); -} - -/* Convert the date y/n/d and time h:m:s to a four byte DOS date and - * time (date in high two bytes, time in low two bytes allowing magnitude - * comparison). - */ -inline -uLong jar::dostime(int y, int n, int d, int h, int m, int s) { - return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0) : - (((uLong)y - 1980) << 25) | ((uLong)n << 21) | ((uLong)d << 16) | - ((uLong)h << 11) | ((uLong)m << 5) | ((uLong)s >> 1); -} - -/* - * For thread-safe reasons, non-Windows platforms need gmtime_r - * while Windows can directly use gmtime that is already thread-safe. - */ -#ifdef _MSC_VER -#define gmtime_r(t, s) gmtime(t) -#endif -/* - * Return the Unix time in DOS format - */ -uLong jar::get_dostime(int modtime) { - // see defines.h - if (modtime != 0 && modtime == modtime_cache) - return dostime_cache; - if (modtime != 0 && default_modtime == 0) - default_modtime = modtime; // catch a reasonable default - time_t t = modtime; - struct tm sbuf; - (void)memset((void*)&sbuf,0, sizeof(sbuf)); - struct tm* s = gmtime_r(&t, &sbuf); - if (s == NULL) { - fprintf(u->errstrm, "Error: gmtime failure, invalid input archive\n"); - exit(-1); - } - modtime_cache = modtime; - dostime_cache = dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, - s->tm_hour, s->tm_min, s->tm_sec); - //printf("modtime %d => %d\n", modtime_cache, dostime_cache); - return dostime_cache; -} - - - -#ifndef NO_ZLIB - -/* Returns true on success, and will set the clen to the compressed - length, the caller should verify if true and clen less than the - input data -*/ -bool jar::deflate_bytes(bytes& head, bytes& tail) { - int len = (int)(head.len + tail.len); - - z_stream zs; - BYTES_OF(zs).clear(); - - // NOTE: the window size should always be -MAX_WBITS normally -15. - // unzip/zipup.c and java/Deflater.c - - int error = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); - if (error != Z_OK) { - switch (error) { - case Z_MEM_ERROR: - PRINTCR((2, "Error: deflate error : Out of memory \n")); - break; - case Z_STREAM_ERROR: - PRINTCR((2,"Error: deflate error : Invalid compression level \n")); - break; - case Z_VERSION_ERROR: - PRINTCR((2,"Error: deflate error : Invalid version\n")); - break; - default: - PRINTCR((2,"Error: Internal deflate error error = %d\n", error)); - } - return false; - } - - deflated.empty(); - zs.next_out = (uchar*) deflated.grow(add_size(len, (len/2))); - zs.avail_out = (int)deflated.size(); - - zs.next_in = (uchar*)head.ptr; - zs.avail_in = (int)head.len; - - bytes* first = &head; - bytes* last = &tail; - if (last->len == 0) { - first = null; - last = &head; - } else if (first->len == 0) { - first = null; - } - - if (first != null && error == Z_OK) { - zs.next_in = (uchar*) first->ptr; - zs.avail_in = (int)first->len; - error = deflate(&zs, Z_NO_FLUSH); - } - if (error == Z_OK) { - zs.next_in = (uchar*) last->ptr; - zs.avail_in = (int)last->len; - error = deflate(&zs, Z_FINISH); - } - if (error == Z_STREAM_END) { - if ((int)zs.total_out > 0) { - // Even if compressed size is bigger than uncompressed, write it - PRINTCR((2, "deflate compressed data %d -> %d\n", len, zs.total_out)); - deflated.b.len = zs.total_out; - deflateEnd(&zs); - return true; - } - PRINTCR((2, "deflate expanded data %d -> %d\n", len, zs.total_out)); - deflateEnd(&zs); - return false; - } - - deflateEnd(&zs); - PRINTCR((2, "Error: deflate error deflate did not finish error=%d\n",error)); - return false; -} - -// Callback for fetching data from a GZIP input stream -static jlong read_input_via_gzip(unpacker* u, - void* buf, jlong minlen, jlong maxlen) { - assert(minlen <= maxlen); // don't talk nonsense - jlong numread = 0; - char* bufptr = (char*) buf; - char* inbuf = u->gzin->inbuf; - size_t inbuflen = sizeof(u->gzin->inbuf); - unpacker::read_input_fn_t read_gzin_fn = - (unpacker::read_input_fn_t) u->gzin->read_input_fn; - z_stream& zs = *(z_stream*) u->gzin->zstream; - while (numread < minlen) { - int readlen = (1 << 16); // pretty arbitrary - if (readlen > (maxlen - numread)) - readlen = (int)(maxlen - numread); - zs.next_out = (uchar*) bufptr; - zs.avail_out = readlen; - if (zs.avail_in == 0) { - zs.avail_in = (int) read_gzin_fn(u, inbuf, 1, inbuflen); - zs.next_in = (uchar*) inbuf; - } - int error = inflate(&zs, Z_NO_FLUSH); - if (error != Z_OK && error != Z_STREAM_END) { - u->abort("error inflating input"); - break; - } - int nr = readlen - zs.avail_out; - u->gzin->gzlen += nr; - u->gzin->gzcrc = crc32(u->gzin->gzcrc, (const unsigned char *)bufptr, nr); - numread += nr; - bufptr += nr; - assert(numread <= maxlen); - if (error == Z_STREAM_END) { - enum { TRAILER_LEN = 8 }; - // skip 8-byte trailer - if (zs.avail_in >= TRAILER_LEN) { - zs.avail_in -= TRAILER_LEN; - } else { - // Bug: 5023768,we read past the TRAILER_LEN to see if there is - // any extraneous data, as we don't support concatenated .gz files. - int extra = (int) read_gzin_fn(u, inbuf, 1, inbuflen); - zs.avail_in += extra - TRAILER_LEN; - } - // %%% should check for concatenated *.gz files here - if (zs.avail_in > 0) - u->abort("garbage after end of deflated input stream"); - - // at this point we know there are no trailing bytes, - // we are safe to get the crc and len. - if (u->gzin->gzcrc != 0) { - // Read the CRC information from the gzip container - fseek(u->infileptr, -TRAILER_LEN, SEEK_END); - uint filecrc; - uint filelen; - if (fread(&filecrc, sizeof(filecrc), 1, u->infileptr) != 1) { - fprintf(u->errstrm, "Error:reading CRC information on input file failed err=%d\n",errno); - exit(1); - } - if (fread(&filelen, sizeof(filelen), 1, u->infileptr) != 1) { - fprintf(u->errstrm, "Error:reading file length on input file failed err=%d\n",errno); - exit(1); - } - filecrc = SWAP_INT(filecrc); - filelen = SWAP_INT(filelen); - if (u->gzin->gzcrc != filecrc || - // rfc1952; ISIZE is the input size modulo 2^32 - u->gzin->gzlen != (filelen & 0xffffffff)) { // CRC error - - PRINTCR((1, "crc: 0x%x 0x%x\n", u->gzin->gzcrc, filecrc)); - PRINTCR((1, "len: 0x%x 0x%x\n", u->gzin->gzlen, filelen)); - - if (u->jarout != null) { - // save the file name first, if any - const char* outfile = u->jarout->jarname; - u->jarout->closeJarFile(false); - if (outfile != null) { - remove(outfile); - } - } - // Print out the error and exit with return code != 0 - u->abort("CRC error, invalid compressed data."); - } - } - // pop this filter off: - u->gzin->free(); - break; - } - } - - //fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n", - // (int)minlen, (int)maxlen, (int)numread); - return numread; -} - -void gunzip::init(unpacker* u_) { - BYTES_OF(*this).clear(); - u = u_; - assert(u->gzin == null); // once only, please - read_input_fn = (void*)u->read_input_fn; - zstream = NEW(z_stream, 1); - u->gzin = this; - u->read_input_fn = read_input_via_gzip; - u->gzin->gzcrc = crc32(0, Z_NULL, 0); - u->gzin->gzlen = 0; -} - -void gunzip::start(int magic) { - assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC); - int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes - enum { - FHCRC = (1<<1), - FEXTRA = (1<<2), - FNAME = (1<<3), - FCOMMENT = (1<<4) - }; - char gz_mtime[4]; - char gz_xfl[1]; - char gz_os[1]; - char gz_extra_len[2]; - char gz_hcrc[2]; - char gz_ignore; - // do not save extra, name, comment - read_fixed_field(gz_mtime, sizeof(gz_mtime)); - read_fixed_field(gz_xfl, sizeof(gz_xfl)); - read_fixed_field(gz_os, sizeof(gz_os)); - if (gz_flg & FEXTRA) { - read_fixed_field(gz_extra_len, sizeof(gz_extra_len)); - int extra_len = gz_extra_len[0] & 0xFF; - extra_len += (gz_extra_len[1] & 0xFF) << 8; - for (; extra_len > 0; extra_len--) { - read_fixed_field(&gz_ignore, 1); - } - } - int null_terms = 0; - if (gz_flg & FNAME) null_terms++; - if (gz_flg & FCOMMENT) null_terms++; - for (; null_terms; null_terms--) { - for (;;) { - gz_ignore = 0; - read_fixed_field(&gz_ignore, 1); - if (gz_ignore == 0) break; - } - } - if (gz_flg & FHCRC) - read_fixed_field(gz_hcrc, sizeof(gz_hcrc)); - - if (aborting()) return; - - // now the input stream is ready to read into the inflater - int error = inflateInit2((z_stream*) zstream, -MAX_WBITS); - if (error != Z_OK) { abort("cannot create input"); return; } -} - -void gunzip::free() { - assert(u->gzin == this); - u->gzin = null; - u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn; - inflateEnd((z_stream*) zstream); - mtrace('f', zstream, 0); - ::free(zstream); - zstream = null; - mtrace('f', this, 0); - ::free(this); -} - -void gunzip::read_fixed_field(char* buf, size_t buflen) { - if (aborting()) return; - jlong nr = ((unpacker::read_input_fn_t)read_input_fn) - (u, buf, buflen, buflen); - if ((size_t)nr != buflen) - u->abort("short stream header"); -} - -#else // NO_ZLIB - -void gunzip::free() { -} - -#endif // NO_ZLIB diff --git a/src/jdk.pack/share/native/common-unpack/zip.h b/src/jdk.pack/share/native/common-unpack/zip.h deleted file mode 100644 index 6581f3ca1d6..00000000000 --- a/src/jdk.pack/share/native/common-unpack/zip.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#define ushort unsigned short -#define uint unsigned int -#define uchar unsigned char - -struct unpacker; - -struct jar { - // JAR file writer - FILE* jarfp; - int default_modtime; - - const char* jarname; - - // Used by unix2dostime: - int modtime_cache; - uLong dostime_cache; - - // Private members - fillbytes central_directory; - uint central_directory_count; - uint output_file_offset; - fillbytes deflated; // temporary buffer - - // pointer to outer unpacker, for error checks etc. - unpacker* u; - - // Public Methods - void openJarFile(const char* fname); - void addJarEntry(const char* fname, - bool deflate_hint, int modtime, - bytes& head, bytes& tail); - void addDirectoryToJarFile(const char* dir_name); - void closeJarFile(bool central); - - void init(unpacker* u_); - - void free() { - central_directory.free(); - deflated.free(); - } - - void reset() { - free(); - init(u); - } - - // Private Methods - void write_data(void* ptr, size_t len); - void write_data(bytes& b) { write_data(b.ptr, b.len); } - void add_to_jar_directory(const char* fname, bool store, int modtime, - int len, int clen, uLong crc); - void write_jar_header(const char* fname, bool store, int modtime, - int len, int clen, unsigned int crc); - void write_jar_extra(int len, int clen, unsigned int crc); - void write_central_directory(); - uLong dostime(int y, int n, int d, int h, int m, int s); - uLong get_dostime(int modtime); - - // The definitions of these depend on the NO_ZLIB option: - bool deflate_bytes(bytes& head, bytes& tail); - static uint get_crc32(uint c, unsigned char *ptr, uint len); - - // error handling - void abort(const char* msg) { unpack_abort(msg, u); } - bool aborting() { return unpack_aborting(u); } -}; - -struct gunzip { - // optional gzip input stream control block - - // pointer to outer unpacker, for error checks etc. - unpacker* u; - - void* read_input_fn; // underlying byte stream - void* zstream; // inflater state - char inbuf[1 << 14]; // input buffer - - uint gzcrc; // CRC gathered from gzip *container* content - uint gzlen; // CRC gathered length - - void init(unpacker* u_); // pushes new value on u->read_input_fn - - void free(); - - void start(int magic); - - // private stuff - void read_fixed_field(char* buf, size_t buflen); - - // error handling - void abort(const char* msg) { unpack_abort(msg, u); } - bool aborting() { return unpack_aborting(u); } -}; diff --git a/src/jdk.pack/share/native/libunpack/jni.cpp b/src/jdk.pack/share/native/libunpack/jni.cpp deleted file mode 100644 index 069df3f3a35..00000000000 --- a/src/jdk.pack/share/native/libunpack/jni.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -#include - -#include -#include -#include -#include - - -#include - -#include - -#include "jni_util.h" - -#include "defines.h" -#include "bytes.h" -#include "utils.h" -#include "coding.h" -#include "bands.h" -#include "constants.h" -#include "zip.h" -#include "unpack.h" - - -static jfieldID unpackerPtrFID; -static jmethodID currentInstMID; -static jmethodID readInputMID; -static jclass NIclazz; -static jmethodID getUnpackerPtrMID; - -static char* dbg = null; - -#define THROW_IOE(x) JNU_ThrowIOException(env,x) - -#define CHECK_EXCEPTION_RETURN_VOID_THROW_IOE(CERVTI_exception, CERVTI_message) \ - do { \ - if ((env)->ExceptionOccurred()) { \ - THROW_IOE(CERVTI_message); \ - return; \ - } \ - if ((CERVTI_exception) == NULL) { \ - THROW_IOE(CERVTI_message); \ - return; \ - } \ - } while (JNI_FALSE) - - -#define CHECK_EXCEPTION_RETURN_VALUE(CERL_exception, CERL_return_value) \ - do { \ - if ((env)->ExceptionOccurred()) { \ - return CERL_return_value; \ - } \ - if ((CERL_exception) == NULL) { \ - return CERL_return_value; \ - } \ - } while (JNI_FALSE) - - -// If these useful macros aren't defined in jni_util.h then define them here -#ifndef CHECK_NULL_RETURN -#define CHECK_NULL_RETURN(x, y) \ - do { \ - if ((x) == NULL) return (y); \ - } while (JNI_FALSE) -#endif - -#ifndef CHECK_EXCEPTION_RETURN -#define CHECK_EXCEPTION_RETURN(env, y) \ - do { \ - if ((*env)->ExceptionCheck(env)) return (y); \ - } while (JNI_FALSE) -#endif - -/* - * Declare library specific JNI_Onload entry if static build - */ -DEF_STATIC_JNI_OnLoad - -static jlong read_input_via_jni(unpacker* self, - void* buf, jlong minlen, jlong maxlen); - -static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) { - unpacker* uPtr; - jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID); - uPtr = (unpacker*)jlong2ptr(p); - if (uPtr == null) { - if (noCreate) return null; - uPtr = new unpacker(); - if (uPtr == null) { - THROW_IOE(ERROR_ENOMEM); - return null; - } - //fprintf(stderr, "get_unpacker(%p) uPtr=%p initializing\n", pObj, uPtr); - uPtr->init(read_input_via_jni); - uPtr->jniobj = (void*) env->NewGlobalRef(pObj); - env->SetLongField(pObj, unpackerPtrFID, ptr2jlong(uPtr)); - } - uPtr->jnienv = env; // keep refreshing this in case of MT access - return uPtr; -} - -// This is the harder trick: Pull the current state out of mid-air. -static unpacker* get_unpacker() { - //fprintf(stderr, "get_unpacker()\n"); - JavaVM* vm = null; - jsize nVM = 0; - jint retval = JNI_GetCreatedJavaVMs(&vm, 1, &nVM); - // other VM implements may differ, thus for correctness, we need these checks - if (retval != JNI_OK || nVM != 1) - return null; - void* envRaw = null; - vm->GetEnv(&envRaw, JNI_VERSION_1_1); - JNIEnv* env = (JNIEnv*) envRaw; - //fprintf(stderr, "get_unpacker() env=%p\n", env); - CHECK_NULL_RETURN(env, NULL); - jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID); - // We should check upon the known non-null variable because here we want to check - // only for pending exceptions. If pObj is null we'll deal with it later. - CHECK_EXCEPTION_RETURN_VALUE(env, NULL); - //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj); - if (pObj != null) { - // Got pObj and env; now do it the easy way. - return get_unpacker(env, pObj); - } - // this should really not happen, if it does something is seriously - // wrong throw an exception - THROW_IOE(ERROR_INTERNAL); - return null; -} - -static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) { - if (uPtr != null) { - //fprintf(stderr, "free_unpacker(%p) uPtr=%p\n", pObj, uPtr); - env->DeleteGlobalRef((jobject) uPtr->jniobj); - uPtr->jniobj = null; - uPtr->free(); - delete uPtr; - env->SetLongField(pObj, unpackerPtrFID, (jlong)null); - } -} - -unpacker* unpacker::current() { - return get_unpacker(); -} - -// Callback for fetching data, Java style. Calls NativeUnpack.readInputFn(). -static jlong read_input_via_jni(unpacker* self, - void* buf, jlong minlen, jlong maxlen) { - JNIEnv* env = (JNIEnv*) self->jnienv; - jobject pbuf = env->NewDirectByteBuffer(buf, maxlen); - return env->CallLongMethod((jobject) self->jniobj, readInputMID, - pbuf, minlen); -} - -JNIEXPORT void JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) { -#ifndef PRODUCT - dbg = getenv("DEBUG_ATTACH"); - while( dbg != null) { sleep(10); } -#endif - NIclazz = (jclass) env->NewGlobalRef(clazz); - - unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J"); - CHECK_EXCEPTION_RETURN_VOID_THROW_IOE(unpackerPtrFID, ERROR_INIT); - - currentInstMID = env->GetStaticMethodID(clazz, "currentInstance", - "()Ljava/lang/Object;"); - CHECK_EXCEPTION_RETURN_VOID_THROW_IOE(currentInstMID, ERROR_INIT); - - readInputMID = env->GetMethodID(clazz, "readInputFn", - "(Ljava/nio/ByteBuffer;J)J"); - CHECK_EXCEPTION_RETURN_VOID_THROW_IOE(readInputMID, ERROR_INIT); - - getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J"); - CHECK_EXCEPTION_RETURN_VOID_THROW_IOE(getUnpackerPtrMID, ERROR_INIT); -} - -JNIEXPORT jlong JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, - jobject pBuf, jlong offset) { - // try to get the unpacker pointer the hard way first, we do this to ensure - // valid object pointers and env is intact, if not now is good time to bail. - unpacker* uPtr = get_unpacker(); - //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, -1); - // redirect our io to the default log file or whatever. - uPtr->redirect_stdio(); - - void* buf = null; - size_t buflen = 0; - if (pBuf != null) { - buf = env->GetDirectBufferAddress(pBuf); - buflen = (size_t)env->GetDirectBufferCapacity(pBuf); - if (buflen == 0) buf = null; - if (buf == null) { THROW_IOE(ERROR_INTERNAL); return 0; } - if ((size_t)offset >= buflen) - { buf = null; buflen = 0; } - else - { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; } - } - // before we start off we make sure there is no other error by the time we - // get here - if (uPtr->aborting()) { - THROW_IOE(uPtr->get_abort_message()); - return 0; - } - uPtr->start(buf, buflen); - if (uPtr->aborting()) { - THROW_IOE(uPtr->get_abort_message()); - return 0; - } - - return ((jlong) - uPtr->get_segments_remaining() << 32) - + uPtr->get_files_remaining(); -} - -JNIEXPORT jboolean JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_getNextFile(JNIEnv *env, jobject pObj, - jobjectArray pParts) { - - unpacker* uPtr = get_unpacker(env, pObj); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); - unpacker::file* filep = uPtr->get_next_file(); - - if (uPtr->aborting()) { - THROW_IOE(uPtr->get_abort_message()); - return false; - } - - CHECK_NULL_RETURN(filep, false); - assert(filep == &uPtr->cur_file); - - int pidx = 0, iidx = 0; - jintArray pIntParts = (jintArray) env->GetObjectArrayElement(pParts, pidx++); - CHECK_EXCEPTION_RETURN_VALUE(pIntParts, false); - jint* intParts = env->GetIntArrayElements(pIntParts, null); - intParts[iidx++] = (jint)( (julong)filep->size >> 32 ); - intParts[iidx++] = (jint)( (julong)filep->size >> 0 ); - intParts[iidx++] = filep->modtime; - intParts[iidx++] = filep->deflate_hint() ? 1 : 0; - env->ReleaseIntArrayElements(pIntParts, intParts, JNI_COMMIT); - jstring filename = env->NewStringUTF(filep->name); - CHECK_EXCEPTION_RETURN_VALUE(filename, false); - env->SetObjectArrayElement(pParts, pidx++, filename); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); - jobject pDataBuf = null; - if (filep->data[0].len > 0) { - pDataBuf = env->NewDirectByteBuffer(filep->data[0].ptr, - filep->data[0].len); - CHECK_EXCEPTION_RETURN_VALUE(pDataBuf, false); - } - env->SetObjectArrayElement(pParts, pidx++, pDataBuf); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); - pDataBuf = null; - if (filep->data[1].len > 0) { - pDataBuf = env->NewDirectByteBuffer(filep->data[1].ptr, - filep->data[1].len); - CHECK_EXCEPTION_RETURN_VALUE(pDataBuf, false); - } - env->SetObjectArrayElement(pParts, pidx++, pDataBuf); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); - - return true; -} - - -JNIEXPORT jobject JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject pObj) { - unpacker* uPtr = get_unpacker(env, pObj); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, NULL); - unpacker::file* filep = &uPtr->cur_file; - - if (uPtr->aborting()) { - THROW_IOE(uPtr->get_abort_message()); - return null; - } - - // We have fetched all the files. - // Now swallow up any remaining input. - if (uPtr->input_remaining() == 0) { - return null; - } else { - bytes remaining_bytes; - remaining_bytes.malloc(uPtr->input_remaining()); - remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining()); - return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len); - } -} - -JNIEXPORT jlong JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) { - unpacker* uPtr = get_unpacker(env, pObj, false); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, 0); - size_t consumed = uPtr->input_consumed(); - free_unpacker(env, pObj, uPtr); - return consumed; -} - -JNIEXPORT jboolean JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj, - jstring pProp, jstring pValue) { - unpacker* uPtr = get_unpacker(env, pObj); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, false); - const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); - CHECK_EXCEPTION_RETURN_VALUE(prop, false); - const char* value = env->GetStringUTFChars(pValue, JNI_FALSE); - CHECK_EXCEPTION_RETURN_VALUE(value, false); - jboolean retval = uPtr->set_option(prop, value); - env->ReleaseStringUTFChars(pProp, prop); - env->ReleaseStringUTFChars(pValue, value); - return retval; -} - -JNIEXPORT jstring JNICALL -Java_com_sun_java_util_jar_pack_NativeUnpack_getOption(JNIEnv *env, jobject pObj, - jstring pProp) { - - unpacker* uPtr = get_unpacker(env, pObj); - CHECK_EXCEPTION_RETURN_VALUE(uPtr, NULL); - const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); - CHECK_EXCEPTION_RETURN_VALUE(prop, NULL); - const char* value = uPtr->get_option(prop); - CHECK_EXCEPTION_RETURN_VALUE(value, NULL); - env->ReleaseStringUTFChars(pProp, prop); - return env->NewStringUTF(value); -} diff --git a/src/jdk.pack/share/native/unpack200/main.cpp b/src/jdk.pack/share/native/unpack200/main.cpp deleted file mode 100644 index b46a6e32c22..00000000000 --- a/src/jdk.pack/share/native/unpack200/main.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -#ifdef _ALLBSD_SOURCE -#include -#define THRTYPE intptr_t -#else -#define THRTYPE int -#endif - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#if defined(unix) && !defined(PRODUCT) -#include "pthread.h" -#define THREAD_SELF ((THRTYPE)pthread_self()) -#endif - -#include "jni.h" -#include "defines.h" -#include "bytes.h" -#include "utils.h" -#include "coding.h" -#include "bands.h" - -#include "constants.h" - -#include "zip.h" - -#include "unpack.h" - - -JNIEXPORT int -main(int argc, char **argv) { - return unpacker::run(argc, argv); -} - -// Single-threaded, implementation, not reentrant. -// Includes a weak error check against MT access. -#ifndef THREAD_SELF -#define THREAD_SELF ((THRTYPE) 0) -#endif -NOT_PRODUCT(static THRTYPE uThread = -1;) - -unpacker* unpacker::non_mt_current = null; -unpacker* unpacker::current() { - //assert(uThread == THREAD_SELF); - return non_mt_current; -} -static void set_current_unpacker(unpacker* u) { - unpacker::non_mt_current = u; - assert(((uThread = (u == null) ? (THRTYPE) -1 : THREAD_SELF), - true)); -} - -// Callback for fetching data, Unix style. -static jlong read_input_via_stdio(unpacker* u, - void* buf, jlong minlen, jlong maxlen) { - assert(minlen <= maxlen); // don't talk nonsense - jlong numread = 0; - char* bufptr = (char*) buf; - while (numread < minlen) { - // read available input, up to buf.length or maxlen - int readlen = (1<<16); - if (readlen > (maxlen - numread)) - readlen = (int)(maxlen - numread); - int nr = 0; - if (u->infileptr != null) { - nr = (int)fread(bufptr, 1, readlen, u->infileptr); - } else { -#ifndef WIN32 - // we prefer unbuffered inputs - nr = (int)read(u->infileno, bufptr, readlen); -#else - nr = (int)fread(bufptr, 1, readlen, stdin); -#endif - } - if (nr <= 0) { - if (errno != EINTR) - break; - nr = 0; - } - numread += nr; - bufptr += nr; - assert(numread <= maxlen); - } - //fprintf(u->errstrm, "readInputFn(%d,%d) => %d\n", - // (int)minlen, (int)maxlen, (int)numread); - return numread; -} - -enum { EOF_MAGIC = 0, BAD_MAGIC = -1 }; -static int read_magic(unpacker* u, char peek[], int peeklen) { - assert(peeklen == 4); // magic numbers are always 4 bytes - jlong nr = (u->read_input_fn)(u, peek, peeklen, peeklen); - if (nr != peeklen) { - return (nr == 0) ? EOF_MAGIC : BAD_MAGIC; - } - int magic = 0; - for (int i = 0; i < peeklen; i++) { - magic <<= 8; - magic += peek[i] & 0xFF; - } - return magic; -} - -static void setup_gzin(unpacker* u) { - gunzip* gzin = NEW(gunzip, 1); - gzin->init(u); -} - -static const char* nbasename(const char* progname) { - const char* slash = strrchr(progname, PATH_SEPARATOR); - if (slash != null) progname = ++slash; - return progname; -} - -#define USAGE_HEADER "Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n" -#define USAGE_OPTIONS \ - "\n" \ - "Unpacking Options\n" \ - " -H{h}, --deflate-hint={h} override transmitted deflate hint:\n" \ - " true, false, or keep (default)\n" \ - " -r, --remove-pack-file remove input file after unpacking\n" \ - " -v, --verbose increase program verbosity\n" \ - " -q, --quiet set verbosity to lowest level\n" \ - " -l{F}, --log-file={F} output to the given log file,\n" \ - " or '-' for standard output (default)\n" \ - " -?, -h, --help print this help message\n" \ - " -V, --version print program version\n" \ - "\n" \ - "Exit Status:\n" \ - " 0 if successful, >0 if an error occurred\n" - -#define DEPRECATE_WARNING \ - "\nWarning: The %s tool is deprecated, and is planned for removal in a future JDK release.\n\n" - -#define SUPPRESS_DEPRECATE_MSG "-XDsuppress-tool-removal-message" - -static bool suppress_warning = false; - -static void usage(unpacker* u, const char* progname, bool full = false) { - // WinMain does not set argv[0] to the progrname - progname = (progname != null) ? nbasename(progname) : "unpack200"; - - fprintf(u->errstrm, USAGE_HEADER, progname); - if (full) { - fprintf(u->errstrm, USAGE_OPTIONS); - } else { - fprintf(u->errstrm, "(For more information, run %s --help .)\n", progname); - } -} - -// argument parsing -static char** init_args(int argc, char** argv, int &envargc) { - const char* env = getenv("UNPACK200_FLAGS"); - ptrlist envargs; - envargs.init(); - if (env != null) { - char* buf = (char*) strdup(env); - const char* delim = "\n\t "; - for (char* p = strtok(buf, delim); p != null; p = strtok(null, delim)) { - if (!strcmp(p, SUPPRESS_DEPRECATE_MSG)) { - suppress_warning = true; - } else { - envargs.add(p); - } - } - } - // allocate extra margin at both head and tail - char** argp = NEW(char*, envargs.length()+argc+1); - char** argp0 = argp; - int i; - for (i = 0; i < envargs.length(); i++) { - *argp++ = (char*) envargs.get(i); - } - for (i = 1; i < argc; i++) { - // note: skip argv[0] (program name) - if (!strcmp(argv[i], SUPPRESS_DEPRECATE_MSG)) { - suppress_warning = true; - } else { - *argp++ = (char*) strdup(argv[i]); // make a scratch copy - } - } - *argp = null; // sentinel - envargc = envargs.length(); // report this count to next_arg - envargs.free(); - return argp0; -} - -static int strpcmp(const char* str, const char* pfx) { - return strncmp(str, pfx, strlen(pfx)); -} - -static const char flag_opts[] = "vqrVh?"; -static const char string_opts[] = "HlJ"; - -static int next_arg(char** &argp) { - char* arg = *argp; - if (arg == null || arg[0] != '-') { // end of option list - return 0; - } - //printf("opt: %s\n", arg); - char ach = arg[1]; - if (ach == '\0') { - // ++argp; // do not pop this arg - return 0; // bare "-" is stdin/stdout - } else if (arg[1] == '-') { // --foo option - static const char* keys[] = { - "Hdeflate-hint=", - "vverbose", - "qquiet", - "rremove-pack-file", - "llog-file=", - "Vversion", - "hhelp", - null }; - if (arg[2] == '\0') { // end of option list - ++argp; // pop the "--" - return 0; - } - for (int i = 0; keys[i] != null; i++) { - const char* key = keys[i]; - char kch = *key++; - if (strchr(key, '=') == null) { - if (!strcmp(arg+2, key)) { - ++argp; // pop option arg - return kch; - } - } else { - if (!strpcmp(arg+2, key)) { - *argp += 2 + strlen(key); // remove "--"+key from arg - return kch; - } - } - } - } else if (strchr(flag_opts, ach) != null) { // plain option - if (arg[2] == '\0') { - ++argp; - } else { - // in-place edit of "-vxyz" to "-xyz" - arg += 1; // skip original '-' - arg[0] = '-'; - *argp = arg; - } - //printf(" key => %c\n", ach); - return ach; - } else if (strchr(string_opts, ach) != null) { // argument-bearing option - if (arg[2] == '\0') { - if (argp[1] == null) return -1; // no next arg - ++argp; // leave the argument in place - } else { - // in-place edit of "-Hxyz" to "xyz" - arg += 2; // skip original '-H' - *argp = arg; - } - //printf(" key => %c\n", ach); - return ach; - } - return -1; // bad argument -} - -static const char sccsver[] = "1.30, 07/05/05"; - -// Usage: unpackage input.pack output.jar -int unpacker::run(int argc, char **argv) { - unpacker u; - u.init(read_input_via_stdio); - set_current_unpacker(&u); - - jar jarout; - jarout.init(&u); - - int envargc = 0; - char** argbuf = init_args(argc, argv, envargc); - char** arg0 = argbuf+envargc; - char** argp = argbuf; - - int verbose = 0; - char* logfile = null; - - if (!suppress_warning) { - fprintf(u.errstrm, DEPRECATE_WARNING, nbasename(argv[0])); - } - - for (;;) { - const char* arg = (*argp == null)? "": u.saveStr(*argp); - bool isenvarg = (argp < arg0); - int ach = next_arg(argp); - bool hasoptarg = (ach != 0 && strchr(string_opts, ach) != null); - if (ach == 0 && argp >= arg0) break; - if (isenvarg && argp == arg0 && hasoptarg) ach = 0; // don't pull from cmdline - switch (ach) { - case 'H': u.set_option(UNPACK_DEFLATE_HINT,*argp++); break; - case 'v': ++verbose; break; - case 'q': verbose = 0; break; - case 'r': u.set_option(UNPACK_REMOVE_PACKFILE,"1"); break; - case 'l': logfile = *argp++; break; - case 'J': argp += 1; break; // skip ignored -Jxxx parameter - - case 'V': - fprintf(u.errstrm, VERSION_STRING, nbasename(argv[0]), sccsver); - exit(0); - - case 'h': - case '?': - usage(&u, argv[0], true); - exit(0); - - default: - const char* inenv = isenvarg? " in ${UNPACK200_FLAGS}": ""; - if (hasoptarg) - fprintf(u.errstrm, "Missing option string%s: %s\n", inenv, arg); - else - fprintf(u.errstrm, "Unrecognized argument%s: %s\n", inenv, arg); - usage(&u, argv[0]); - exit(2); - } - } - - if (verbose != 0) { - u.set_option(DEBUG_VERBOSE, u.saveIntStr(verbose)); - } - if (logfile != null) { - u.set_option(UNPACK_LOG_FILE, logfile); - } - - u.redirect_stdio(); - - const char* source_file = *argp++; - const char* destination_file = *argp++; - - if (source_file == null || destination_file == null || *argp != null) { - usage(&u, argv[0]); - exit(2); - } - - if (verbose != 0) { - fprintf(u.errstrm, - "Unpacking from %s to %s\n", source_file, destination_file); - } - bool& remove_source = u.remove_packfile; - - if (strcmp(source_file, "-") == 0) { - remove_source = false; - u.infileno = fileno(stdin); - } else { - u.infileptr = fopen(source_file, "rb"); - if (u.infileptr == null) { - fprintf(u.errstrm, - "Error: Could not open input file: %s\n", source_file); - exit(3); // Called only from the native standalone unpacker - } - } - - if (strcmp(destination_file, "-") == 0) { - jarout.jarfp = stdout; - jarout.jarname = null; - if (u.errstrm == stdout) // do not mix output - u.set_option(UNPACK_LOG_FILE, LOGFILE_STDERR); - } else { - jarout.openJarFile(destination_file); - assert(jarout.jarfp != null); - } - - if (verbose != 0) - u.dump_options(); - - char peek[4]; - int magic; - - // check for GZIP input - magic = read_magic(&u, peek, (int)sizeof(peek)); - if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC) { - // Oops; must slap an input filter on this data. - setup_gzin(&u); - u.gzin->start(magic); - u.gzin->gzcrc = 0; - u.gzin->gzlen = 0; - if (!u.aborting()) { - u.start(); - } - } else { - u.start(peek, sizeof(peek)); - } - - // Note: The checks to u.aborting() are necessary to gracefully - // terminate processing when the first segment throws an error. - - for (;;) { - if (u.aborting()) break; - - // Each trip through this loop unpacks one segment - // and then resets the unpacker. - for (unpacker::file* filep; (filep = u.get_next_file()) != null; ) { - if (u.aborting()) break; - u.write_file_to_jar(filep); - } - if (u.aborting()) break; - - // Peek ahead for more data. - magic = read_magic(&u, peek, (int)sizeof(peek)); - if (magic != (int)JAVA_PACKAGE_MAGIC) { - if (magic != EOF_MAGIC) - u.abort("garbage after end of pack archive"); - break; // all done - } - - // Release all storage from parsing the old segment. - u.reset(); - - // Restart, beginning with the peek-ahead. - u.start(peek, sizeof(peek)); - } - - int status = 0; - if (u.aborting()) { - fprintf(u.errstrm, "Error: %s\n", u.get_abort_message()); - status = 1; - } - - if (u.infileptr != null) { - fclose(u.infileptr); - u.infileptr = null; - } - - if (!u.aborting() && remove_source) - remove(source_file); - - if (verbose != 0) { - fprintf(u.errstrm, "unpacker completed with status=%d\n", status); - } - - u.finish(); - - u.free(); // tidy up malloc blocks - set_current_unpacker(null); // clean up global pointer - - return status; -} diff --git a/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest b/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest deleted file mode 100644 index b2583b5b744..00000000000 --- a/src/jdk.pack/windows/native/unpack200/unpack200_proto.exe.manifest +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Java(TM) SE Runtime Environment unpack200 Process. - - - - - - - - - diff --git a/src/utils/IdealGraphVisualizer/nbproject/project.properties b/src/utils/IdealGraphVisualizer/nbproject/project.properties index f9a657cb6ee..27cd941e4ed 100644 --- a/src/utils/IdealGraphVisualizer/nbproject/project.properties +++ b/src/utils/IdealGraphVisualizer/nbproject/project.properties @@ -6,7 +6,6 @@ auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=true auxiliary.org-netbeans-modules-apisupport-installer.os-solaris=false auxiliary.org-netbeans-modules-apisupport-installer.os-windows=false -auxiliary.org-netbeans-modules-apisupport-installer.pack200-enabled=false auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml modules=\ ${project.com.sun.hotspot.igv.graph}:\ diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index e823472803b..4ebc36c778e 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -885,15 +885,6 @@ sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all # core_tools -tools/pack200/CommandLineTests.java 8059906 generic-all -tools/pack200/TestNormal.java 8234542 generic-all this test can be delisted as soon as pack200 is removed -tools/pack200/Pack200Test.java 8234542 generic-all this test can be delisted as soon as pack200 is removed -tools/pack200/MultiRelease.java 8234542 generic-all this test can be delisted as soon as pack200 is removed -tools/pack200/ModuleAttributes.java 8234542 generic-all this test can be delisted as soon as pack200 is removed -tools/pack200/InstructionTests.java 8234542 generic-all this test can be delisted as soon as pack200 is removed -tools/pack200/AttributeTests.java 8234542 generic-all this test can be delisted as soon as pack200 is removed -tools/pack200/typeannos/TestTypeAnnotations.java 8234542 generic-all this test can be delisted as soon as pack200 is removed - tools/jlink/JLinkReproducibleTest.java 8217166 windows-all ############################################################################ diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 91ae0fb2efc..25484b673e6 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -42,8 +42,7 @@ tier1_part3 = \ :jdk_svc_sanity \ java/nio/Buffer \ com/sun/crypto/provider/Cipher \ - sun/nio/cs/ISO8859x.java \ - tools/pack200 + sun/nio/cs/ISO8859x.java # When adding tests to tier2, make sure they end up in one of the tier2_partX groups tier2 = \ @@ -59,7 +58,6 @@ tier2_part1 = \ # sun/nio/cs/ISO8859x.java and java/nio/Buffer are in tier1 because of JDK-8132854 tier2_part2 = \ :core_tools \ - -tools/pack200 \ :jdk_io \ :jdk_nio \ -java/nio/Buffer \ diff --git a/test/jdk/java/util/jar/Pack200/SecurityTest.java b/test/jdk/java/util/jar/Pack200/SecurityTest.java deleted file mode 100644 index 93b24818356..00000000000 --- a/test/jdk/java/util/jar/Pack200/SecurityTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8179645 - * @run main/othervm SecurityTest - * @summary Verify Pack200 initialization with security manager - */ - -import java.util.jar.Pack200; - -public class SecurityTest { - public static void main(String... args) { - System.setSecurityManager(new SecurityManager()); - Pack200.newPacker(); - Pack200.newUnpacker(); - } -} diff --git a/test/jdk/tools/jar/DeprecateOptionN.java b/test/jdk/tools/jar/DeprecateOptionN.java deleted file mode 100644 index d9cf2978299..00000000000 --- a/test/jdk/tools/jar/DeprecateOptionN.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8199871 - * @modules jdk.jartool - * @summary jar -n should print out deprecation warning - * @run testng DeprecateOptionN - */ - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.spi.ToolProvider; -import org.testng.annotations.Test; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -public class DeprecateOptionN { - private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") - .orElseThrow(() -> - new RuntimeException("jar tool not found") - ); - - protected static String jar(String... options) { - StringWriter writer = new StringWriter(); - PrintWriter pw = new PrintWriter(writer); - - JAR_TOOL.run(pw, pw, options); - String output = writer.toString(); - System.err.println(output); - return output; - } - - @Test - public void helpCompatWithWarning() { - String output = jar("--help:compat"); - assertTrue(output.contains("this option is deprecated, and is planned for removal in a future JDK release")); - } - - @Test - public void helpExtraWithWarning() { - String output = jar("--help-extra"); - assertTrue(output.contains("This option is deprecated, and is")); - assertTrue(output.contains("planned for removal in a future JDK release")); - } - - @Test - public void normalizeWithWarning() throws IOException { - File tmp = File.createTempFile("test", null); - String output = jar("cnf", "test.jar", tmp.getAbsolutePath()); - tmp.delete(); - assertTrue(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release")); - } - - @Test - public void NoWarningWithoutN() throws IOException { - File tmp = File.createTempFile("test", null); - String output = jar("cf", "test.jar", tmp.getAbsolutePath()); - tmp.delete(); - assertFalse(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release")); - } - - - @Test - public void SuppressWarning() throws IOException { - File tmp = File.createTempFile("test", null); - String output = jar("-c", "-n", "-XDsuppress-tool-removal-message", - "-f", "test.jar", tmp.getAbsolutePath()); - tmp.delete(); - assertFalse(output.contains("Warning: The -n option is deprecated, and is planned for removal in a future JDK release")); - } -} diff --git a/test/jdk/tools/launcher/HelpFlagsTest.java b/test/jdk/tools/launcher/HelpFlagsTest.java index 639c9c92da8..8101035b856 100644 --- a/test/jdk/tools/launcher/HelpFlagsTest.java +++ b/test/jdk/tools/launcher/HelpFlagsTest.java @@ -155,12 +155,10 @@ private static class ToolHelpSpec { new ToolHelpSpec("jstat", 1, 1, 1, 0, 1, 1, 1), // -?, -h, --help -help, Documents -help new ToolHelpSpec("jstatd", 1, 1, 1, 0, 0, 0, 1), // -?, -h, --help new ToolHelpSpec("keytool", 1, 1, 1, 0, 1, 0, 1), // none, prints help message anyways. - new ToolHelpSpec("pack200", 1, 1, 1, 0, 1, 0, 2), // -?, -h, --help, -help accepted but not documented. new ToolHelpSpec("rmic", 0, 0, 0, 0, 0, 0, 1), // none, prints help message anyways. new ToolHelpSpec("rmid", 0, 0, 0, 0, 0, 0, 1), // none, prints help message anyways. new ToolHelpSpec("rmiregistry", 0, 0, 0, 0, 0, 0, 1), // none, prints help message anyways. new ToolHelpSpec("serialver", 0, 0, 0, 0, 0, 0, 1), // none, prints help message anyways. - new ToolHelpSpec("unpack200", 1, 1, 1, 0, 1, 0, 2), // -?, -h, --help, -help accepted but not documented. new ToolHelpSpec("jpackage", 0, 1, 1, 0, 0, 1, 1), // -h, --help, }; diff --git a/test/jdk/tools/launcher/VersionCheck.java b/test/jdk/tools/launcher/VersionCheck.java index b9cfffdc4dc..4e405ded37b 100644 --- a/test/jdk/tools/launcher/VersionCheck.java +++ b/test/jdk/tools/launcher/VersionCheck.java @@ -63,8 +63,7 @@ public class VersionCheck extends TestHelper { "jmc.ini", "jweblauncher", "jpackage", - "ssvagent", - "unpack200", + "ssvagent" }; // tools that do not accept -version @@ -107,15 +106,13 @@ public class VersionCheck extends TestHelper { "kinit", "klist", "ktab", - "pack200", "jpackage", "rmic", "rmid", "rmiregistry", "serialver", "servertool", - "ssvagent", - "unpack200" + "ssvagent" }; // expected reference strings diff --git a/test/jdk/tools/pack200/AttributeTests.java b/test/jdk/tools/pack200/AttributeTests.java deleted file mode 100644 index 09b9986175c..00000000000 --- a/test/jdk/tools/pack200/AttributeTests.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -/* - * @test - * @bug 6746111 8005252 8008262 - * @summary tests various classfile format and attribute handling by pack200 - * @compile -XDignore.symbol.file Utils.java AttributeTests.java - * @run main AttributeTests - * @author ksrini - */ -public class AttributeTests { - - public static void main(String... args) throws Exception { - test6746111(); - testMethodParameters(); - Utils.cleanup(); - } - - /* - * this tests ensure that MethodParameters produces by javac is packed - * correctly. Usually this is not the case as new attributes are available - * in the sdk jars, since MethodParameters happens to be an optional - * attribute, thus this test. - */ - static void testMethodParameters() throws Exception { - List scratch = new ArrayList<>(); - final String fname = "MP"; - String javaFileName = fname + Utils.JAVA_FILE_EXT; - String javaClassName = fname + Utils.CLASS_FILE_EXT; - scratch.add("class " + fname + " {"); - scratch.add("void foo2(int j, final int k){}"); - scratch.add("}"); - File cwd = new File("."); - File javaFile = new File(cwd, javaFileName); - Utils.createFile(javaFile, scratch); - - Utils.compiler(javaFile.getName(), "-parameters"); - - // jar the file up - File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); - Utils.jar("cvf", testjarFile.getName(), javaClassName); - - Utils.testWithRepack(testjarFile, "--unknown-attribute=error"); - } - /* - * this test checks to see if we get the expected strings for output - */ - static void test6746111() throws Exception { - String pack200Cmd = Utils.getPack200Cmd(); - File badAttrJar = new File(".", "badattr.jar"); - Utils.copyFile(new File(Utils.TEST_SRC_DIR, "badattr.jar"), badAttrJar); - File testJar = new File(".", "test.jar"); - List cmds = new ArrayList(); - cmds.add(pack200Cmd); - cmds.add("--repack"); - cmds.add("-v"); - cmds.add(testJar.getAbsolutePath()); - cmds.add(badAttrJar.getAbsolutePath()); - List output = Utils.runExec(cmds); - /* - * compare the repacked jar bit-wise, as all the files - * should be transmitted "as-is". - */ - Utils.doCompareBitWise(badAttrJar.getAbsoluteFile(), testJar.getAbsoluteFile()); - String[] expectedStrings = { - "WARNING: Passing class file uncompressed due to unrecognized" + - " attribute: Foo.class", - "INFO: com.sun.java.util.jar.pack.Attribute$FormatException: " + - "class attribute \"XourceFile\": is unknown attribute " + - "in class Foo", - "INFO: com.sun.java.util.jar.pack.ClassReader$ClassFormatException: " + - "AnnotationDefault: attribute length cannot be zero, in Test.message()", - "WARNING: Passing class file uncompressed due to unknown class format: Test.class" - }; - List notfoundList = new ArrayList(); - notfoundList.addAll(Arrays.asList(expectedStrings)); - // make sure the expected messages are emitted - for (String x : output) { - findString(x, notfoundList, expectedStrings); - } - if (!notfoundList.isEmpty()) { - System.out.println("Not found:"); - for (String x : notfoundList) { - System.out.println(x); - } - throw new Exception("Test fails: " + notfoundList.size() + - " expected strings not found"); - } - testJar.delete(); - badAttrJar.delete(); - } - - private static void findString(String outputStr, List notfoundList, - String[] expectedStrings) { - for (String y : expectedStrings) { - if (outputStr.contains(y)) { - notfoundList.remove(y); - return; - } - } - } -} diff --git a/test/jdk/tools/pack200/BandIntegrity.java b/test/jdk/tools/pack200/BandIntegrity.java deleted file mode 100644 index c46a4b7d9de..00000000000 --- a/test/jdk/tools/pack200/BandIntegrity.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test 8187645 - * @summary test ensures the proper sequencing of bands, dump bands as well. - * @compile -XDignore.symbol.file Utils.java BandIntegrity.java - * @run main BandIntegrity - * @author ksrini - */ -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/* - * This makes use of the optDebugBands to ensure the bands are read in the - * same sequence as it was written. The caveat is that this works only with - * the java unpacker, therefore it will work only with --repack such that - * the java packer and unpacker must be called in the same java instance. - */ -public class BandIntegrity { - public static void main(String... args) throws IOException { - File testFile = new File("test.jar"); - Utils.jar("cvf", testFile.getName(), - "-C", Utils.TEST_CLS_DIR.getAbsolutePath(), - "."); - List scratch = new ArrayList<>(); - // band debugging works only with java unpacker - scratch.add("com.sun.java.util.jar.pack.disable.native=true"); - scratch.add("com.sun.java.util.jar.pack.debug.bands=true"); - // while at it, might as well exercise this functionality - scratch.add("com.sun.java.util.jar.pack.dump.bands=true"); - scratch.add("pack.unknown.attribute=error"); - File configFile = new File("pack.conf"); - Utils.createFile(configFile, scratch); - File outFile = new File("out.jar"); - Utils.repack(testFile, outFile, true, - "-v", "--config-file=" + configFile.getName()); - Utils.cleanup(); - } -} diff --git a/test/jdk/tools/pack200/CommandLineTests.java b/test/jdk/tools/pack200/CommandLineTests.java deleted file mode 100644 index 0eff5388e45..00000000000 --- a/test/jdk/tools/pack200/CommandLineTests.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test CommandLineTests.sh - * @bug 6521334 6965836 6965836 - * @ignore 8059906 - * @compile -XDignore.symbol.file CommandLineTests.java Pack200Test.java - * @run main/timeout=1200 CommandLineTests - * @summary An ad hoc test to verify the behavior of pack200/unpack200 CLIs, - * and a simulation of pack/unpacking in the install repo. - * @author ksrini - */ - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; -/* - * We try a potpouri of things ie. we have pack.conf to setup some - * options as well as a couple of command line options. We also test - * the packing and unpacking mechanism using the Java APIs. This also - * simulates pack200 the install workspace, noting that this is a simulation - * and can only test jars that are guaranteed to be available, also the - * configuration may not be in sync with the installer workspace. - */ - -public class CommandLineTests { - private static final File CWD = new File("."); - private static final File EXP_SDK = new File(CWD, "exp-sdk-image"); - private static final File EXP_SDK_LIB_DIR = new File(EXP_SDK, "lib"); - private static final File EXP_SDK_BIN_DIR = new File(EXP_SDK, "bin"); - private static final File EXP_JRE_DIR = new File(EXP_SDK, "jre"); - private static final File EXP_JRE_LIB_DIR = new File(EXP_JRE_DIR, "lib"); - private static final File RtJar = new File(EXP_JRE_LIB_DIR, "rt.jar"); - private static final File CharsetsJar = new File(EXP_JRE_LIB_DIR, "charsets.jar"); - private static final File JsseJar = new File(EXP_JRE_LIB_DIR, "jsse.jar"); - private static final File ToolsJar = new File(EXP_SDK_LIB_DIR, "tools.jar"); - private static final File javaCmd; - private static final File javacCmd; - private static final File ConfigFile = new File("pack.conf"); - private static final List jarList; - - static { - javaCmd = Utils.IsWindows - ? new File(EXP_SDK_BIN_DIR, "java.exe") - : new File(EXP_SDK_BIN_DIR, "java"); - - javacCmd = Utils.IsWindows - ? new File(EXP_SDK_BIN_DIR, "javac.exe") - : new File(EXP_SDK_BIN_DIR, "javac"); - - jarList = new ArrayList(); - jarList.add(RtJar); - jarList.add(CharsetsJar); - jarList.add(JsseJar); - jarList.add(ToolsJar); - } - - // init test area with a copy of the sdk - static void init() throws IOException { - Utils.recursiveCopy(Utils.JavaSDK, EXP_SDK); - creatConfigFile(); - } - // cleanup the test area - static void cleanup() throws IOException { - Utils.recursiveDelete(EXP_SDK); - Utils.cleanup(); - } - - // Hopefully, this should be kept in sync with what the installer does. - static void creatConfigFile() throws IOException { - FileOutputStream fos = null; - PrintStream ps = null; - try { - fos = new FileOutputStream(ConfigFile); - ps = new PrintStream(fos); - ps.println("com.sun.java.util.jar.pack.debug.verbose=0"); - ps.println("pack.modification.time=keep"); - ps.println("pack.keep.class.order=true"); - ps.println("pack.deflate.hint=false"); - // Fail the build, if new or unknown attributes are introduced. - ps.println("pack.unknown.attribute=error"); - ps.println("pack.segment.limit=-1"); - // BugId: 6328502, These files will be passed-through as-is. - ps.println("pack.pass.file.0=java/lang/Error.class"); - ps.println("pack.pass.file.1=java/lang/LinkageError.class"); - ps.println("pack.pass.file.2=java/lang/Object.class"); - ps.println("pack.pass.file.3=java/lang/Throwable.class"); - ps.println("pack.pass.file.4=java/lang/VerifyError.class"); - } finally { - Utils.close(ps); - Utils.close(fos); - } - } - - static void runPack200(boolean jre) throws IOException { - List cmdsList = new ArrayList(); - for (File f : jarList) { - if (jre && f.getName().equals("tools.jar")) { - continue; // need not worry about tools.jar for JRE - } - // make a backup copy for re-use - File bakFile = new File(f.getName() + ".bak"); - if (!bakFile.exists()) { // backup - Utils.copyFile(f, bakFile); - } else { // restore - Utils.copyFile(bakFile, f); - } - cmdsList.clear(); - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add("-J-esa"); - cmdsList.add("-J-ea"); - cmdsList.add(Utils.Is64Bit ? "-J-Xmx1g" : "-J-Xmx512m"); - cmdsList.add("--repack"); - cmdsList.add("--config-file=" + ConfigFile.getAbsolutePath()); - if (jre) { - cmdsList.add("--strip-debug"); - } - // NOTE: commented until 6965836 is fixed - // cmdsList.add("--code-attribute=StackMapTable=strip"); - cmdsList.add(f.getAbsolutePath()); - Utils.runExec(cmdsList); - } - } - - static void testJRE() throws IOException { - runPack200(true); - // the speciment JRE - List cmdsList = new ArrayList(); - cmdsList.add(javaCmd.getAbsolutePath()); - cmdsList.add("-verify"); - cmdsList.add("-version"); - Utils.runExec(cmdsList); - } - - static void testJDK() throws IOException { - runPack200(false); - // test the specimen JDK - List cmdsList = new ArrayList(); - cmdsList.add(javaCmd.getAbsolutePath()); - cmdsList.add("-verify"); - cmdsList.add("-version"); - Utils.runExec(cmdsList); - - // invoke javac to test the tools.jar - cmdsList.clear(); - cmdsList.add(javacCmd.getAbsolutePath()); - cmdsList.add("-J-verify"); - cmdsList.add("-help"); - Utils.runExec(cmdsList); - } - public static void main(String... args) { - try { - init(); - testJRE(); - testJDK(); - cleanup(); // cleanup only if we pass successfully - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } -} diff --git a/test/jdk/tools/pack200/DeprecatePack200.java b/test/jdk/tools/pack200/DeprecatePack200.java deleted file mode 100644 index df9f4c777d6..00000000000 --- a/test/jdk/tools/pack200/DeprecatePack200.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8199871 - * @summary pack200 and unpack200 should print out deprecate warning - * @modules jdk.pack - * @compile -XDignore.symbol.file Utils.java - * @run testng DeprecatePack200 - */ - -import java.util.List; -import java.util.function.Predicate; -import java.util.regex.Pattern; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; - -public class DeprecatePack200 { - final static String PACK200_CMD = Utils.getPack200Cmd(); - final static String UNPACK200_CMD = Utils.getUnpack200Cmd(); - final static Predicate PACK200_MSG = Pattern.compile( - "Warning: The pack200(\\.exe)?? tool is deprecated, and is planned for removal in a future JDK release.") - .asMatchPredicate(); - final static Predicate UNPACK200_MSG = Pattern.compile( - "Warning: The unpack200(\\.exe)?? tool is deprecated, and is planned for removal in a future JDK release.") - .asMatchPredicate(); - - @DataProvider(name="tools") - public static final Object[][] provide() { return cases; } - - private static final Object[][] cases = { - { PACK200_MSG, 1, List.of(PACK200_CMD) }, - { PACK200_MSG, 1, List.of(PACK200_CMD, "-V") }, - { PACK200_MSG, 2, List.of(PACK200_CMD, "--help") }, - { PACK200_MSG, 0, List.of(PACK200_CMD, "-XDsuppress-tool-removal-message") }, - { PACK200_MSG, 0, List.of(PACK200_CMD, "--version", "-XDsuppress-tool-removal-message") }, - { PACK200_MSG, 0, List.of(PACK200_CMD, "-h", "-XDsuppress-tool-removal-message") }, - - { UNPACK200_MSG, 1, List.of(UNPACK200_CMD) }, - { UNPACK200_MSG, 1, List.of(UNPACK200_CMD, "-V") }, - { UNPACK200_MSG, 1, List.of(UNPACK200_CMD, "--help") }, - { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "-XDsuppress-tool-removal-message") }, - { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "--version", "-XDsuppress-tool-removal-message") }, - { UNPACK200_MSG, 0, List.of(UNPACK200_CMD, "-h", "-XDsuppress-tool-removal-message") } - }; - - @Test(dataProvider = "tools") - public void CheckWarnings(Predicate msg, long count, List cmd) { - List output = Utils.runExec(cmd, null, true); - assertEquals(output.stream().filter(msg).count(), count); - } -} diff --git a/test/jdk/tools/pack200/InstructionTests.java b/test/jdk/tools/pack200/InstructionTests.java deleted file mode 100644 index 569b7a0acb0..00000000000 --- a/test/jdk/tools/pack200/InstructionTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/* - * @test - * @bug 8003549 8007297 - * @summary tests class files instruction formats introduced in JSR-335 - * @compile -XDignore.symbol.file Utils.java InstructionTests.java - * @run main InstructionTests - * @author ksrini - */ -public class InstructionTests { - public static void main(String... args) throws Exception { - testInvokeOpCodes(); - Utils.cleanup(); - } - /* - * the following should produce invokestatic and invokespecial - * on InterfaceMethodRefs vs. MethodRefs, packer/unpacker should work - */ - static void testInvokeOpCodes() throws Exception { - List scratch = new ArrayList<>(); - final String fname = "A"; - String javaFileName = fname + Utils.JAVA_FILE_EXT; - scratch.add("interface I {"); - scratch.add(" default void forEach(){}"); - scratch.add(" static void next() {}"); - scratch.add("}"); - scratch.add("class A implements I {"); - scratch.add(" public void forEach(Object o){"); - scratch.add(" I.super.forEach();"); - scratch.add(" I.next();"); - scratch.add(" }"); - scratch.add("}"); - File cwd = new File("."); - File javaFile = new File(cwd, javaFileName); - Utils.createFile(javaFile, scratch); - - // -g to compare LVT and LNT entries - Utils.compiler("-g", javaFile.getName()); - - File propsFile = new File("pack.props"); - scratch.clear(); - scratch.add("com.sun.java.util.jar.pack.class.format.error=error"); - scratch.add("pack.unknown.attribute=error"); - Utils.createFile(propsFile, scratch); - // jar the file up - File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); - Utils.jar("cvf", testjarFile.getName(), "."); - - Utils.testWithRepack(testjarFile, "--config-file=" + propsFile.getName()); - } -} diff --git a/test/jdk/tools/pack200/ModuleAttributes.java b/test/jdk/tools/pack200/ModuleAttributes.java deleted file mode 100644 index c795f764c59..00000000000 --- a/test/jdk/tools/pack200/ModuleAttributes.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -/* - * @test - * @bug 8048100 - * @summary test the new Module attributes - * @modules jdk.compiler - * jdk.zipfs - * @compile -XDignore.symbol.file Utils.java ModuleAttributes.java - * @run main ModuleAttributes - */ -public class ModuleAttributes { - - public static void main(String... args) throws Exception { - new ModuleAttributes().run(); - } - - public void run() throws Exception { - File file = Utils.createRtJar(".*module-info\\.class"); - Utils.testWithRepack(file, - "--effort=1", - "--unknown-attribute=error"); - Utils.cleanup(); - } -} diff --git a/test/jdk/tools/pack200/MultiRelease.java b/test/jdk/tools/pack200/MultiRelease.java deleted file mode 100644 index 491c09c34c5..00000000000 --- a/test/jdk/tools/pack200/MultiRelease.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/* - * @test - * @bug 8066272 - * @summary tests a simple multi-versioned jar file - * @compile -XDignore.symbol.file Utils.java MultiRelease.java - * @run main MultiRelease - * @author ksrini - */ - -public class MultiRelease { - private static final File cwd = new File("."); - private static int pass = 0; - private static int fail = 0; - // specify alternate name via arguments to verify - // if permanent fix works - - private static final String PropKey = "pack200.MultiRelease.META-INF"; - private static final String MetaInfName = System.getProperty(PropKey, "META-INF"); - - public static void main(String... args) throws Exception { - new MultiRelease().run(); - } - - void run() throws Exception { - List testCases = new ArrayList<>(); - testCases.add(new TestCase1()); - testCases.add(new TestCase2()); - for (TestCase tc : testCases) { - tc.run(); - } - if (fail > 0) { - throw new Exception(fail + "/" + testCases.size() + " tests fails"); - } else { - System.out.println("All tests(" + pass + ") passes"); - } - Utils.cleanup(); - } - - /* - * An abstract class to eliminate test boiler plating. - */ - static abstract class TestCase { - final File tcwd; - final File metaInfDir; - final File versionsDir; - final File manifestFile; - - TestCase(String directory) throws IOException { - System.out.println("initializing directories"); - tcwd = new File(cwd, directory); - metaInfDir = mkdir(new File(tcwd, MetaInfName)); - versionsDir = mkdir(new File(metaInfDir, "versions")); - manifestFile = new File(tcwd, "manifest.tmp"); - List scratch = new ArrayList<>(); - scratch.add("Multi-Release: true"); - Utils.createFile(manifestFile, scratch); - } - - File mkdir(File f) throws IOException { - if (f.exists() && f.isDirectory() && f.canRead() && f.canWrite()) { - return f; - } - if (!f.mkdirs()) { - throw new IOException("mkdirs failed: " + f.getAbsolutePath()); - } - return f; - } - - abstract void emitClassFiles() throws Exception; - - void run() { - try { - emitClassFiles(); - // jar the file up - File testFile = new File(tcwd, "test" + Utils.JAR_FILE_EXT); - Utils.jar("cvfm", - testFile.getAbsolutePath(), - manifestFile.getAbsolutePath(), - "-C", - tcwd.getAbsolutePath(), - "."); - File outFile = new File(tcwd, "test-repacked" + Utils.JAR_FILE_EXT); - List cmdsList = new ArrayList<>(); - - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add("-J-ea"); - cmdsList.add("-J-esa"); - cmdsList.add("-v"); - cmdsList.add("--repack"); - cmdsList.add(outFile.getAbsolutePath()); - cmdsList.add(testFile.getAbsolutePath()); - List output = Utils.runExec(cmdsList); - Utils.doCompareVerify(testFile.getAbsoluteFile(), outFile.getAbsoluteFile()); - pass++; - } catch (Exception e) { - e.printStackTrace(System.err); - fail++; - } - } - } - - static class TestCase1 extends TestCase { - private TestCase1(String directory) throws IOException { - super(directory); - } - - public TestCase1() throws Exception { - this("case1"); - } - - @Override - void emitClassFiles() throws Exception { - emitClassFile(""); - emitClassFile("7"); - emitClassFile("8"); - emitClassFile("9"); - } - - /* - * Adds different variants of types - */ - void emitClassFile(String version) throws IOException { - final File outDir = mkdir(version.isEmpty() - ? tcwd - : new File(versionsDir, version)); - - final File srcDir = mkdir(version.isEmpty() - ? new File(tcwd, "src") - : new File(new File(versionsDir, version), "src")); - - final String fname = "Foo"; - final File srcFile = new File(srcDir, fname + Utils.JAVA_FILE_EXT); - List scratch = new ArrayList<>(); - - scratch.add("package pkg;"); - switch (version) { - case "7": - scratch.add("public class Foo {"); - scratch.add("public static final class Bar {}"); - break; - case "8": - scratch.add("public abstract class Foo {"); - scratch.add("public final class Bar {}"); - break; - case "9": - scratch.add("public interface Foo {"); - scratch.add("public final class Bar {}"); - break; - default: - scratch.add("public class Foo {"); - scratch.add("public final class Bar {}"); - break; - } - scratch.add("}"); - - Utils.createFile(srcFile, scratch); - Utils.compiler("-d", - outDir.getAbsolutePath(), - srcFile.getAbsolutePath()); - } - } - - static class TestCase2 extends TestCase { - private TestCase2(String directory) throws IOException { - super(directory); - } - - TestCase2() throws Exception { - this("case2"); - } - - @Override - void emitClassFiles() throws Exception { - emitClassFile(""); - emitClassFile("8"); - } - - /* - * Adds different variants of types and tries to invoke an - * interface or concrete method defined by them. - */ - void emitClassFile(String version) throws IOException { - - final File outDir = mkdir(version.isEmpty() - ? tcwd - : new File(versionsDir, version)); - - final File srcDir = mkdir(version.isEmpty() - ? new File(tcwd, "src") - : new File(new File(versionsDir, version), "src")); - - List scratch = new ArrayList<>(); - final String fname1 = "Ab"; - final File srcFile1 = new File(srcDir, fname1 + Utils.JAVA_FILE_EXT); - - final String fname2 = "AbNormal"; - final File srcFile2 = new File(srcDir, fname2 + Utils.JAVA_FILE_EXT); - switch (version) { - case "8": - scratch.clear(); - scratch.add("import java.io.IOException;"); - scratch.add("public interface " + fname1 + "{"); - scratch.add(" public abstract void close() throws IOException ;"); - scratch.add("}"); - Utils.createFile(srcFile1, scratch); - break; - default: - scratch.clear(); - scratch.add("import java.io.IOException;"); - scratch.add("public abstract class " + fname1 + "{"); - scratch.add(" public abstract void close() throws IOException ;"); - scratch.add("}"); - Utils.createFile(srcFile1, scratch); - } - - scratch.clear(); - scratch.add("import java.io.IOException;"); - scratch.add("public class " + fname2 + "{"); - scratch.add(" public void doSomething(Ab ab) throws IOException {"); - scratch.add(" ab.close();"); - scratch.add(" }"); - scratch.add("}"); - - Utils.createFile(srcFile2, scratch); - Utils.compiler("-d", - outDir.getAbsolutePath(), - srcFile1.getAbsolutePath(), - srcFile2.getAbsolutePath()); - } - } -} diff --git a/test/jdk/tools/pack200/Pack200Props.java b/test/jdk/tools/pack200/Pack200Props.java deleted file mode 100644 index 6dc24b2d225..00000000000 --- a/test/jdk/tools/pack200/Pack200Props.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6575373 6969063 - * @summary verify default properties of the packer/unpacker and segment limit - * @modules java.logging - * jdk.compiler - * jdk.zipfs - * @compile -XDignore.symbol.file Utils.java Pack200Props.java - * @run main Pack200Props - * @author ksrini - */ - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.jar.Pack200; -import java.util.jar.Pack200.Packer; -import java.util.logging.Logger; - -/* - * Run this against a large jar file, by default the packer should generate only - * one segment, parse the output of the packer to verify if this is indeed true. - */ - -public class Pack200Props { - - final static Logger log = Logger.getLogger("Pack200Props"); - - public static void main(String... args) throws Exception { - verifyDefaults(); - File out = new File("test" + Utils.PACK_FILE_EXT); - out.delete(); - verifySegmentLimit(out); - log.info("cleanup"); - Utils.cleanup(); - } - - static void verifySegmentLimit(File outFile) throws Exception { - log.info("creating jar"); - File testJar = Utils.createRtJar(); - - log.info("using pack200: " + Utils.getPack200Cmd()); - List cmdsList = new ArrayList<>(); - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add("-J-Xshare:off"); - cmdsList.add("-J-Xmx1280m"); - cmdsList.add("--effort=1"); - cmdsList.add("--verbose"); - cmdsList.add("--no-gzip"); - cmdsList.add(outFile.getName()); - cmdsList.add(testJar.getAbsolutePath()); - List outList = Utils.runExec(cmdsList); - - log.info("verifying"); - int count = 0; - for (String line : outList) { - System.out.println(line); - if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) { - count++; - } - } - log.info("fini"); - if (count == 0) { - throw new RuntimeException("no segments or no output ????"); - } else if (count > 1) { - throw new RuntimeException("multiple segments detected, expected 1"); - } - } - - private static void verifyDefaults() { - log.info("start"); - Map expectedDefaults = new HashMap<>(); - Packer p = Pack200.newPacker(); - expectedDefaults.put("com.sun.java.util.jar.pack.disable.native", - p.FALSE); - expectedDefaults.put("com.sun.java.util.jar.pack.verbose", "0"); - expectedDefaults.put(p.CLASS_ATTRIBUTE_PFX + "CompilationID", "RUH"); - expectedDefaults.put(p.CLASS_ATTRIBUTE_PFX + "SourceID", "RUH"); - expectedDefaults.put(p.CODE_ATTRIBUTE_PFX + "CharacterRangeTable", - "NH[PHPOHIIH]"); - expectedDefaults.put(p.CODE_ATTRIBUTE_PFX + "CoverageTable", - "NH[PHHII]"); - expectedDefaults.put(p.DEFLATE_HINT, p.KEEP); - expectedDefaults.put(p.EFFORT, "5"); - expectedDefaults.put(p.KEEP_FILE_ORDER, p.TRUE); - expectedDefaults.put(p.MODIFICATION_TIME, p.KEEP); - expectedDefaults.put(p.SEGMENT_LIMIT, "-1"); - expectedDefaults.put(p.UNKNOWN_ATTRIBUTE, p.PASS); - - Map props = p.properties(); - int errors = 0; - for (String key : expectedDefaults.keySet()) { - String def = expectedDefaults.get(key); - String x = props.get(key); - if (x == null) { - System.out.println("Error: key not found:" + key); - errors++; - } else { - if (!def.equals(x)) { - System.out.println("Error: key " + key - + "\n value expected: " + def - + "\n value obtained: " + x); - errors++; - } - } - } - log.info("fini"); - if (errors > 0) { - throw new RuntimeException(errors + - " error(s) encountered in default properties verification"); - } - } -} - diff --git a/test/jdk/tools/pack200/Pack200Test.java b/test/jdk/tools/pack200/Pack200Test.java deleted file mode 100644 index a259df19df2..00000000000 --- a/test/jdk/tools/pack200/Pack200Test.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - /* - * @test - * @bug 6521334 6712743 8007902 8151901 - * @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g) - * @summary test general packer/unpacker functionality - * using native and java unpackers - * @modules jdk.management - * jdk.zipfs - * @compile -XDignore.symbol.file Utils.java Pack200Test.java - * @run main/othervm/timeout=1200 -Xmx1280m -Xshare:off Pack200Test - */ - -import java.util.*; -import java.io.*; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryMXBean; -import java.util.jar.*; - -/** - * Tests the packing/unpacking via the APIs. - */ -public class Pack200Test { - - private static ArrayList jarList = new ArrayList(); - static final MemoryMXBean mmxbean = ManagementFactory.getMemoryMXBean(); - static final long m0 = getUsedMemory(); - static final int LEAK_TOLERANCE = 21000; // OS and GC related variations. - // enable leak checks only if required, GC charecteristics vary on - // platforms and this may not yield consistent results - static final boolean LEAK_CHECK = Boolean.getBoolean("Pack200Test.enableLeakCheck"); - - /** Creates a new instance of Pack200Test */ - private Pack200Test() {} - - static long getUsedMemory() { - mmxbean.gc(); - mmxbean.gc(); - mmxbean.gc(); - return mmxbean.getHeapMemoryUsage().getUsed()/1024; - } - - private static void leakCheck() throws Exception { - if (!LEAK_CHECK) - return; - long diff = getUsedMemory() - m0; - System.out.println(" Info: memory diff = " + diff + "K"); - if (diff > LEAK_TOLERANCE) { - throw new Exception("memory leak detected " + diff); - } - } - - private static void doPackUnpack() throws IOException { - for (File in : jarList) { - JarOutputStream javaUnpackerStream = null; - JarOutputStream nativeUnpackerStream = null; - JarFile jarFile = null; - try { - jarFile = new JarFile(in); - - // Write out to a jtreg scratch area - File packFile = new File(in.getName() + Utils.PACK_FILE_EXT); - - System.out.println("Packing [" + in.toString() + "]"); - // Call the packer - Utils.pack(jarFile, packFile); - System.out.println("Done Packing [" + in.toString() + "]"); - jarFile.close(); - System.out.println("Start leak check"); - leakCheck(); - - System.out.println(" Unpacking using java unpacker"); - File javaUnpackedJar = new File("java-" + in.getName()); - // Write out to current directory, jtreg will setup a scratch area - javaUnpackerStream = new JarOutputStream( - new FileOutputStream(javaUnpackedJar)); - Utils.unpackj(packFile, javaUnpackerStream); - javaUnpackerStream.close(); - System.out.println(" Testing...java unpacker"); - leakCheck(); - // Ok we have unpacked the file, lets test it. - Utils.doCompareVerify(in.getAbsoluteFile(), javaUnpackedJar); - - System.out.println(" Unpacking using native unpacker"); - // Write out to current directory - File nativeUnpackedJar = new File("native-" + in.getName()); - nativeUnpackerStream = new JarOutputStream( - new FileOutputStream(nativeUnpackedJar)); - Utils.unpackn(packFile, nativeUnpackerStream); - nativeUnpackerStream.close(); - System.out.println(" Testing...native unpacker"); - leakCheck(); - // the unpackers (native and java) should produce identical bits - // so we use use bit wise compare, the verification compare is - // very expensive wrt. time. - Utils.doCompareBitWise(javaUnpackedJar, nativeUnpackedJar); - System.out.println("Done."); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - Utils.close(nativeUnpackerStream); - Utils.close(javaUnpackerStream); - Utils.close((Closeable) jarFile); - } - } - Utils.cleanup(); // cleanup artifacts, if successful run - } - - /** - * @param args the command line arguments - */ - public static void main(String[] args) throws Exception { - // select the jars carefully, adding more jars will increase the - // testing time. - jarList.add(Utils.createRtJar()); - jarList.add(Utils.getGoldenJar()); - System.out.println(jarList); - doPackUnpack(); - } -} diff --git a/test/jdk/tools/pack200/PackChecksum.java b/test/jdk/tools/pack200/PackChecksum.java deleted file mode 100644 index a33c10f2902..00000000000 --- a/test/jdk/tools/pack200/PackChecksum.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; - -/* - * @test - * @bug 8000650 8150469 - * @summary unpack200.exe should check gzip crc - * @compile -XDignore.symbol.file Utils.java PackChecksum.java - * @run main PackChecksum - * @author kizune - */ -public class PackChecksum { - final int TRAILER_LEN = 8; - final List cmdsList = new ArrayList<>(); - static enum Case { - CRC32, - ISIZE, - BOTH; - - }; - public static void main(String... args) throws Exception { - new PackChecksum().run(); - } - void run() throws Exception { - testBrokenTrailer(Case.CRC32); // negative - testBrokenTrailer(Case.ISIZE); // negative - testBrokenTrailer(Case.BOTH); // negative - testMultipleSegments(); - } - - void testMultipleSegments() throws Exception { - File inputJar = new File("input.jar"); - Utils.copyFile(Utils.getGoldenJar(), inputJar); - cmdsList.clear(); - - File testPack = new File("out.jar.pack.gz"); - - cmdsList.clear(); - cmdsList.add(Utils.getPack200Cmd()); - // force multiple segments - cmdsList.add("--segment-limit=100"); - cmdsList.add(testPack.getName()); - cmdsList.add(inputJar.getName()); - Utils.runExec(cmdsList); - - File destFile = new File("dst.jar"); - cmdsList.clear(); - cmdsList.add(Utils.getUnpack200Cmd()); - cmdsList.add(testPack.getName()); - cmdsList.add(destFile.getName()); - try { - Utils.runExec(cmdsList); - if (!destFile.exists()) { - throw new Exception("file not created: " + destFile); - } - } finally { - if (inputJar.exists()) - inputJar.delete(); - if (testPack.exists()) - testPack.delete(); - if (destFile.exists()) - destFile.delete(); - } - } - - void testBrokenTrailer(Case type) throws Exception { - System.out.println("Testing: case " + type); - // Create a fresh .jar file - File testFile = new File("src_tools.jar"); - File testPack = new File("src_tools.pack.gz"); - generateJar(testFile); - - cmdsList.clear(); - // Create .pack file - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add(testPack.getName()); - cmdsList.add(testFile.getName()); - Utils.runExec(cmdsList); - - // mutate the checksum of the packed file - RandomAccessFile raf = new RandomAccessFile(testPack, "rw"); - - switch (type) { - case CRC32: - raf.seek(raf.length() - TRAILER_LEN); - raf.writeInt(0x0dea0a0d); - break; - case ISIZE: - raf.seek(raf.length() - (TRAILER_LEN/2)); - raf.writeInt(0x0b0e0e0f); - break; - default: - raf.seek(raf.length() - (TRAILER_LEN)); - raf.writeLong(0x0dea0a0d0b0e0e0fL); - break; - } - - raf.close(); - - File dstFile = new File("dst_tools.jar"); - if (dstFile.exists()) { - dstFile.delete(); - } - cmdsList.clear(); - cmdsList.add(Utils.getUnpack200Cmd()); - cmdsList.add(testPack.getName()); - cmdsList.add(dstFile.getName()); - - boolean processFailed = false; - try { - Utils.runExec(cmdsList); - } catch (RuntimeException re) { - // unpack200 should exit with non-zero exit code - processFailed = true; - } finally { - // tidy up - if (testFile.exists()) - testFile.delete(); - - if (testPack.exists()) - testPack.delete(); - - if (!processFailed) { - throw new Exception("case " + type + - ": file with incorrect CRC, unpacked without the error."); - } - if (dstFile.exists()) { - dstFile.delete(); - throw new Exception("case " + type + - ": file exists: " + dstFile); - } - } - } - - void generateJar(File result) throws IOException { - if (result.exists()) { - result.delete(); - } - - try (JarOutputStream output = new JarOutputStream(new FileOutputStream(result)); ) { - for (int i = 0 ; i < 100 ; i++) { - JarEntry e = new JarEntry("F-" + i + ".txt"); - output.putNextEntry(e); - } - output.flush(); - output.close(); - } - } - -} diff --git a/test/jdk/tools/pack200/PackTestZip64.java b/test/jdk/tools/pack200/PackTestZip64.java deleted file mode 100644 index d952549cc20..00000000000 --- a/test/jdk/tools/pack200/PackTestZip64.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.zip.ZipEntry; -/* - * @test - * @bug 8029646 - * @summary tests that native unpacker produces the same result as Java one - * @compile -XDignore.symbol.file Utils.java PackTestZip64.java - * @run main PackTestZip64 - * @author kizune - */ - -public class PackTestZip64 { - - private static final boolean bigJarEnabled - = Boolean.getBoolean("PackTestZip64.enableBigJar"); - - public static void main(String... args) throws Exception { - testPacking(); - Utils.cleanup(); - } - - // 1KB buffer is enough to copy jar content - private static final byte[] BUFFER = new byte[1024]; - - static void testPacking() throws IOException { - File testFile = new File("tools_java.jar"); - if (bigJarEnabled) { - // Add a large number of small files to the golden jar - generateLargeJar(testFile, Utils.getGoldenJar()); - } else { - // make a copy of the test specimen to local directory - Utils.copyFile(Utils.getGoldenJar(), testFile); - } - - List cmdsList = new ArrayList<>(); - - // Repack file to get the Java-based result - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add("--repack"); - cmdsList.add(testFile.getName()); - Utils.runExec(cmdsList); - cmdsList.clear(); - - // Pack file with pack200 and unpack in with unpack200 - File packedFile = new File("tools.pack.gz"); - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add(packedFile.getName()); - cmdsList.add(testFile.getName()); - Utils.runExec(cmdsList); - cmdsList.clear(); - - File unpackedFile = new File("tools_native.jar"); - cmdsList.add(Utils.getUnpack200Cmd()); - cmdsList.add(packedFile.getName()); - cmdsList.add(unpackedFile.getName()); - Utils.runExec(cmdsList); - - // Compare files binary - compareTwoFiles(testFile, unpackedFile); - - // Cleaning up generated files - testFile.delete(); - packedFile.delete(); - unpackedFile.delete(); - } - - static void compareTwoFiles(File src, File dst) throws IOException { - if (!src.exists()) { - throw new IOException("File " + src.getName() + " does not exist!"); - } - - if(!dst.exists()) { - throw new IOException("File " + dst.getName() + " does not exist!"); - } - - BufferedInputStream srcis, dstis; - srcis = new BufferedInputStream(new FileInputStream(src)); - dstis = new BufferedInputStream(new FileInputStream(dst)); - - int s = 0, d, pos = 0; - while (s != -1) { // Checking of just one result for EOF is enough - s = srcis.read(); - d = dstis.read(); - - if (s != d) { - throw new IOException("Files are differ starting at position: " - + Integer.toHexString(pos)); - } - - pos++; - } - - srcis.close(); - dstis.close(); - } - - static void generateLargeJar(File result, File source) throws IOException { - if (result.exists()) { - result.delete(); - } - - try (JarOutputStream copyTo = new JarOutputStream(new FileOutputStream(result)); - JarFile srcJar = new JarFile(source)) { - - for (JarEntry je : Collections.list(srcJar.entries())) { - copyTo.putNextEntry(je); - if (!je.isDirectory()) { - copyStream(srcJar.getInputStream(je), copyTo); - } - copyTo.closeEntry(); - } - - int many = Short.MAX_VALUE * 2 + 2; - - for (int i = 0 ; i < many ; i++) { - JarEntry e = new JarEntry("F-" + i + ".txt"); - copyTo.putNextEntry(e); - } - copyTo.flush(); - copyTo.close(); - } - } - - static void copyStream(InputStream in, OutputStream out) throws IOException { - int bytesRead; - while ((bytesRead = in.read(BUFFER))!= -1) { - out.write(BUFFER, 0, bytesRead); - } - } -} diff --git a/test/jdk/tools/pack200/PackTestZip64Manual.java b/test/jdk/tools/pack200/PackTestZip64Manual.java deleted file mode 100644 index 38e4101ac3b..00000000000 --- a/test/jdk/tools/pack200/PackTestZip64Manual.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8029646 - * @summary tests that native unpacker produces the same result as Java one - * @compile -XDignore.symbol.file Utils.java PackTestZip64.java - * @run main/manual/othervm -DPackTestZip64.enableBigJar=true PackTestZip64 - */ - -public class PackTestZip64Manual { -} diff --git a/test/jdk/tools/pack200/PackageVersionTest.java b/test/jdk/tools/pack200/PackageVersionTest.java deleted file mode 100644 index 4c4cac4ed77..00000000000 --- a/test/jdk/tools/pack200/PackageVersionTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6712743 6991164 7168401 - * @summary verify package versions - * @compile -XDignore.symbol.file Utils.java PackageVersionTest.java - * @run main PackageVersionTest - * @author ksrini - */ - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.jar.JarFile; -import java.util.jar.Pack200; -import java.util.jar.Pack200.Packer; -import java.util.jar.Pack200.Unpacker; - -public class PackageVersionTest { - private static final File javaHome = new File(System.getProperty("java.home")); - - public final static int JAVA5_PACKAGE_MAJOR_VERSION = 150; - public final static int JAVA5_PACKAGE_MINOR_VERSION = 7; - - public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160; - public final static int JAVA6_PACKAGE_MINOR_VERSION = 1; - - public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170; - public final static int JAVA7_PACKAGE_MINOR_VERSION = 1; - - public static void main(String... args) throws IOException { - File out = new File("test.pack"); - createClassFile("Test6"); - createClassFile("Test7"); - - verify6991164(); - - // a jar file devoid of indy classes must generate 160.1 package file - verifyPack("Test7.class", JAVA6_PACKAGE_MAJOR_VERSION, - JAVA6_PACKAGE_MINOR_VERSION); - - // test for resource file, ie. no class files - verifyPack("Test6.java", JAVA5_PACKAGE_MAJOR_VERSION, - JAVA5_PACKAGE_MINOR_VERSION); - Utils.cleanup(); - } - - static void verify6991164() { - Unpacker unpacker = Pack200.newUnpacker(); - String versionStr = unpacker.toString(); - String expected = "Pack200, Vendor: " + - System.getProperty("java.vendor") + ", Version: " + - JAVA7_PACKAGE_MAJOR_VERSION + "." + JAVA7_PACKAGE_MINOR_VERSION; - if (!versionStr.equals(expected)) { - System.out.println("Expected: " + expected); - System.out.println("Obtained: " + versionStr); - throw new RuntimeException("did not get expected string " + expected); - } - } - - static void createClassFile(String name) { - createJavaFile(name); - String target = name.substring(name.length() - 1); - String javacCmds[] = { - "-source", - "7", - "-target", - "7", - "-Xlint:-options", - name + ".java" - }; - Utils.compiler(javacCmds); - } - - static void createJavaFile(String name) { - PrintStream ps = null; - FileOutputStream fos = null; - File outputFile = new File(name + ".java"); - outputFile.delete(); - try { - fos = new FileOutputStream(outputFile); - ps = new PrintStream(fos); - ps.format("public class %s {}", name); - } catch (IOException ioe) { - throw new RuntimeException("creation of test file failed"); - } finally { - Utils.close(ps); - Utils.close(fos); - } - } - - static void verifyPack(String filename, int expected_major, int expected_minor) { - - File jarFileName = new File("test.jar"); - jarFileName.delete(); - String jargs[] = { - "cvf", - jarFileName.getName(), - filename - }; - Utils.jar(jargs); - JarFile jfin = null; - - try { - jfin = new JarFile(jarFileName); - Packer packer = Pack200.newPacker(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - packer.pack(jfin, baos); - baos.flush(); - baos.close(); - byte[] buf = baos.toByteArray(); - - int minor = buf[4] & 0x000000ff; - int major = buf[5] & 0x000000ff; - - if (major != expected_major || minor != expected_minor) { - String msg = - String.format("test fails: expected:%d.%d but got %d.%d\n", - expected_major, expected_minor, - major, minor); - throw new Error(msg); - } - - System.out.println(filename + ": OK"); - } catch (IOException ioe) { - throw new RuntimeException(ioe.getMessage()); - } finally { - Utils.close((Closeable) jfin); - } - } -} diff --git a/test/jdk/tools/pack200/RepackTest.java b/test/jdk/tools/pack200/RepackTest.java deleted file mode 100644 index f9d25660431..00000000000 --- a/test/jdk/tools/pack200/RepackTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -/* - * @test - * @bug 7184145 - * @summary tests repacking of a simple named jarfile. - * @compile -XDignore.symbol.file Utils.java RepackTest.java - * @run main RepackTest - * @author ksrini - */ -public class RepackTest { - - public static void main(String... args) throws Exception { - testRepack(); - Utils.cleanup(); - } - - /* - * there are two cases we need to test, where the file in question is - * orpaned, ie. without a parent ie. not qualified by a parent path - * relative nor absolute - * case 1: src and dest are the same - * case 2: src and dest are different - */ - static void testRepack() throws IOException { - - // make a copy of the test specimen to local directory - File testFile = new File("src_tools.jar"); - Utils.copyFile(Utils.getGoldenJar(), testFile); - List cmdsList = new ArrayList<>(); - - // case 1: - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add("--repack"); - cmdsList.add(testFile.getName()); - Utils.runExec(cmdsList); - - // case 2: - File dstFile = new File("dst_tools.jar"); - cmdsList.clear(); - cmdsList.add(Utils.getPack200Cmd()); - cmdsList.add("--repack"); - cmdsList.add(dstFile.getName()); - cmdsList.add(testFile.getName()); - Utils.runExec(cmdsList); - - // tidy up - testFile.delete(); - dstFile.delete(); - } -} diff --git a/test/jdk/tools/pack200/T7007157.java b/test/jdk/tools/pack200/T7007157.java deleted file mode 100644 index fa88b4c5fb4..00000000000 --- a/test/jdk/tools/pack200/T7007157.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Map; -import java.util.jar.JarFile; -import java.util.jar.Pack200; -/* - * @test - * @bug 7007157 - * @summary make sure the strip command works on an attribute - * @compile -XDignore.symbol.file Utils.java T7007157.java - * @run main T7007157 - * @author ksrini - */ -public class T7007157 { - - public static void main(String... args) throws IOException { - File sdkHome = Utils.JavaSDK; - File testJar = new File("test.jar"); - Utils.jar("cvf", testJar.getName(), Utils.TEST_CLS_DIR.getAbsolutePath()); - JarFile jarFile = new JarFile(testJar); - File packFile = new File("foo.pack"); - Pack200.Packer packer = Pack200.newPacker(); - Map p = packer.properties(); - // Take the time optimization vs. space - p.put(packer.EFFORT, "1"); // CAUTION: do not use 0. - // Make the memory consumption as effective as possible - p.put(packer.SEGMENT_LIMIT, "10000"); - // ignore all JAR deflation requests to save time - p.put(packer.DEFLATE_HINT, packer.FALSE); - // save the file ordering of the original JAR - p.put(packer.KEEP_FILE_ORDER, packer.TRUE); - // strip the StackMapTables - p.put(packer.CODE_ATTRIBUTE_PFX + "StackMapTable", packer.STRIP); - FileOutputStream fos = null; - try { - // Write out to a jtreg scratch area - fos = new FileOutputStream(packFile); - // Call the packer - packer.pack(jarFile, fos); - } finally { - Utils.close(fos); - Utils.close(jarFile); - } - Utils.cleanup(); - } -} diff --git a/test/jdk/tools/pack200/TestExceptions.java b/test/jdk/tools/pack200/TestExceptions.java deleted file mode 100644 index 5947180d636..00000000000 --- a/test/jdk/tools/pack200/TestExceptions.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; - -/* - * @test - * @bug 6985763 - * @summary verify that proper exceptions are thrown - * @compile -XDignore.symbol.file Utils.java TestExceptions.java - * @run main TestExceptions - * @author ksrini - */ - -public class TestExceptions { - - static final File testJar = new File("test.jar"); - static final File testPackFile = new File("test.pack"); - - static void init() { - Utils.jar("cvf", testJar.getAbsolutePath(), "."); - JarFile jf = null; - try { - jf = new JarFile(testJar); - Utils.pack(jf, testPackFile); - } catch (IOException ioe) { - throw new Error("Initialization error", ioe); - } finally { - Utils.close(jf); - } - } - - // a test that closes the input jarFile. - static void pack200Test1() { - PackTestInput ti = null; - // setup the scenario - try { - ti = new PackTestInput(new JarFile(testJar), new ByteArrayOutputStream()); - } catch (Exception e) { - throw new Error("Initialization error", e); - } finally { - Utils.close(ti.getJarFile()); - } - // test the scenario - try { - System.out.println(ti); - Pack200.Packer p = Pack200.newPacker(); - p.pack(ti.getJarFile(), ti.getOutputStream()); - } catch (Exception e) { - ti.checkException(e); - } finally { - if (ti != null) { - ti.close(); - } - } - } - - // test the Pack200.pack(JarFile, OutputStream); - static void pack200Test2() { - List tlist = new ArrayList(); - try { - // setup the test scenarios - try { - tlist.add(new PackTestInput((JarFile)null, null)); - tlist.add(new PackTestInput(new JarFile(testJar), null)); - tlist.add(new PackTestInput((JarFile)null, new ByteArrayOutputStream())); - } catch (Exception e) { - throw new Error("Initialization error", e); - } - - // test the scenarios - for (PackTestInput ti : tlist) { - System.out.println(ti); - try { - Pack200.Packer p = Pack200.newPacker(); - p.pack(ti.getJarFile(), ti.getOutputStream()); - } catch (Exception e) { - ti.checkException(e); - } - } - } finally { // clean up - for (TestInput ti : tlist) { - if (ti != null) { - ti.close(); - } - } - } - } - - // test the Pack200.pack(JarInputStream, OutputStream); - static void pack200Test3() { - List tlist = new ArrayList(); - try { - // setup the test scenarios - try { - tlist.add(new PackTestJarInputStream((JarInputStream)null, null)); - tlist.add(new PackTestJarInputStream((JarInputStream)null, - new ByteArrayOutputStream())); - tlist.add(new PackTestJarInputStream( - new JarInputStream(new FileInputStream(testJar)), null)); - - } catch (Exception e) { - throw new Error("Initialization error", e); - } - for (PackTestJarInputStream ti : tlist) { - System.out.println(ti); - try { - Pack200.Packer p = Pack200.newPacker(); - p.pack(ti.getJarInputStream(), ti.getOutputStream()); - } catch (Exception e) { - ti.checkException(e); - } - } - } finally { // clean up - for (PackTestJarInputStream ti : tlist) { - if (ti != null) { - ti.close(); - } - } - } - } - - // test the Pack200.unpack(InputStream, OutputStream); - static void unpack200Test1() { - List tlist = new ArrayList(); - try { - // setup the test scenarios - try { - tlist.add(new UnpackTestInput((InputStream)null, null)); - tlist.add(new UnpackTestInput(new FileInputStream(testPackFile), - null)); - tlist.add(new UnpackTestInput((InputStream) null, - new JarOutputStream(new ByteArrayOutputStream()))); - } catch (Exception e) { - throw new Error("Initialization error", e); - } - - // test the scenarios - for (UnpackTestInput ti : tlist) { - System.out.println(ti); - try { - Pack200.Unpacker unpacker = Pack200.newUnpacker(); - unpacker.unpack(ti.getInputStream(), ti.getJarOutputStream()); - } catch (Exception e) { - ti.checkException(e); - } - } - } finally { // clean up - for (TestInput ti : tlist) { - if (ti != null) { - ti.close(); - } - } - } - } - - // test the Pack200.unpack(File, OutputStream); - static void unpack200Test2() { - List tlist = new ArrayList(); - try { - // setup the test scenarios - try { - tlist.add(new UnpackTestFileInput((File)null, null)); - tlist.add(new UnpackTestFileInput(testPackFile, null)); - tlist.add(new UnpackTestFileInput((File)null, - new JarOutputStream(new ByteArrayOutputStream()))); - } catch (Exception e) { - throw new Error("Initialization error", e); - } - - // test the scenarios - for (UnpackTestFileInput ti : tlist) { - System.out.println(ti); - try { - Pack200.Unpacker unpacker = Pack200.newUnpacker(); - unpacker.unpack(ti.getInputFile(), ti.getJarOutputStream()); - } catch (Exception e) { - ti.checkException(e); - } - } - } finally { // clean up - for (TestInput ti : tlist) { - if (ti != null) { - ti.close(); - } - } - } - } - - public static void main(String... args) throws IOException { - init(); - pack200Test1(); - pack200Test2(); - pack200Test3(); - unpack200Test1(); - Utils.cleanup(); - } - - // containers for test inputs and management - static abstract class TestInput { - - private final Object in; - private final Object out; - final boolean shouldNPE; - final String testname; - - public TestInput(String name, Object in, Object out) { - this.testname = name; - this.in = in; - this.out = out; - shouldNPE = (in == null || out == null); - } - - @Override - public String toString() { - StringBuilder outStr = new StringBuilder(testname); - outStr.append(", input:").append(in); - outStr.append(", output:").append(this.out); - outStr.append(", should NPE:").append(shouldNPE); - return outStr.toString(); - } - - void close() { - if (in != null && (in instanceof Closeable)) { - Utils.close((Closeable) in); - } - if (out != null && (out instanceof Closeable)) { - Utils.close((Closeable) out); - } - } - - void checkException(Throwable t) { - if (shouldNPE) { - if (t instanceof NullPointerException) { - System.out.println("Got expected exception"); - return; - } else { - throw new RuntimeException("Expected NPE, but got ", t); - } - } - if (t instanceof IOException) { - System.out.println("Got expected exception"); - return; - } else { - throw new RuntimeException("Expected IOException but got ", t); - } - } - } - - static class PackTestInput extends TestInput { - - public PackTestInput(JarFile jf, OutputStream out) { - super("PackTestInput", jf, out); - } - - JarFile getJarFile() { - return (JarFile) super.in; - } - - OutputStream getOutputStream() { - return (OutputStream) super.out; - } - }; - - static class PackTestJarInputStream extends TestInput { - - public PackTestJarInputStream(JarInputStream in, OutputStream out) { - super("PackTestJarInputStream", in, out); - } - - JarInputStream getJarInputStream() { - return (JarInputStream) super.in; - } - - OutputStream getOutputStream() { - return (OutputStream) super.out; - } - }; - - static class UnpackTestInput extends TestInput { - - public UnpackTestInput(InputStream in, JarOutputStream out) { - super("UnpackTestInput", in, out); - } - - InputStream getInputStream() { - return (InputStream) super.in; - } - - JarOutputStream getJarOutputStream() { - return (JarOutputStream) super.out; - } - }; - - static class UnpackTestFileInput extends TestInput { - - public UnpackTestFileInput(File in, JarOutputStream out) { - super("UnpackTestInput", in, out); - } - - File getInputFile() { - return (File) super.in; - } - - JarOutputStream getJarOutputStream() { - return (JarOutputStream) super.out; - } - }; -} diff --git a/test/jdk/tools/pack200/TestNormal.java b/test/jdk/tools/pack200/TestNormal.java deleted file mode 100644 index a85a9d4040f..00000000000 --- a/test/jdk/tools/pack200/TestNormal.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @run main/timeout=600 TestNormal - * @bug 8020802 8156807 - * @summary Need an ability to create jar files that are invariant to the pack200 packing/unpacking - * @author Alexander Zuev - */ - -import java.io.*; - -public class TestNormal { - private static String FS = File.separator; - - public static void main(String args[]) throws Exception { - String testdir = Utils.TEST_CLS_DIR.getAbsolutePath(); - - try { - String jarCmd = Utils.getJarCmd(); - String packCmd = Utils.getPack200Cmd(); - - // create the original jar - Utils.runExec(jarCmd, "cf", "original.jar", "-C", testdir, "."); - - // create the reference jar - Utils.runExec(packCmd, "-r", "repacked.jar", "original.jar"); - - // create the normalized jar using jar(1) - Utils.runExec(jarCmd, "cnf", "normalized.jar", "-C", testdir, "."); - - // compare archive contents bit wise, these should be identical! - Utils.doCompareBitWise(new File("repacked.jar"), - new File("normalized.jar")); - } finally { - Utils.cleanup(); - } - } -} diff --git a/test/jdk/tools/pack200/TimeStamp.java b/test/jdk/tools/pack200/TimeStamp.java deleted file mode 100644 index fc16dd06a6b..00000000000 --- a/test/jdk/tools/pack200/TimeStamp.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.TimeZone; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; - -/* - * @test - * @bug 6966740 - * @summary verify identical timestamps, unpacked in any timezone - * @compile -XDignore.symbol.file Utils.java TimeStamp.java - * @run main/othervm TimeStamp - * @author ksrini - */ - -/** - * First we pack the file in some time zone say India, then we unpack the file - * in the current time zone, and ensure the timestamp recorded in the unpacked - * jar are the same. - */ -public class TimeStamp { - static final TimeZone tz = TimeZone.getDefault(); - - - public static void main(String... args) throws IOException { - - // make a local copy of our test file - File srcFile = Utils.getGoldenJar(); - File goldenFile = new File("golden.jar"); - Utils.copyFile(srcFile, goldenFile); - - JarFile goldenJarFile = new JarFile(goldenFile); - File packFile = new File("golden.pack"); - - // set the test timezone and pack the file - TimeZone.setDefault(TimeZone.getTimeZone("IST")); - Utils.pack(goldenJarFile, packFile); - TimeZone.setDefault(tz); // reset the timezone - - // unpack in the test timezone - File istFile = new File("golden.jar.java.IST"); - unpackJava(packFile, istFile); - verifyJar(goldenFile, istFile); - istFile.delete(); - - // unpack in some other timezone - File pstFile = new File("golden.jar.java.PST"); - unpackJava(packFile, pstFile); - verifyJar(goldenFile, pstFile); - pstFile.delete(); - - // repeat the test for unpack200 tool. - istFile = new File("golden.jar.native.IST"); - unpackNative(packFile, istFile); - verifyJar(goldenFile, istFile); - istFile.delete(); - - pstFile = new File("golden.jar.native.PST"); - unpackNative(packFile, pstFile); - verifyJar(goldenFile, pstFile); - pstFile.delete(); - Utils.cleanup(); - } - - static void unpackNative(File packFile, File outFile) { - String name = outFile.getName(); - String tzname = name.substring(name.lastIndexOf(".") + 1); - HashMap env = new HashMap<>(); - switch(tzname) { - case "PST": - env.put("TZ", "US/Pacific"); - break; - case "IST": - env.put("TZ", "Asia/Calcutta"); - break; - default: - throw new RuntimeException("not implemented: " + tzname); - } - List cmdsList = new ArrayList<>(); - cmdsList.add(Utils.getUnpack200Cmd()); - cmdsList.add(packFile.getName()); - cmdsList.add(outFile.getName()); - Utils.runExec(cmdsList, env); - } - - static void unpackJava(File packFile, File outFile) throws IOException { - String name = outFile.getName(); - String tzname = name.substring(name.lastIndexOf(".") + 1); - JarOutputStream jos = null; - try { - TimeZone.setDefault(TimeZone.getTimeZone(tzname)); - jos = new JarOutputStream(new FileOutputStream(outFile)); - System.out.println("Using timezone: " + TimeZone.getDefault()); - Utils.unpackj(packFile, jos); - } finally { - Utils.close(jos); - TimeZone.setDefault(tz); // always reset - } - } - - static void verifyJar(File f1, File f2) throws IOException { - int errors = 0; - JarFile jf1 = null; - JarFile jf2 = null; - try { - jf1 = new JarFile(f1); - jf2 = new JarFile(f2); - System.out.println("Verifying: " + f1 + " and " + f2); - for (JarEntry je1 : Collections.list(jf1.entries())) { - JarEntry je2 = jf2.getJarEntry(je1.getName()); - if (je1.getTime() != je2.getTime()) { - System.out.println("Error:"); - System.out.println(" expected:" + jf1.getName() + ":" - + je1.getName() + ":" + je1.getTime()); - System.out.println(" obtained:" + jf2.getName() + ":" - + je2.getName() + ":" + je2.getTime()); - errors++; - } - } - } finally { - Utils.close(jf1); - Utils.close(jf2); - } - if (errors > 0) { - throw new RuntimeException("FAIL:" + errors + " error(s) encounted"); - } - } -} diff --git a/test/jdk/tools/pack200/UnpackerMemoryTest.java b/test/jdk/tools/pack200/UnpackerMemoryTest.java deleted file mode 100644 index ec8ffb6a402..00000000000 --- a/test/jdk/tools/pack200/UnpackerMemoryTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6531345 - * @summary check for unpacker memory leaks - * @compile -XDignore.symbol.file Utils.java UnpackerMemoryTest.java - * @run main/othervm/timeout=1200 -Xmx32m UnpackerMemoryTest - * @author ksrini - */ - -import java.io.File; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.io.IOException; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; - -public class UnpackerMemoryTest { - - private static void createPackFile(File packFile) throws IOException { - File tFile = new File("test.dat"); - FileOutputStream fos = null; - PrintStream ps = null; - String jarFileName = Utils.baseName(packFile, Utils.PACK_FILE_EXT) - + Utils.JAR_FILE_EXT; - JarFile jarFile = null; - try { - fos = new FileOutputStream(tFile); - ps = new PrintStream(fos); - ps.println("A quick brown fox"); - Utils.jar("cvf", jarFileName, tFile.getName()); - jarFile = new JarFile(jarFileName); - Utils.pack(jarFile, packFile); - } finally { - Utils.close(ps); - tFile.delete(); - Utils.close(jarFile); - } - } - - public static void main(String[] args) throws Exception { - String name = "foo"; - File packFile = new File(name + Utils.PACK_FILE_EXT); - createPackFile(packFile); - if (!packFile.exists()) { - throw new RuntimeException(packFile + " not found"); - } - File jarOut = new File(name + ".out"); - for (int i = 0; i < 2000; i++) { - JarOutputStream jarOS = null; - FileOutputStream fos = null; - try { - fos = new FileOutputStream(jarOut); - jarOS = new JarOutputStream(fos); - System.out.println("Unpacking[" + i + "]" + packFile); - Utils.unpackn(packFile, jarOS); - } finally { - Utils.close(jarOS); - Utils.close(fos); - } - } - Utils.cleanup(); - } -} - diff --git a/test/jdk/tools/pack200/Utils.java b/test/jdk/tools/pack200/Utils.java deleted file mode 100644 index 0ae4766ed90..00000000000 --- a/test/jdk/tools/pack200/Utils.java +++ /dev/null @@ -1,670 +0,0 @@ -/* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.nio.file.Path; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileFilter; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.net.URI; -import java.nio.charset.Charset; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import static java.nio.file.StandardCopyOption.*; -import static java.nio.file.StandardOpenOption.*; - - -/** - * - * @author ksrini - */ - -/* - * This class contains the commonly used utilities. - */ -class Utils { - static final String JavaHome = System.getProperty("test.java", - System.getProperty("java.home")); - static final boolean IsWindows = - System.getProperty("os.name").startsWith("Windows"); - static final boolean Is64Bit = - System.getProperty("sun.arch.data.model", "32").equals("64"); - static final File JavaSDK = new File(JavaHome); - - static final String PACK_FILE_EXT = ".pack"; - static final String JAVA_FILE_EXT = ".java"; - static final String CLASS_FILE_EXT = ".class"; - static final String JAR_FILE_EXT = ".jar"; - - static final File TEST_SRC_DIR = new File(System.getProperty("test.src")); - static final File TEST_CLS_DIR = new File(System.getProperty("test.classes")); - static final String VERIFIER_DIR_NAME = "pack200-verifier"; - static final File VerifierJar = new File(VERIFIER_DIR_NAME + JAR_FILE_EXT); - static final File XCLASSES = new File("xclasses"); - - private Utils() {} // all static - - private static void init() throws IOException { - if (VerifierJar.exists()) { - return; - } - File srcDir = new File(getVerifierDir(), "src"); - List javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT)); - File tmpFile = File.createTempFile("javac", ".tmp", new File(".")); - XCLASSES.mkdirs(); - FileOutputStream fos = null; - PrintStream ps = null; - try { - fos = new FileOutputStream(tmpFile); - ps = new PrintStream(fos); - for (File f : javaFileList) { - ps.println(f.getAbsolutePath()); - } - } finally { - close(ps); - close(fos); - } - - compiler("-d", - XCLASSES.getName(), - "--add-modules=jdk.jdeps", - "--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED", - "@" + tmpFile.getAbsolutePath()); - - jar("cvfe", - VerifierJar.getName(), - "sun.tools.pack.verify.Main", - "-C", - XCLASSES.getName(), - "."); - } - - private static File getVerifierDir() { - File srcDir = new File(TEST_SRC_DIR, VERIFIER_DIR_NAME); - if (!srcDir.exists()) { - // if not available try one level above - srcDir = new File(TEST_SRC_DIR.getParentFile(), VERIFIER_DIR_NAME); - } - return srcDir; - } - - static File getGoldenJar() { - return new File(new File(getVerifierDir(), "data"), "golden.jar"); - } - static void dirlist(File dir) { - File[] files = dir.listFiles(); - System.out.println("--listing " + dir.getAbsolutePath() + "---"); - for (File f : files) { - StringBuffer sb = new StringBuffer(); - sb.append(f.isDirectory() ? "d " : "- "); - sb.append(f.getName()); - System.out.println(sb); - } - } - static void doCompareVerify(File reference, File specimen) throws IOException { - init(); - List cmds = new ArrayList(); - cmds.add(getJavaCmd()); - cmds.add("--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED"); - cmds.add("-cp"); - cmds.add(VerifierJar.getName()); - cmds.add("sun.tools.pack.verify.Main"); - cmds.add(reference.getAbsolutePath()); - cmds.add(specimen.getAbsolutePath()); - cmds.add("-O"); - runExec(cmds); - } - - static void doCompareBitWise(File reference, File specimen) - throws IOException { - init(); - List cmds = new ArrayList(); - cmds.add(getJavaCmd()); - cmds.add("-cp"); - cmds.add(VerifierJar.getName()); - cmds.add("sun.tools.pack.verify.Main"); - cmds.add(reference.getName()); - cmds.add(specimen.getName()); - cmds.add("-O"); - cmds.add("-b"); - runExec(cmds); - } - - static FileFilter createFilter(final String extension) { - return new FileFilter() { - @Override - public boolean accept(File pathname) { - String name = pathname.getName(); - if (name.endsWith(extension)) { - return true; - } - return false; - } - }; - } - - /* - * clean up all the usual suspects - */ - static void cleanup() throws IOException { - recursiveDelete(XCLASSES); - List toDelete = new ArrayList<>(); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".out"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".bak"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".jar"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".pack"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".bnd"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".txt"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".idx"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".gidx"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".tmp"))); - toDelete.addAll(Utils.findFiles(new File("."), - Utils.createFilter(".class"))); - for (File f : toDelete) { - f.delete(); - } - } - - static final FileFilter DIR_FILTER = new FileFilter() { - public boolean accept(File pathname) { - if (pathname.isDirectory()) { - return true; - } - return false; - } - }; - - static final FileFilter FILE_FILTER = new FileFilter() { - public boolean accept(File pathname) { - if (pathname.isFile()) { - return true; - } - return false; - } - }; - - static void copyFile(File src, File dst) throws IOException { - Path parent = dst.toPath().getParent(); - if (parent != null) { - Files.createDirectories(parent); - } - Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING); - if (dst.isDirectory() && !dst.canWrite()) { - dst.setWritable(true); - } - } - - static String baseName(File file, String extension) { - return baseName(file.getAbsolutePath(), extension); - } - - static String baseName(String name, String extension) { - int cut = name.length() - extension.length(); - return name.lastIndexOf(extension) == cut - ? name.substring(0, cut) - : name; - - } - static void createFile(File outFile, List content) throws IOException { - Files.write(outFile.getAbsoluteFile().toPath(), content, - Charset.defaultCharset(), CREATE_NEW, TRUNCATE_EXISTING); - } - - /* - * Suppose a path is provided which consists of a full path - * this method returns the sub path for a full path ex: /foo/bar/baz/foobar.z - * and the base path is /foo/bar it will will return baz/foobar.z. - */ - private static String getEntryPath(String basePath, String fullPath) { - if (!fullPath.startsWith(basePath)) { - return null; - } - return fullPath.substring(basePath.length()); - } - - static String getEntryPath(File basePathFile, File fullPathFile) { - return getEntryPath(basePathFile.toString(), fullPathFile.toString()); - } - - public static void recursiveCopy(File src, File dest) throws IOException { - if (!src.exists() || !src.canRead()) { - throw new IOException("file not found or readable: " + src); - } - if (dest.exists() && !dest.isDirectory() && !dest.canWrite()) { - throw new IOException("file not found or writeable: " + dest); - } - if (!dest.exists()) { - dest.mkdirs(); - } - List a = directoryList(src); - for (File f : a) { - copyFile(f, new File(dest, getEntryPath(src, f))); - } - } - - static List directoryList(File dirname) { - List dirList = new ArrayList(); - return directoryList(dirname, dirList, null); - } - - private static List directoryList(File dirname, List dirList, - File[] dirs) { - dirList.addAll(Arrays.asList(dirname.listFiles(FILE_FILTER))); - dirs = dirname.listFiles(DIR_FILTER); - for (File f : dirs) { - if (f.isDirectory() && !f.equals(dirname)) { - dirList.add(f); - directoryList(f, dirList, dirs); - } - } - return dirList; - } - - static void recursiveDelete(File dir) throws IOException { - if (dir.isFile()) { - dir.delete(); - } else if (dir.isDirectory()) { - File[] entries = dir.listFiles(); - for (int i = 0; i < entries.length; i++) { - if (entries[i].isDirectory()) { - recursiveDelete(entries[i]); - } - entries[i].delete(); - } - dir.delete(); - } - } - - static List findFiles(File startDir, FileFilter filter) - throws IOException { - List list = new ArrayList(); - findFiles0(startDir, list, filter); - return list; - } - /* - * finds files in the start directory using the the filter, appends - * the files to the dirList. - */ - private static void findFiles0(File startDir, List list, - FileFilter filter) throws IOException { - File[] foundFiles = startDir.listFiles(filter); - if (foundFiles == null) { - return; - } - list.addAll(Arrays.asList(foundFiles)); - File[] dirs = startDir.listFiles(DIR_FILTER); - for (File dir : dirs) { - findFiles0(dir, list, filter); - } - } - - static void close(Closeable c) { - if (c == null) { - return; - } - try { - c.close(); - } catch (IOException ignore) { - } - } - - static void compiler(String... javacCmds) { - List cmdList = new ArrayList<>(); - cmdList.add(getJavacCmd()); - for (String x : javacCmds) { - cmdList.add(x); - } - runExec(cmdList); - } - - static void jar(String... jargs) { - List cmdList = new ArrayList<>(); - cmdList.add(getJarCmd()); - for (String x : jargs) { - cmdList.add(x); - } - runExec(cmdList); - } - - static void testWithRepack(File inFile, String... repackOpts) throws IOException { - File cwd = new File("."); - // pack using --repack in native mode - File nativejarFile = new File(cwd, "out-n" + Utils.JAR_FILE_EXT); - repack(inFile, nativejarFile, false, repackOpts); - doCompareVerify(inFile, nativejarFile); - - // ensure bit compatibility between the unpacker variants - File javajarFile = new File(cwd, "out-j" + Utils.JAR_FILE_EXT); - repack(inFile, javajarFile, true, repackOpts); - doCompareBitWise(javajarFile, nativejarFile); - } - - static List repack(File inFile, File outFile, - boolean disableNative, String... extraOpts) { - List cmdList = new ArrayList<>(); - cmdList.clear(); - cmdList.add(Utils.getJavaCmd()); - cmdList.add("-ea"); - cmdList.add("-esa"); - if (disableNative) { - cmdList.add("-Dcom.sun.java.util.jar.pack.disable.native=true"); - } - cmdList.add("com.sun.java.util.jar.pack.Driver"); - cmdList.add("--repack"); - if (extraOpts != null) { - for (String opt: extraOpts) { - cmdList.add(opt); - } - } - cmdList.add(outFile.getName()); - cmdList.add(inFile.getName()); - return Utils.runExec(cmdList); - } - - // given a jar file foo.jar will write to foo.pack - static void pack(JarFile jarFile, File packFile) throws IOException { - Pack200.Packer packer = Pack200.newPacker(); - Map p = packer.properties(); - // Take the time optimization vs. space - p.put(packer.EFFORT, "1"); // CAUTION: do not use 0. - // Make the memory consumption as effective as possible - p.put(packer.SEGMENT_LIMIT, "10000"); - // ignore all JAR deflation requests to save time - p.put(packer.DEFLATE_HINT, packer.FALSE); - // save the file ordering of the original JAR - p.put(packer.KEEP_FILE_ORDER, packer.TRUE); - FileOutputStream fos = null; - try { - // Write out to a jtreg scratch area - fos = new FileOutputStream(packFile); - // Call the packer - packer.pack(jarFile, fos); - } finally { - close(fos); - } - } - - // uses java unpacker, slow but useful to discover issues with the packer - static void unpackj(File inFile, JarOutputStream jarStream) - throws IOException { - unpack0(inFile, jarStream, true); - - } - - // uses native unpacker using the java APIs - static void unpackn(File inFile, JarOutputStream jarStream) - throws IOException { - unpack0(inFile, jarStream, false); - } - - // given a packed file, create the jar file in the current directory. - private static void unpack0(File inFile, JarOutputStream jarStream, - boolean useJavaUnpack) throws IOException { - // Unpack the files - Pack200.Unpacker unpacker = Pack200.newUnpacker(); - Map props = unpacker.properties(); - if (useJavaUnpack) { - props.put("com.sun.java.util.jar.pack.disable.native", "true"); - } - // Call the unpacker - unpacker.unpack(inFile, jarStream); - } - - static byte[] getBuffer(ZipFile zf, ZipEntry ze) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte buf[] = new byte[8192]; - InputStream is = null; - try { - is = zf.getInputStream(ze); - int n = is.read(buf); - while (n > 0) { - baos.write(buf, 0, n); - n = is.read(buf); - } - return baos.toByteArray(); - } finally { - close(is); - } - } - - static ArrayList getZipFileEntryNames(ZipFile z) { - ArrayList out = new ArrayList(); - for (ZipEntry ze : Collections.list(z.entries())) { - out.add(ze.getName()); - } - return out; - } - - static List runExec(String... cmds) { - return runExec(Arrays.asList(cmds)); - } - - static List runExec(List cmdsList) { - return runExec(cmdsList, null); - } - - static List runExec(List cmdsList, Map penv) { - return runExec(cmdsList, penv, false); - } - - static List runExec(List cmdsList, Map penv, boolean ignoreReturnValue) { - ArrayList alist = new ArrayList(); - ProcessBuilder pb = - new ProcessBuilder(cmdsList); - Map env = pb.environment(); - if (penv != null && !penv.isEmpty()) { - env.putAll(penv); - } - pb.directory(new File(".")); - dirlist(new File(".")); - for (String x : cmdsList) { - System.out.print(x + " "); - } - System.out.println(""); - int retval = 0; - Process p = null; - InputStreamReader ir = null; - BufferedReader rd = null; - InputStream is = null; - try { - pb.redirectErrorStream(true); - p = pb.start(); - is = p.getInputStream(); - ir = new InputStreamReader(is); - rd = new BufferedReader(ir, 8192); - - String in = rd.readLine(); - while (in != null) { - alist.add(in); - System.out.println(in); - in = rd.readLine(); - } - retval = p.waitFor(); - if (!ignoreReturnValue && retval != 0) { - throw new RuntimeException("process failed with non-zero exit"); - } - } catch (Exception ex) { - throw new RuntimeException(ex.getMessage()); - } finally { - close(rd); - close(ir); - close(is); - if (p != null) { - p.destroy(); - } - } - return alist; - } - - static String getUnpack200Cmd() { - return getAjavaCmd("unpack200"); - } - - static String getPack200Cmd() { - return getAjavaCmd("pack200"); - } - - static String getJavaCmd() { - return getAjavaCmd("java"); - } - - static String getJavacCmd() { - return getAjavaCmd("javac"); - } - - static String getJarCmd() { - return getAjavaCmd("jar"); - } - - static String getAjavaCmd(String cmdStr) { - File binDir = new File(JavaHome, "bin"); - File unpack200File = IsWindows - ? new File(binDir, cmdStr + ".exe") - : new File(binDir, cmdStr); - - String cmd = unpack200File.getAbsolutePath(); - if (!unpack200File.canExecute()) { - throw new RuntimeException("please check" + - cmd + " exists and is executable"); - } - return cmd; - } - - // used to get all classes - static File createRtJar() throws Exception { - File rtJar = new File("rt.jar"); - new JrtToZip(".*\\.class", rtJar).run(); - return rtJar; - } - - // used to select the contents - static File createRtJar(String pattern) throws Exception { - File rtJar = new File("rt.jar"); - new JrtToZip(pattern, rtJar).run(); - return rtJar; - } - - /* - * A helper class to create a pseudo rt.jar. - */ - static class JrtToZip { - - final File outFile; - final Pattern pattern; - - public static void main(String[] args) throws Exception { - new JrtToZip(args[0], new File(args[1])).run(); - } - - JrtToZip(String pattern, File outFile) throws Exception { - this.pattern = Pattern.compile(pattern); - this.outFile = outFile; - } - - void run() throws Exception { - URI uri = URI.create("jar:" + outFile.toURI()); - Map env = new HashMap<>(); - env.put("create", "true"); - try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { - toZipfs(zipfs); - } - } - - void toZipfs(FileSystem zipfs) throws Exception { - FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); - for (Path root : jrtfs.getRootDirectories()) { - Files.walkFileTree(root, new FileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, - BasicFileAttributes attrs) throws IOException { - // ignore unneeded directory - if (dir.startsWith("/packages")) - return FileVisitResult.SKIP_SUBTREE; - - // pre-create required directories - Path zpath = zipfs.getPath(dir.toString()); - Files.createDirectories(zpath); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, - BasicFileAttributes attrs) throws IOException { - Matcher matcher = pattern.matcher(file.toString()); - if (matcher.matches()) { - // System.out.println("x: " + file); - Path zpath = zipfs.getPath(file.toString()); - Files.copy(file, zpath, REPLACE_EXISTING); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, - IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, - IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - }); - } - } - } -} diff --git a/test/jdk/tools/pack200/badattr.jar b/test/jdk/tools/pack200/badattr.jar deleted file mode 100644 index 330be6147c1da7b15da65df3eb331da064fc39f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1493 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⪚Z)<_>5&5?h_!e?nmJ`&!2Fu|8%MIsX|#%E=V*lz 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

    w$VJePo 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

    3Q;_*uaOSjbfUSoH{;QjRB-_&=EtRMZqf_TEe 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 z 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java b/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java deleted file mode 100644 index 63a66f765d6..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/ClassCompare.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package sun.tools.pack.verify; - -import java.io.*; -import java.util.*; -import java.util.jar.*; -import xmlkit.*; - -public class ClassCompare { - - /* - * @author ksrini - */ - private static XMLKit.Element getXMLelement(InputStream is, - boolean ignoreUnkAttrs, - List ignoreElements) throws IOException { - - ClassReader cr = new ClassReader(); - cr.keepOrder = false; - XMLKit.Element e = cr.readFrom(is); - - if (ignoreElements != null) { - XMLKit.Filter filter = XMLKit.elementFilter(ignoreElements); - e.removeAllInTree(filter); - } - - if (ignoreUnkAttrs == true) { - // This removes any unknown attributes - e.removeAllInTree(XMLKit.elementFilter("Attribute")); - } - return e; - } - - private static String getXMLPrettyString(XMLKit.Element e) throws IOException { - StringWriter out = new StringWriter(); - e.writePrettyTo(out); - return out.toString(); - } - - private static boolean compareClass0(JarFile jf1, JarFile jf2, - JarEntry je, boolean ignoreUnkAttrs, - List ignoreElements) - throws IOException { - - InputStream is1 = jf1.getInputStream(je); - InputStream is2 = jf2.getInputStream(je); - - // First we try to compare the bits if they are the same - boolean bCompare = JarFileCompare.compareStreams(is1, is2); - - // If they are the same there is nothing more to do. - if (bCompare) { - Globals.println("+++" + je.getName() + "+++\t" - + "b/b:PASS"); - return bCompare; - } - is1.close(); - is2.close(); - - is1 = jf1.getInputStream(je); - is2 = jf2.getInputStream(je); - - - XMLKit.Element e1 = getXMLelement(is1, ignoreUnkAttrs, ignoreElements); - XMLKit.Element e2 = getXMLelement(is2, ignoreUnkAttrs, ignoreElements); - - Globals.print("+++" + je.getName() + "+++\t" - + e1.size() + "/" + e1.size() + ":"); - - boolean result = true; - - if (e1.equals(e2)) { - Globals.println("PASS"); - } else { - Globals.println("FAIL"); - Globals.log("Strings differs"); - Globals.log(getXMLPrettyString(e1)); - Globals.log("----------"); - Globals.log(getXMLPrettyString(e2)); - result = false; - } - return result; - } - - /* - * Given two Class Paths could be jars the first being a reference - * will execute a series of comparisons on the classname specified - * The className could be null in which case it will iterate through - * all the classes, otherwise it will compare one class and exit. - */ - public static boolean compareClass(String jar1, String jar2, - String className, boolean ignoreUnkAttrs, - List ignoreElements) - throws IOException { - - Globals.println("Unknown attributes ignored:" + ignoreUnkAttrs); - if (ignoreElements != null) { - Globals.println(ignoreElements.toString()); - } - - JarFile jf1 = new JarFile(jar1); - JarFile jf2 = new JarFile(jar2); - - boolean result = true; - - if (className == null) { - for (JarEntry je1 : Collections.list((Enumeration) jf1.entries())) { - if (je1.getName().endsWith(".class")) { - JarEntry je2 = jf2.getJarEntry(je1.getName()); - boolean pf = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements); - if (result == true) { - result = pf; - } - } - } - } else { - JarEntry je1 = jf1.getJarEntry(className); - result = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements); - } - if (result == false) { - throw new RuntimeException("Class structural comparison failure"); - } - return result; - } - - public static boolean compareClass(String jar1, String jar2, - String className) throws IOException { - - Stack s = new Stack(); - if (Globals.ignoreDebugAttributes()) { - s = new Stack(); - s.push("LocalVariable"); - s.push("LocalVariableType"); - s.push("LineNumber"); - s.push("SourceFile"); - } - return compareClass(jar1, jar2, className, Globals.ignoreUnknownAttributes(), s); - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java b/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java deleted file mode 100644 index ed439dc991a..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Globals.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * A collection of useful global utilities commonly used. - */ -package sun.tools.pack.verify; - -import java.io.*; -import java.util.*; - -/* - * @author ksrini - */ - -class Globals { - - private static int errors = 0; - private static PrintWriter _pw = null; - private static String _logFileName = null; - private static final String DEFAULT_LOG_FILE = "verifier.log"; - private static boolean _verbose = true; - private static boolean _ignoreJarDirectories = false; - private static boolean _checkJarClassOrdering = true; - private static boolean _bitWiseClassCompare = false; - // Ignore Deprecated, SourceFile and Synthetic - private static boolean _ignoreCompileAttributes = false; - // Ignore Debug Attributes LocalVariableTable, LocalVariableType,LineNumberTable - private static boolean _ignoreDebugAttributes = false; - private static boolean _ignoreUnknownAttributes = false; - private static boolean _validateClass = true; - private static Globals _instance = null; - - static Globals getInstance() { - if (_instance == null) { - _instance = new Globals(); - _verbose = (System.getProperty("sun.tools.pack.verify.verbose") == null) - ? false : true; - _ignoreJarDirectories = (System.getProperty("ignoreJarDirectories") == null) - ? false : true; - } - return _instance; - } - - static boolean ignoreCompileAttributes() { - return _ignoreCompileAttributes; - } - - static boolean ignoreDebugAttributes() { - return _ignoreDebugAttributes; - } - - static boolean ignoreUnknownAttributes() { - return _ignoreUnknownAttributes; - } - - static boolean ignoreJarDirectories() { - return _ignoreJarDirectories; - } - - static boolean validateClass() { - return _validateClass; - } - - static void setCheckJarClassOrdering(boolean flag) { - _checkJarClassOrdering = flag; - } - - static boolean checkJarClassOrdering() { - return _checkJarClassOrdering; - } - - static boolean bitWiseClassCompare() { - return _bitWiseClassCompare; - } - - static boolean setBitWiseClassCompare(boolean flag) { - return _bitWiseClassCompare = flag; - } - - public static boolean setIgnoreCompileAttributes(boolean flag) { - return _ignoreCompileAttributes = flag; - } - - static boolean setIgnoreDebugAttributes(boolean flag) { - return _ignoreDebugAttributes = flag; - } - - static boolean setIgnoreUnknownAttributes(boolean flag) { - return _ignoreUnknownAttributes = flag; - } - - static boolean setValidateClass(boolean flag) { - return _validateClass = flag; - } - - static int getErrors() { - return errors; - } - - static void trace(String s) { - if (_verbose) { - println(s); - } - } - - static void print(String s) { - _pw.print(s); - } - - static void println(String s) { - _pw.println(s); - } - - static void log(String s) { - errors++; - _pw.println("ERROR:" + s); - } - - static void lognoln(String s) { - errors++; - _pw.print(s); - } - - private static PrintWriter openFile(String fileName) { - //Lets create the directory if it does not exist. - File f = new File(fileName); - File baseDir = f.getParentFile(); - if (baseDir != null && baseDir.exists() == false) { - baseDir.mkdirs(); - } - try { - return new PrintWriter(new FileWriter(f), true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static void closeFile() { - _pw.flush(); - _pw.close(); - } - - static void printPropsToLog() { - println("Log started " + new Date(System.currentTimeMillis())); - print(System.getProperty("java.vm.version")); - println("\t" + System.getProperty("java.vm.name")); - - println("System properties"); - println("\tjava.home=" + System.getProperty("java.home")); - println("\tjava.class.version=" + System.getProperty("java.class.version")); - println("\tjava.class.path=" + System.getProperty("java.class.path")); - println("\tos.name=" + System.getProperty("os.name")); - println("\tos.arch=" + System.getProperty("os.arch")); - println("\tos.version=" + System.getProperty("os.version")); - println("\tuser.name=" + System.getProperty("user.name")); - println("\tuser.home=" + System.getProperty("user.home")); - println("\tuser.dir=" + System.getProperty("user.dir")); - println("\tLocale.getDefault=" + Locale.getDefault()); - println("System properties end"); - } - - static void openLog(String s) { - _logFileName = (s != null) ? s : "." + File.separator + DEFAULT_LOG_FILE; - _logFileName = (new File(_logFileName).isDirectory()) - ? _logFileName + File.separator + DEFAULT_LOG_FILE : _logFileName; - _pw = openFile(_logFileName); - printPropsToLog(); - } - - static void closeLog() { - closeFile(); - } - - static String getLogFileName() { - return _logFileName; - } - - static void diffCharData(String s1, String s2) { - boolean diff = false; - char[] c1 = s1.toCharArray(); - char[] c2 = s2.toCharArray(); - if (c1.length != c2.length) { - diff = true; - Globals.log("Length differs: " + (c1.length - c2.length)); - } - // Take the smaller of the two arrays to prevent Array...Exception - int minlen = (c1.length < c2.length) ? c1.length : c2.length; - for (int i = 0; i < c1.length; i++) { - if (c1[i] != c2[i]) { - diff = true; - Globals.lognoln("\t idx[" + i + "] 0x" + Integer.toHexString(c1[i]) + "<>" + "0x" + Integer.toHexString(c2[i])); - Globals.log(" -> " + c1[i] + "<>" + c2[i]); - } - } - } - - static void diffByteData(String s1, String s2) { - boolean diff = false; - byte[] b1 = s1.getBytes(); - byte[] b2 = s2.getBytes(); - - if (b1.length != b2.length) { - diff = true; - //(+) b1 is greater, (-) b2 is greater - Globals.log("Length differs diff: " + (b1.length - b2.length)); - } - // Take the smaller of the two array to prevent Array...Exception - int minlen = (b1.length < b2.length) ? b1.length : b2.length; - for (int i = 0; i < b1.length; i++) { - if (b1[i] != b2[i]) { - diff = true; - Globals.log("\t" + "idx[" + i + "] 0x" + Integer.toHexString(b1[i]) + "<>" + "0x" + Integer.toHexString(b2[i])); - } - } - } - - static void dumpToHex(String s) { - try { - dumpToHex(s.getBytes("UTF-8")); - } catch (UnsupportedEncodingException uce) { - throw new RuntimeException(uce); - } - } - - static void dumpToHex(byte[] buffer) { - int linecount = 0; - byte[] b = new byte[16]; - for (int i = 0; i < buffer.length; i += 16) { - if (buffer.length - i > 16) { - System.arraycopy(buffer, i, b, 0, 16); - print16Bytes(b, linecount); - linecount += 16; - } else { - System.arraycopy(buffer, i, b, 0, buffer.length - i); - for (int n = buffer.length - (i + 1); n < 16; n++) { - b[n] = 0; - } - print16Bytes(b, linecount); - linecount += 16; - } - } - Globals.log("-----------------------------------------------------------------"); - } - - static void print16Bytes(byte[] buffer, int linecount) { - final int MAX = 4; - Globals.lognoln(paddedHexString(linecount, 4) + " "); - - for (int i = 0; i < buffer.length; i += 2) { - int iOut = pack2Bytes2Int(buffer[i], buffer[i + 1]); - Globals.lognoln(paddedHexString(iOut, 4) + " "); - } - - Globals.lognoln("| "); - - StringBuilder sb = new StringBuilder(new String(buffer)); - - for (int i = 0; i < buffer.length; i++) { - if (Character.isISOControl(sb.charAt(i))) { - sb.setCharAt(i, '.'); - } - } - Globals.log(sb.toString()); - } - - static int pack2Bytes2Int(byte b1, byte b2) { - int out = 0x0; - out += b1; - out <<= 8; - out &= 0x0000ffff; - out |= 0x000000ff & b2; - return out; - } - - static String paddedHexString(int n, int max) { - char[] c = Integer.toHexString(n).toCharArray(); - char[] out = new char[max]; - - for (int i = 0; i < max; i++) { - out[i] = '0'; - } - int offset = (max - c.length < 0) ? 0 : max - c.length; - for (int i = 0; i < c.length; i++) { - out[offset + i] = c[i]; - } - return new String(out); - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java b/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java deleted file mode 100644 index 419fda1ba23..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/JarFileCompare.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package sun.tools.pack.verify; - -import java.io.*; -import java.util.*; -import java.util.jar.*; - -class JarFileCompare { - /* - * @author ksrini - */ - - private static VerifyTreeSet getVerifyTreeSet(String jarPath) { - VerifyTreeSet vts = new VerifyTreeSet(); - try { - JarFile j = new JarFile(jarPath); - for (JarEntry je : Collections.list((Enumeration) j.entries())) { - if (!je.isDirectory()) { // totally ignore directories - vts.add(je.getName()); - } - } - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - return vts; - } - - private static LinkedList getListOfClasses(String jarPath) { - LinkedList l = new LinkedList(); - try { - JarFile j = new JarFile(jarPath); - for (JarEntry je : Collections.list((Enumeration) j.entries())) { - if (!je.isDirectory() && je.getName().endsWith(".class")) { - l.add(je.getName()); - } - } - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - return l; - } - - private static void jarDirectoryCompare(String jarPath1, String jarPath2) { - VerifyTreeSet vts1 = getVerifyTreeSet(jarPath1); - VerifyTreeSet vts2 = getVerifyTreeSet(jarPath2); - - TreeSet diff1 = vts1.diff(vts2); - if (diff1.size() > 0) { - Globals.log("Left has the following entries that right does not have"); - Globals.log(diff1.toString()); - } - TreeSet diff2 = vts2.diff(vts1); - if (diff2.size() > 0) { - Globals.log("Right has the following entries that left does not have"); - Globals.log(diff2.toString()); - } - if (Globals.checkJarClassOrdering()) { - boolean error = false; - Globals.println("Checking Class Ordering"); - LinkedList l1 = getListOfClasses(jarPath1); - LinkedList l2 = getListOfClasses(jarPath2); - if (l1.size() != l2.size()) { - error = true; - Globals.log("The number of classes differs"); - Globals.log("\t" + l1.size() + "<>" + l2.size()); - } - for (int i = 0; i < l1.size(); i++) { - String s1 = (String) l1.get(i); - String s2 = (String) l2.get(i); - if (s1.compareTo(s2) != 0) { - error = true; - Globals.log("Ordering differs at[" + i + "] = " + s1); - Globals.log("\t" + s2); - } - } - } - } - - /* - * Returns true if the two Streams are bit identical, and false if they - * are not, no further diagnostics - */ - static boolean compareStreams(InputStream is1, InputStream is2) { - - BufferedInputStream bis1 = new BufferedInputStream(is1, 8192); - BufferedInputStream bis2 = new BufferedInputStream(is2, 8192); - try { - int i1, i2; - int count = 0; - while ((i1 = bis1.read()) == (i2 = bis2.read())) { - count++; - if (i1 < 0) { - // System.out.println("bytes read " + count); - return true; // got all the way to EOF - } - } - return false; // reads returned dif - - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - private static void checkEntry(JarFile jf1, JarFile jf2, JarEntry je) throws IOException { - InputStream is1 = jf1.getInputStream(je); - InputStream is2 = jf2.getInputStream(je); - if (is1 != null && is2 != null) { - if (!compareStreams(jf1.getInputStream(je), jf2.getInputStream(je))) { - Globals.println("+++" + je.getName() + "+++"); - Globals.log("Error: File:" + je.getName() - + " differs, use a diff util for further diagnostics"); - } - } else { - Globals.println("+++" + je.getName() + "+++"); - Globals.log("Error: File:" + je.getName() + " not found in " + jf2.getName()); - } - } - - /* - * Given two jar files we compare and see if the jarfiles have all the - * entries. The property ignoreJarDirectories is set to true by default - * which means that Directory entries in a jar may be ignore. - */ - static void jarCompare(String jarPath1, String jarPath2) { - jarDirectoryCompare(jarPath1, jarPath2); - - try { - JarFile jf1 = new JarFile(jarPath1); - JarFile jf2 = new JarFile(jarPath2); - - int nclasses = 0; - int nentries = 0; - int entries_checked = 0; - int classes_checked = 0; - - for (JarEntry je : Collections.list((Enumeration) jf1.entries())) { - if (!je.isDirectory() && !je.getName().endsWith(".class")) { - nentries++; - } else if (je.getName().endsWith(".class")) { - nclasses++; - } - } - - for (JarEntry je : Collections.list((Enumeration) jf1.entries())) { - if (je.isDirectory()) { - continue; // Ignore directories - } - if (!je.getName().endsWith(".class")) { - entries_checked++; - if (je.getName().compareTo("META-INF/MANIFEST.MF") == 0) { - Manifest mf1 = new Manifest(jf1.getInputStream(je)); - Manifest mf2 = new Manifest(jf2.getInputStream(je)); - if (!mf1.equals(mf2)) { - Globals.log("Error: Manifests differ"); - Globals.log("Manifest1"); - Globals.log(mf1.getMainAttributes().entrySet().toString()); - Globals.log("Manifest2"); - Globals.log(mf2.getMainAttributes().entrySet().toString()); - } - } else { - checkEntry(jf1, jf2, je); - } - } else if (Globals.bitWiseClassCompare() == true) { - checkEntry(jf1, jf2, je); - classes_checked++; - } - } - if (Globals.bitWiseClassCompare()) { - Globals.println("Class entries checked (byte wise)/Total Class entries = " - + classes_checked + "/" + nclasses); - } - Globals.println("Non-class entries checked/Total non-class entries = " - + entries_checked + "/" + nentries); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java b/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java deleted file mode 100644 index 481c67b15ce..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/Main.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -// The Main Entry point -package sun.tools.pack.verify; - -import java.io.*; - -/** - * This class provides a convenient entry point to the pack200 verifier. This - * compares two classes, either in path or in an archive. - * @see xmlkit.XMLKit - * @author ksrini - */ -public class Main { - - private static void syntax() { - System.out.println("Usage: "); - System.out.println("\tREFERENCE_CLASSPATH COMPARED_CLASSPATH [Options]"); - System.out.println("\tOptions:"); - System.out.println("\t\t-O check jar ordering"); - System.out.println("\t\t-C ignore compile attributes (Deprecated, SourceFile, Synthetic, )"); - System.out.println("\t\t-D ignore debug attributes (LocalVariable, LineNumber)"); - System.out.println("\t\t-u ignore unknown attributes"); - System.out.println("\t\t-V turn off class validation"); - System.out.println("\t\t-c CLASS, compare CLASS only"); - System.out.println("\t\t-b Compares all entries bitwise only"); - System.out.println("\t\t-l Directory or Log File Name"); - } - - /** - * main entry point to the class file comparator, which compares semantically - * class files in a classpath or an archive. - * @param args String array as described below - * @throws RuntimeException - *

    -     *  Usage:
    -     *     ReferenceClasspath SpecimenClaspath [Options]
    -     *     Options:
    -     *      -O check jar ordering
    -     *      -C do not compare compile attributes (Deprecated, SourceFile, Synthetic)
    -     *      -D do not compare debug attribute (LocalVariableTable, LineNumberTable)
    -     *      -u ignore unknown attributes
    -     *      -V turn off class validation
    -     *      -c class, compare a single class
    -     *      -b compares all entries bitwise (fastest)
    -     *      -l directory or log file name
    -     * 
    - */ - public static void main(String args[]) { - Globals.getInstance(); - if (args == null || args.length < 2) { - syntax(); - System.exit(1); - } - String refJarFileName = null; - String cmpJarFileName = null; - String specificClass = null; - String logDirFileName = null; - - for (int i = 0; i < args.length; i++) { - if (i == 0) { - refJarFileName = args[0]; - continue; - } - if (i == 1) { - cmpJarFileName = args[1]; - continue; - } - - if (args[i].startsWith("-O")) { - Globals.setCheckJarClassOrdering(true); - } - - if (args[i].startsWith("-b")) { - Globals.setBitWiseClassCompare(true); - } - - if (args[i].startsWith("-C")) { - Globals.setIgnoreCompileAttributes(true); - } - - if (args[i].startsWith("-D")) { - Globals.setIgnoreDebugAttributes(true); - } - - if (args[i].startsWith("-V")) { - Globals.setValidateClass(false); - } - - if (args[i].startsWith("-c")) { - i++; - specificClass = args[i].trim(); - } - - if (args[i].startsWith("-u")) { - i++; - Globals.setIgnoreUnknownAttributes(true); - } - - if (args[i].startsWith("-l")) { - i++; - logDirFileName = args[i].trim(); - } - } - - Globals.openLog(logDirFileName); - - File refJarFile = new File(refJarFileName); - File cmpJarFile = new File(cmpJarFileName); - - String f1 = refJarFile.getAbsoluteFile().toString(); - String f2 = cmpJarFile.getAbsoluteFile().toString(); - - System.out.println("LogFile:" + Globals.getLogFileName()); - System.out.println("Reference JAR:" + f1); - System.out.println("Compared JAR:" + f2); - - Globals.println("LogFile:" + Globals.getLogFileName()); - Globals.println("Reference JAR:" + f1); - Globals.println("Compared JAR:" + f2); - - Globals.println("Ignore Compile Attributes:" + Globals.ignoreCompileAttributes()); - Globals.println("Ignore Debug Attributes:" + Globals.ignoreDebugAttributes()); - Globals.println("Ignore Unknown Attributes:" + Globals.ignoreUnknownAttributes()); - Globals.println("Class ordering check:" + Globals.checkJarClassOrdering()); - Globals.println("Class validation check:" + Globals.validateClass()); - Globals.println("Bit-wise compare:" + Globals.bitWiseClassCompare()); - Globals.println("ClassName:" + ((specificClass == null) ? "ALL" : specificClass)); - - if (specificClass == null && Globals.bitWiseClassCompare() == true) { - JarFileCompare.jarCompare(refJarFileName, cmpJarFileName); - } else { - try { - ClassCompare.compareClass(refJarFileName, cmpJarFileName, specificClass); - } catch (Exception e) { - Globals.log("Exception " + e); - throw new RuntimeException(e); - } - } - - if (Globals.getErrors() > 0) { - System.out.println("FAIL"); - Globals.println("FAIL"); - System.exit(Globals.getErrors()); - } - - System.out.println("PASS"); - Globals.println("PASS"); - System.exit(Globals.getErrors()); - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java b/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java deleted file mode 100644 index 1e4c32b2af0..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/sun/tools/pack/verify/VerifyTreeSet.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.tools.pack.verify; - -import java.util.*; -/* - * @author ksrini - */ - -class VerifyTreeSet extends java.util.TreeSet { - - VerifyTreeSet() { - super(); - } - - public VerifyTreeSet(Comparator c) { - super(c); - } - - public TreeSet diff(TreeSet in) { - TreeSet delta = (TreeSet) this.clone(); - delta.removeAll(in); - return delta; - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java b/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java deleted file mode 100644 index e288e9b4eec..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java +++ /dev/null @@ -1,1911 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -import com.sun.tools.classfile.AccessFlags; -import com.sun.tools.classfile.Annotation; -import com.sun.tools.classfile.Annotation.Annotation_element_value; -import com.sun.tools.classfile.Annotation.Array_element_value; -import com.sun.tools.classfile.Annotation.Class_element_value; -import com.sun.tools.classfile.Annotation.Enum_element_value; -import com.sun.tools.classfile.Annotation.Primitive_element_value; -import com.sun.tools.classfile.AnnotationDefault_attribute; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Attributes; -import com.sun.tools.classfile.BootstrapMethods_attribute; -import com.sun.tools.classfile.CharacterRangeTable_attribute; -import com.sun.tools.classfile.ClassFile; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.CompilationID_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Module_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Package_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Integer_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_InterfaceMethodref_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Long_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodType_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; -import com.sun.tools.classfile.ConstantPool.CPInfo; -import com.sun.tools.classfile.ConstantPool.InvalidIndex; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.ConstantValue_attribute; -import com.sun.tools.classfile.DefaultAttribute; -import com.sun.tools.classfile.Deprecated_attribute; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; -import com.sun.tools.classfile.EnclosingMethod_attribute; -import com.sun.tools.classfile.Exceptions_attribute; -import com.sun.tools.classfile.Field; -import com.sun.tools.classfile.InnerClasses_attribute; -import com.sun.tools.classfile.InnerClasses_attribute.Info; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.Instruction.TypeKind; -import com.sun.tools.classfile.LineNumberTable_attribute; -import com.sun.tools.classfile.LocalVariableTable_attribute; -import com.sun.tools.classfile.LocalVariableTypeTable_attribute; -import com.sun.tools.classfile.Method; -import com.sun.tools.classfile.MethodParameters_attribute; -import com.sun.tools.classfile.Module_attribute; -import com.sun.tools.classfile.Module_attribute.ExportsEntry; -import com.sun.tools.classfile.Module_attribute.ProvidesEntry; -import com.sun.tools.classfile.Module_attribute.RequiresEntry; -import com.sun.tools.classfile.ModuleHashes_attribute; -import com.sun.tools.classfile.ModuleHashes_attribute.Entry; -import com.sun.tools.classfile.ModuleMainClass_attribute; -import com.sun.tools.classfile.ModuleResolution_attribute; -import com.sun.tools.classfile.ModuleTarget_attribute; -import com.sun.tools.classfile.ModulePackages_attribute; -import com.sun.tools.classfile.NestHost_attribute; -import com.sun.tools.classfile.NestMembers_attribute; -import com.sun.tools.classfile.Opcode; -import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; -import com.sun.tools.classfile.Signature_attribute; -import com.sun.tools.classfile.SourceDebugExtension_attribute; -import com.sun.tools.classfile.SourceFile_attribute; -import com.sun.tools.classfile.SourceID_attribute; -import com.sun.tools.classfile.StackMapTable_attribute; -import com.sun.tools.classfile.StackMapTable_attribute.append_frame; -import com.sun.tools.classfile.StackMapTable_attribute.chop_frame; -import com.sun.tools.classfile.StackMapTable_attribute.full_frame; -import com.sun.tools.classfile.StackMapTable_attribute.same_frame; -import com.sun.tools.classfile.StackMapTable_attribute.same_frame_extended; -import com.sun.tools.classfile.StackMapTable_attribute.same_locals_1_stack_item_frame; -import com.sun.tools.classfile.StackMapTable_attribute.same_locals_1_stack_item_frame_extended; -import com.sun.tools.classfile.StackMap_attribute; -import com.sun.tools.classfile.Synthetic_attribute; -import com.sun.tools.classfile.TypeAnnotation; -import com.sun.tools.classfile.TypeAnnotation.Position; -import static com.sun.tools.classfile.TypeAnnotation.TargetType.THROWS; -import java.io.*; -import java.util.*; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import xmlkit.XMLKit.Element; - -/* - * @author jrose, ksrini - */ -public class ClassReader { - - private static final CommandLineParser CLP = new CommandLineParser("" - + "-source: +> = \n" - + "-dest: +> = \n" - + "-encoding: +> = \n" - + "-jcov $ \n -nojcov !-jcov \n" - + "-verbose $ \n -noverbose !-verbose \n" - + "-keepPath $ \n -nokeepPath !-keepPath \n" - + "-keepCP $ \n -nokeepCP !-keepCP \n" - + "-keepOrder $ \n -nokeepOrder !-keepOrder \n" - + "-continue $ \n -nocontinue !-continue \n" - + "-@ >-@ . \n" - + "- +? \n" - + "\n"); - - - // Protected state for representing the class file. - protected Element cfile; // - protected Element cpool; // - protected Element klass; // - protected List thePool; // stringified flattened Constant Pool - - public static void main(String[] ava) throws IOException { - ArrayList av = new ArrayList<>(Arrays.asList(ava)); - HashMap props = new HashMap<>(); - props.put("-encoding:", "UTF8"); // default - props.put("-keepOrder", null); // CLI default - props.put("-pretty", "1"); // CLI default - props.put("-continue", "1"); // CLI default - CLP.parse(av, props); - //System.out.println(props+" ++ "+av); - File source = asFile(props.get("-source:")); - File dest = asFile(props.get("-dest:")); - String encoding = props.get("-encoding:"); - boolean contError = props.containsKey("-continue"); - ClassReader options = new ClassReader(); - options.copyOptionsFrom(props); - /* - if (dest == null && av.size() > 1) { - dest = File.createTempFile("TestOut", ".dir", new File(".")); - dest.delete(); - if (!dest.mkdir()) - throw new RuntimeException("Cannot create "+dest); - System.out.println("Writing results to "+dest); - } - */ - if (av.isEmpty()) { - av.add(""); //to enter this loop - } - boolean readList = false; - for (String a : av) { - if (readList) { - readList = false; - InputStream fin; - if (a.equals("-")) { - fin = System.in; - } else { - fin = new FileInputStream(a); - } - - BufferedReader files = makeReader(fin, encoding); - for (String file; (file = files.readLine()) != null;) { - doFile(file, source, dest, options, encoding, contError); - } - if (fin != System.in) { - fin.close(); - } - } else if (a.equals("-@")) { - readList = true; - } else if (a.startsWith("-")) { - throw new RuntimeException("Bad flag argument: " + a); - } else if (source.getName().endsWith(".jar")) { - doJar(a, source, dest, options, encoding, contError); - } else { - doFile(a, source, dest, options, encoding, contError); - } - } - } - - private static File asFile(String str) { - return (str == null) ? null : new File(str); - } - - private static void doFile(String a, - File source, File dest, - ClassReader options, String encoding, - boolean contError) throws IOException { - if (!contError) { - doFile(a, source, dest, options, encoding); - } else { - try { - doFile(a, source, dest, options, encoding); - } catch (Exception ee) { - System.out.println("Error processing " + source + ": " + ee); - ee.printStackTrace(); - } - } - } - - private static void doJar(String a, File source, File dest, - ClassReader options, String encoding, - Boolean contError) throws IOException { - try { - JarFile jf = new JarFile(source); - for (JarEntry je : Collections.list(jf.entries())) { - String name = je.getName(); - if (!name.endsWith(".class")) { - continue; - } - try { - doStream(name, jf.getInputStream(je), dest, options, encoding); - } catch (Exception e) { - if (contError) { - System.out.println("Error processing " + source + ": " + e); - e.printStackTrace(); - continue; - } - } - } - } catch (IOException ioe) { - throw ioe; - } - } - - private static void doStream(String a, InputStream in, File dest, - ClassReader options, String encoding) throws IOException { - - File f = new File(a); - ClassReader cr = new ClassReader(options); - Element e; - if (options.verbose) { - System.out.println("Reading " + f); - } - e = cr.readFrom(in); - - OutputStream out; - if (dest == null) { - out = System.out; - } else { - File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath()); - String outName = outf.getName(); - File outSubdir = outf.getParentFile(); - outSubdir.mkdirs(); - int extPos = outName.lastIndexOf('.'); - if (extPos > 0) { - outf = new File(outSubdir, outName.substring(0, extPos) + ".xml"); - } - out = new FileOutputStream(outf); - } - - Writer outw = makeWriter(out, encoding); - if (options.pretty || !options.keepOrder) { - e.writePrettyTo(outw); - } else { - e.writeTo(outw); - } - if (out == System.out) { - outw.write("\n"); - outw.flush(); - } else { - outw.close(); - } - } - - private static void doFile(String a, - File source, File dest, - ClassReader options, String encoding) throws IOException { - File inf = new File(source, a); - if (dest != null && options.verbose) { - System.out.println("Reading " + inf); - } - - BufferedInputStream in = new BufferedInputStream(new FileInputStream(inf)); - - doStream(a, in, dest, options, encoding); - - } - - public static BufferedReader makeReader(InputStream in, - String encoding) throws IOException { - Reader inw; - in = new BufferedInputStream(in); // add buffering - if (encoding == null) { - inw = new InputStreamReader(in); - } else { - inw = new InputStreamReader(in, encoding); - } - return new BufferedReader(inw); // add buffering - } - - public static Writer makeWriter(OutputStream out, - String encoding) throws IOException { - Writer outw; - if (encoding == null) { - outw = new OutputStreamWriter(out); - } else { - outw = new OutputStreamWriter(out, encoding); - } - return new BufferedWriter(outw); // add buffering - } - - public Element result() { - return cfile; - } - - protected InputStream in; - protected ByteArrayOutputStream buf = new ByteArrayOutputStream(1024); - // input options - public boolean pretty = false; - public boolean verbose = false; - public boolean keepPath = false; - public boolean keepCP = false; - public boolean keepBytes = false; - public boolean parseBytes = true; - public boolean resolveRefs = true; - public boolean keepOrder = true; - public boolean keepSizes = false; - - public ClassReader() { - cfile = new Element("ClassFile"); - } - - public ClassReader(ClassReader options) { - this(); - copyOptionsFrom(options); - } - - public void copyOptionsFrom(ClassReader options) { - pretty = options.pretty; - verbose = options.verbose; - keepPath = options.keepPath; - keepCP = options.keepCP; - keepOrder = options.keepOrder; - } - - public void copyOptionsFrom(Map options) { - if (options.containsKey("-pretty")) { - pretty = (options.get("-pretty") != null); - } - if (options.containsKey("-verbose")) { - verbose = (options.get("-verbose") != null); - } - if (options.containsKey("-keepPath")) { - keepPath = (options.get("-keepPath") != null); - } - if (options.containsKey("-keepCP")) { - keepCP = (options.get("-keepCP") != null); - } - if (options.containsKey("-keepOrder")) { - keepOrder = (options.get("-keepOrder") != null); - } - } - - protected String getCpString(int i) { - return thePool.get(i); - } - - public Element readFrom(InputStream in) throws IOException { - try { - this.in = in; - ClassFile c = ClassFile.read(in); - // read the file header - if (c.magic != 0xCAFEBABE) { - throw new RuntimeException("bad magic number " + - Integer.toHexString(c.magic)); - } - cfile.setAttr("magic", "" + c.magic); - int minver = c.minor_version; - int majver = c.major_version; - cfile.setAttr("minver", "" + minver); - cfile.setAttr("majver", "" + majver); - readCP(c); - readClass(c); - return result(); - } catch (InvalidDescriptor | ConstantPoolException ex) { - throw new IOException("Fatal error", ex); - } - } - - public Element readFrom(File file) throws IOException { - try (InputStream strm = new FileInputStream(file)) { - Element e = readFrom(new BufferedInputStream(strm)); - if (keepPath) { - e.setAttr("path", file.toString()); - } - return e; - } - } - - private void readClass(ClassFile c) throws IOException, - ConstantPoolException, - InvalidDescriptor { - klass = new Element("Class"); - cfile.add(klass); - String thisk = c.getName(); - - klass.setAttr("name", thisk); - - AccessFlags af = new AccessFlags(c.access_flags.flags); - klass.setAttr("flags", flagString(af, klass)); - if (!"java/lang/Object".equals(thisk)) { - if (c.super_class != 0) { - klass.setAttr("super", c.getSuperclassName()); - } - } - for (int i : c.interfaces) { - klass.add(new Element("Interface", "name", getCpString(i))); - } - readFields(c, klass); - readMethods(c, klass); - readAttributesFor(c, c.attributes, klass); - klass.trimToSize(); - } - - private void readFields(ClassFile c, Element klass) throws IOException { - int len = c.fields.length; - Element fields = new Element(len); - for (Field f : c.fields) { - Element field = new Element("Field"); - field.setAttr("name", getCpString(f.name_index)); - field.setAttr("type", getCpString(f.descriptor.index)); - field.setAttr("flags", flagString(f.access_flags.flags, field)); - readAttributesFor(c, f.attributes, field); - - field.trimToSize(); - fields.add(field); - } - if (!keepOrder) { - fields.sort(); - } - klass.addAll(fields); - } - - - private void readMethods(ClassFile c, Element klass) throws IOException { - int len = c.methods.length; - Element methods = new Element(len); - for (Method m : c.methods) { - Element member = new Element("Method"); - member.setAttr("name", getCpString(m.name_index)); - member.setAttr("type", getCpString(m.descriptor.index)); - member.setAttr("flags", flagString(m.access_flags.flags, member)); - readAttributesFor(c, m.attributes, member); - - member.trimToSize(); - methods.add(member); - } - if (!keepOrder) { - methods.sort(); - } - klass.addAll(methods); - } - - private AccessFlags.Kind getKind(Element e) { - switch(e.getName()) { - case "Class": - return AccessFlags.Kind.Class; - case "InnerClass": - return AccessFlags.Kind.InnerClass; - case "Field": - return AccessFlags.Kind.Field ; - case "Method": - return AccessFlags.Kind.Method; - default: throw new RuntimeException("should not reach here"); - } - } - - protected String flagString(int flags, Element holder) { - return flagString(new AccessFlags(flags), holder); - } - protected String flagString(AccessFlags af, Element holder) { - return flagString(af, holder.getName()); - } - protected String flagString(int flags, String kind) { - return flagString(new AccessFlags(flags), kind); - } - protected String flagString(AccessFlags af, String kind) { - Set mods = null; - switch (kind) { - case "Class": - mods = af.getClassFlags(); - break; - case "InnerClass": - mods = af.getInnerClassFlags(); - break; - case "Field": - mods = af.getFieldFlags(); - break; - case "Method": - mods = af.getMethodFlags(); - break; - default: - throw new RuntimeException("should not reach here"); - } - StringBuilder sb = new StringBuilder(); - for (String x : mods) { - sb.append(x.substring(x.indexOf('_') + 1).toLowerCase()).append(" "); - } - return sb.toString().trim(); - } - - - protected void readAttributesFor(ClassFile c, Attributes attrs, Element x) { - Element container = new Element(); - AttributeVisitor av = new AttributeVisitor(this, c); - for (Attribute a : attrs) { - av.visit(a, container); - } - if (!keepOrder) { - container.sort(); - } - x.addAll(container); - } - - private int fileSize = 0; - private HashMap attrSizes = new HashMap<>(); - - private void attachTo(Element x, Object aval0) { - if (aval0 == null) { - return; - } - if (!(aval0 instanceof Element)) { - x.add(aval0); - return; - } - Element aval = (Element) aval0; - if (!aval.isAnonymous()) { - x.add(aval); - return; - } - for (int imax = aval.attrSize(), i = 0; i < imax; i++) { - //%% - attachAttrTo(x, aval.getAttrName(i), aval.getAttr(i)); - } - x.addAll(aval); - } - - private void attachAttrTo(Element x, String aname, String aval) { - String aval0 = x.getAttr(aname); - if (aval0 != null) { - aval = aval0 + " " + aval; - } - x.setAttr(aname, aval); - } - - private void readCP(ClassFile c) throws IOException { - cpool = new Element("ConstantPool", c.constant_pool.size()); - ConstantPoolVisitor cpv = new ConstantPoolVisitor(cpool, c, - c.constant_pool.size()); - for (int i = 1 ; i < c.constant_pool.size() ; i++) { - try { - cpv.visit(c.constant_pool.get(i), i); - } catch (InvalidIndex ex) { - // can happen periodically when accessing doubles etc. ignore it - // ex.printStackTrace(); - } - } - thePool = cpv.getPoolList(); - if (verbose) { - for (int i = 0; i < thePool.size(); i++) { - System.out.println("[" + i + "]: " + thePool.get(i)); - } - } - if (keepCP) { - cfile.add(cpool); - } - } -} - -class ConstantPoolVisitor implements ConstantPool.Visitor { - final List slist; - final Element xpool; - final ClassFile cf; - final ConstantPool cfpool; - final List bsmlist; - - - public ConstantPoolVisitor(Element xpool, ClassFile cf, int size) { - slist = new ArrayList<>(size); - for (int i = 0 ; i < size; i++) { - slist.add(null); - } - this.xpool = xpool; - this.cf = cf; - this.cfpool = cf.constant_pool; - bsmlist = readBSM(); - } - - public List getPoolList() { - return Collections.unmodifiableList(slist); - } - - public List getBSMList() { - return Collections.unmodifiableList(bsmlist); - } - - public String visit(CPInfo c, int index) { - return c.accept(this, index); - } - - private List readBSM() { - BootstrapMethods_attribute bsmAttr = - (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods); - if (bsmAttr != null) { - List out = - new ArrayList<>(bsmAttr.bootstrap_method_specifiers.length); - for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms : - bsmAttr.bootstrap_method_specifiers) { - int index = bsms.bootstrap_method_ref; - try { - String value = slist.get(index); - String bsmStr = value; - if (value == null) { - value = visit(cfpool.get(index), index); - slist.set(index, value); - } - bsmStr = value; - for (int idx : bsms.bootstrap_arguments) { - value = slist.get(idx); - if (value == null) { - value = visit(cfpool.get(idx), idx); - slist.set(idx, value); - } - bsmStr = bsmStr.concat("," + value); - } - out.add(bsmStr); - } catch (InvalidIndex ex) { - ex.printStackTrace(); - } - } - return out; - } - return new ArrayList<>(0); - } - - @Override - public String visitClass(CONSTANT_Class_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(c.name_index), c.name_index); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Class", - new String[]{"id", p.toString()}, - value)); - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitModule(CONSTANT_Module_info info, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(info.name_index), info.name_index); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Module", - new String[]{"id", p.toString()}, - value)); - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitPackage(CONSTANT_Package_info info, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(info.name_index), info.name_index); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Package", - new String[]{"id", p.toString()}, - value)); - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitDouble(CONSTANT_Double_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - value = Double.toString(c.value); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Double", - new String[]{"id", p.toString()}, - value)); - } - return value; - } - - @Override - public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(c.class_index), c.class_index); - value = value.concat(" " + visit(cfpool.get(c.name_and_type_index), - c.name_and_type_index)); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Fieldref", - new String[]{"id", p.toString()}, - value)); - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitFloat(CONSTANT_Float_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - value = Float.toString(c.value); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Float", - new String[]{"id", p.toString()}, - value)); - } - return value; - } - - @Override - public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) { - String value = slist.get(p); - if (value == null) { - value = Integer.toString(cnstnt.value); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Integer", - new String[]{"id", p.toString()}, - value)); - } - return value; - } - - @Override - public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c, - Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(c.class_index), c.class_index); - value = value.concat(" " + - visit(cfpool.get(c.name_and_type_index), - c.name_and_type_index)); - slist.set(p, value); - xpool.add(new Element("CONSTANT_InterfaceMethodref", - new String[]{"id", p.toString()}, - value)); - - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = bsmlist.get(c.bootstrap_method_attr_index) + " " - + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index); - slist.set(p, value); - xpool.add(new Element("CONSTANT_InvokeDynamic", - new String[]{"id", p.toString()}, - value)); - - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitDynamicConstant(ConstantPool.CONSTANT_Dynamic_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = bsmlist.get(c.bootstrap_method_attr_index) + " " - + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Dynamic", - new String[]{"id", p.toString()}, - value)); - - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitLong(CONSTANT_Long_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - value = Long.toString(c.value); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Long", - new String[]{"id", p.toString()}, - value)); - } - return value; - } - - @Override - public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(c.name_index), c.name_index); - value = value.concat(" " + - visit(cfpool.get(c.type_index), c.type_index)); - slist.set(p, value); - xpool.add(new Element("CONSTANT_NameAndType", - new String[]{"id", p.toString()}, - value)); - } catch (InvalidIndex ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitMethodref(CONSTANT_Methodref_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(c.class_index), c.class_index); - value = value.concat(" " + - visit(cfpool.get(c.name_and_type_index), - c.name_and_type_index)); - slist.set(p, value); - xpool.add(new Element("CONSTANT_Methodref", - new String[]{"id", p.toString()}, - value)); - - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = c.reference_kind.name(); - value = value.concat(" " - + visit(cfpool.get(c.reference_index), c.reference_index)); - slist.set(p, value); - xpool.add(new Element("CONSTANT_MethodHandle", - new String[]{"id", p.toString()}, - value)); - - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitMethodType(CONSTANT_MethodType_info c, Integer p) { - String value = slist.get(p); - if (value == null) { - try { - value = visit(cfpool.get(c.descriptor_index), c.descriptor_index); - slist.set(p, value); - xpool.add(new Element("CONSTANT_MethodType", - new String[]{"id", p.toString()}, - value)); - } catch (ConstantPoolException ex) { - ex.printStackTrace(); - } - } - return value; - } - - @Override - public String visitString(CONSTANT_String_info c, Integer p) { - try { - - String value = slist.get(p); - if (value == null) { - value = c.getString(); - slist.set(p, value); - xpool.add(new Element("CONSTANT_String", - new String[]{"id", p.toString()}, - value)); - } - return value; - } catch (ConstantPoolException ex) { - throw new RuntimeException("Fatal error", ex); - } - } - - @Override - public String visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) { - String value = slist.get(p); - if (value == null) { - value = cnstnt.value; - slist.set(p, value); - xpool.add(new Element("CONSTANT_Utf8", - new String[]{"id", p.toString()}, - value)); - } - return value; - - } -} - -class AttributeVisitor implements Attribute.Visitor { - final ClassFile cf; - final ClassReader x; - final AnnotationsElementVisitor aev; - final InstructionVisitor iv; - - public AttributeVisitor(ClassReader x, ClassFile cf) { - this.x = x; - this.cf = cf; - iv = new InstructionVisitor(x, cf); - aev = new AnnotationsElementVisitor(x, cf); - } - - public void visit(Attribute a, Element parent) { - a.accept(this, parent); - } - - @Override - public Element visitBootstrapMethods(BootstrapMethods_attribute bm, Element p) { - Element e = new Element(x.getCpString(bm.attribute_name_index)); - for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : bm.bootstrap_method_specifiers) { - Element be = new Element("BootstrapMethodSpecifier"); - be.setAttr("ref", x.getCpString(bsm.bootstrap_method_ref)); - if (bsm.bootstrap_arguments.length > 0) { - Element bme = new Element("MethodArguments"); - for (int index : bsm.bootstrap_arguments) { - bme.add(x.getCpString(index)); - } - bme.trimToSize(); - be.add(bme); - } - be.trimToSize(); - e.add(be); - } - e.trimToSize(); - if (!x.keepOrder) { - e.sort(); - } - p.add(e); - return null; - } - - @Override - public Element visitDefault(DefaultAttribute da, Element p) { - Element e = new Element(x.getCpString(da.attribute_name_index)); - StringBuilder sb = new StringBuilder(); - for (byte x : da.info) { - sb.append("0x").append(Integer.toHexString(x)).append(" "); - } - e.setAttr("bytes", sb.toString().trim()); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitAnnotationDefault(AnnotationDefault_attribute ad, Element p) { - Element e = new Element(x.getCpString(ad.attribute_name_index)); - e.setAttr("tag", "" + ad.default_value.tag); - Element child = aev.visit(ad.default_value, e); - if (child != null) { - e.add(child); - } - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitCharacterRangeTable(CharacterRangeTable_attribute crt, - Element p) { - Element e = new Element(x.getCpString(crt.attribute_name_index)); - for (CharacterRangeTable_attribute.Entry ce : crt.character_range_table) { - e.setAttr("start_pc", "" + ce.start_pc); - e.setAttr("end_pc", "" + ce.end_pc); - e.setAttr("range_start", "" + ce.character_range_start); - e.setAttr("range_end", "" + ce.character_range_end); - e.setAttr("flags", x.flagString(ce.flags, "Method")); - } - e.trimToSize(); - p.add(e); - return null; - } - - private Element instructions(Element code, Code_attribute c) { - Element ielement = new Element("Instructions"); - for (Instruction ins : c.getInstructions()) { - ielement.add(iv.visit(ins)); - } - ielement.trimToSize(); - return ielement; - } - - @Override - public Element visitCode(Code_attribute c, Element p) { - Element e = null; - - e = new Element(x.getCpString(c.attribute_name_index), - "stack", "" + c.max_stack, - "local", "" + c.max_locals); - - e.add(instructions(e, c)); - - for (Code_attribute.Exception_data edata : c.exception_table) { - e.add(new Element("Handler", - "start", "" + edata.start_pc, - "end", "" + edata.end_pc, - "catch", "" + edata.handler_pc, - "class", x.getCpString(edata.catch_type))); - - } - this.x.readAttributesFor(cf, c.attributes, e); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitCompilationID(CompilationID_attribute cid, Element p) { - Element e = new Element(x.getCpString(cid.attribute_name_index), - x.getCpString(cid.compilationID_index)); - p.add(e); - return null; - } - - @Override - public Element visitModulePackages(ModulePackages_attribute attr, Element p) { - Element e = new Element(x.getCpString(attr.attribute_name_index)); - for (int i : attr.packages_index) { - Element ee = new Element("Package"); - String pkg = x.getCpString(i); - ee.setAttr("package", pkg); - e.add(ee); - } - e.trimToSize(); - e.sort(); - p.add(e); - return null; - } - - @Override - public Element visitConstantValue(ConstantValue_attribute cv, Element p) { - Element e = new Element(x.getCpString(cv.attribute_name_index)); - e.add(x.getCpString(cv.constantvalue_index)); - p.add(e); - return null; - } - - @Override - public Element visitDeprecated(Deprecated_attribute d, Element p) { - Element e = new Element(x.getCpString(d.attribute_name_index)); - p.add(e); - return null; - } - - @Override - public Element visitEnclosingMethod(EnclosingMethod_attribute em, Element p) { - Element e = new Element(x.getCpString(em.attribute_name_index)); - e.setAttr("class", x.getCpString(em.class_index)); - e.setAttr("desc", x.getCpString(em.method_index)); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitExceptions(Exceptions_attribute e, Element p) { - Element ee = new Element(x.getCpString(e.attribute_name_index)); - for (int idx : e.exception_index_table) { - Element n = new Element("Item"); - n.setAttr("class", x.getCpString(idx)); - ee.add(n); - } - ee.trimToSize(); - p.add(ee); - return null; - } - - @Override - public Element visitInnerClasses(InnerClasses_attribute ic, Element p) { - for (Info info : ic.classes) { - Element e = new Element(x.getCpString(ic.attribute_name_index)); - e.setAttr("class", x.getCpString(info.inner_class_info_index)); - e.setAttr("outer", x.getCpString(info.outer_class_info_index)); - e.setAttr("name", x.getCpString(info.inner_name_index)); - e.setAttr("flags", x.flagString(info.inner_class_access_flags, - "InnerClass")); - e.trimToSize(); - p.add(e); - } - return null; - } - - @Override - public Element visitLineNumberTable(LineNumberTable_attribute lnt, Element p) { - String name = x.getCpString(lnt.attribute_name_index); - for (LineNumberTable_attribute.Entry e : lnt.line_number_table) { - Element l = new Element(name); - l.setAttr("bci", "" + e.start_pc); - l.setAttr("line", "" + e.line_number); - l.trimToSize(); - p.add(l); - } - return null; // already added to parent - } - - @Override - public Element visitLocalVariableTable(LocalVariableTable_attribute lvt, - Element p) { - String name = x.getCpString(lvt.attribute_name_index); - for (LocalVariableTable_attribute.Entry e : lvt.local_variable_table) { - Element l = new Element(name); - l.setAttr("bci", "" + e.start_pc); - l.setAttr("span", "" + e.length); - l.setAttr("name", x.getCpString(e.name_index)); - l.setAttr("type", x.getCpString(e.descriptor_index)); - l.setAttr("slot", "" + e.index); - l.trimToSize(); - p.add(l); - } - return null; // already added to parent - } - - private void parseModuleRequires(RequiresEntry[] res, Element p) { - for (RequiresEntry re : res) { - Element er = new Element("Requires"); - er.setAttr("module", x.getCpString(re.requires_index)); - er.setAttr("flags", Integer.toString(re.requires_flags)); - p.add(er); - } - } - - private void parseModuleExports(ExportsEntry[] exports, Element p) { - Element ex = new Element("Exports"); - for (ExportsEntry export : exports) { - Element exto = new Element("exports"); - exto.setAttr("package", x.getCpString(export.exports_index)); - for (int idx : export.exports_to_index) { - exto.setAttr("module", x.getCpString(idx)); - } - ex.add(exto); - } - p.add(ex); - } - - private void parseModuleProvides(ProvidesEntry[] provides, Element p) { - Element ex = new Element("Provides"); - for (ProvidesEntry provide : provides) { - ex.setAttr("provides", x.getCpString(provide.provides_index)); - for (int idx : provide.with_index) { - ex.setAttr("with", x.getCpString(idx)); - } - } - p.add(ex); - } - - @Override - public Element visitModule(Module_attribute m, Element p) { - Element e = new Element(x.getCpString(m.attribute_name_index)); - parseModuleRequires(m.requires, e); - parseModuleExports(m.exports, e); - for (int idx : m.uses_index) { - Element ei = new Element("Uses"); - ei.setAttr("used_class", x.getCpString(idx)); - e.add(ei); - } - parseModuleProvides(m.provides, e); - p.add(e); - return null; - } - - @Override - public Element visitLocalVariableTypeTable(LocalVariableTypeTable_attribute lvtt, - Element p) { - String name = x.getCpString(lvtt.attribute_name_index); - for (LocalVariableTypeTable_attribute.Entry e : lvtt.local_variable_table) { - Element l = new Element(name); - l.setAttr("bci", "" + e.start_pc); - l.setAttr("span", "" + e.length); - l.setAttr("name", x.getCpString(e.name_index)); - l.setAttr("type", x.getCpString(e.signature_index)); - l.setAttr("slot", "" + e.index); - l.trimToSize(); - p.add(l); - } - return null; // already added to parent - } - - @Override - public Element visitMethodParameters(MethodParameters_attribute mp, Element p) { - String name = x.getCpString(mp.attribute_name_index); - for (MethodParameters_attribute.Entry e : mp.method_parameter_table) { - Element l = new Element(name); - l.setAttr("name", x.getCpString(e.name_index)); - l.setAttr("flag", "" + e.flags); - l.trimToSize(); - p.add(l); - } - return null; // already added to parent - } - private void parseAnnotation(Annotation anno, Element p) { - Element ea = new Element("Annotation"); - ea.setAttr("name", "" + x.getCpString(anno.type_index)); - for (Annotation.element_value_pair evp : anno.element_value_pairs) { - Element evpe = new Element("Element"); - evpe.setAttr("tag", "" + evp.value.tag); - evpe.setAttr("value", x.getCpString(evp.element_name_index)); - Element child = aev.visit(evp.value, evpe); - if (child != null) { - evpe.add(child); - } - ea.add(evpe); - } - ea.trimToSize(); - p.add(ea); - } - - private void parseAnnotations(Annotation[] ra, Element p) { - for (Annotation anno : ra) { - parseAnnotation(anno, p); - } - } - - @Override - public Element visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute rva, - Element p) { - Element e = new Element(x.getCpString(rva.attribute_name_index)); - parseAnnotations(rva.annotations, e); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute ria, - Element p) { - Element e = new Element(x.getCpString(ria.attribute_name_index)); - parseAnnotations(ria.annotations, e); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute rvpa, - Element p) { - Element e = new Element(x.getCpString(rvpa.attribute_name_index)); - for (Annotation[] pa : rvpa.parameter_annotations) { - parseAnnotations(pa, e); - } - p.add(e); - return null; - } - - @Override - public Element visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute ripa, - Element p) { - Element e = new Element(x.getCpString(ripa.attribute_name_index)); - for (Annotation[] pa : ripa.parameter_annotations) { - parseAnnotations(pa, e); - } - p.add(e); - return null; - } - - private void parsePosition(Position ap, Element p) { - Element te = new Element(); - switch (ap.type) { - case CLASS_TYPE_PARAMETER: // 0x00 - te.setName("CLASS_TYPE_PARAMETER"); - te.setAttr("idx", "" + ap.parameter_index); - break; - case METHOD_TYPE_PARAMETER: // 0x01 - te.setName("METHOD_TYPE_PARAMETER"); - te.setAttr("idx", "" + ap.parameter_index); - break; - case CLASS_EXTENDS: // 0x10 - te.setName("CLASS_EXTENDS"); - te.setAttr("idx", "" + ap.type_index); - break; - case CLASS_TYPE_PARAMETER_BOUND: // 0x11 - te.setName("CLASS_TYPE_PARAMETER_BOUND"); - te.setAttr("idx1", "" + ap.parameter_index); - te.setAttr("idx2", "" + ap.bound_index); - break; - case METHOD_TYPE_PARAMETER_BOUND: // 0x12 - te.setName("METHOD_TYPE_PARAMETER_BOUND"); - te.setAttr("idx1", "" + ap.parameter_index); - te.setAttr("idx2", "" + ap.bound_index); - break; - case FIELD: // 0x13 - te.setName("FIELD"); - break; - case METHOD_RETURN: // 0x14 - te.setName("METHOD_RETURN"); - break; - case METHOD_RECEIVER: // 0x15 - te.setName("METHOD_RECEIVER"); - break; - case METHOD_FORMAL_PARAMETER: // 0x16 - te.setName("METHOD_FORMAL_PARAMETER"); - te.setAttr("idx", "" + ap.parameter_index); - break; - case THROWS: // 0x17 - te.setName("THROWS"); - te.setAttr("idx", "" + ap.type_index); - break; - case LOCAL_VARIABLE: // 0x40 - te.setName("LOCAL_VARIABLE"); - for (int i = 0; i < ap.lvarIndex.length; i++) { - te.setAttr("lvar_idx_" + i, "" + ap.lvarIndex[i]); - te.setAttr("lvar_len_" + i, "" + ap.lvarLength[i]); - te.setAttr("lvar_off_" + i, "" + ap.lvarOffset[i]); - } - break; - case RESOURCE_VARIABLE: // 0x41 - te.setName("RESOURCE_VARIABLE"); - for (int i = 0; i < ap.lvarIndex.length ; i++) { - te.setAttr("lvar_idx_" + i, "" + ap.lvarIndex[i]); - te.setAttr("lvar_len_" + i, "" + ap.lvarLength[i]); - te.setAttr("lvar_off_" + i, "" + ap.lvarOffset[i]); - } - break; - case EXCEPTION_PARAMETER: // 0x42 - te.setName("EXCEPTION_PARAMETER"); - te.setAttr("idx", "" + ap.exception_index); - break; - case INSTANCEOF: // 0x43 - te.setName("INSTANCE_OF"); - te.setAttr("off", "" + ap.offset); - break; - case NEW: // 0x44 - te.setName("NEW"); - te.setAttr("off", "" + ap.offset); - break; - case CONSTRUCTOR_REFERENCE: // 0x45 - te.setName("CONSTRUCTOR_REFERENCE_RECEIVER"); - te.setAttr("off", "" + ap.offset); - break; - case METHOD_REFERENCE: // 0x46 - te.setName("METHOD_REFERENCE_RECEIVER"); - te.setAttr("off", "" + ap.offset); - break; - case CAST: // 0x47 - te.setName("CAST"); - te.setAttr("off", "" + ap.offset); - te.setAttr("idx", "" + ap.type_index); - break; - case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: // 0x48 - te.setName("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT"); - te.setAttr("off", "" + ap.offset); - te.setAttr("idx", "" + ap.type_index); - break; - case METHOD_INVOCATION_TYPE_ARGUMENT: // 0x49 - te.setName("METHOD_INVOCATION_TYPE_ARGUMENT"); - te.setAttr("off", "" + ap.offset); - te.setAttr("idx", "" + ap.type_index); - break; - case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: // 0x4A - te.setName("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT"); - te.setAttr("off", "" + ap.offset); - te.setAttr("idx", "" + ap.type_index); - break; - case METHOD_REFERENCE_TYPE_ARGUMENT: // 0x4B - te.setName("METHOD_REFERENCE_TYPE_ARGUMENT"); - te.setAttr("off", "" + ap.offset); - te.setAttr("idx", "" + ap.type_index); - break; - default: - throw new RuntimeException("not implemented"); - } - te.trimToSize(); - p.add(te); - } - private void parseTypeAnnotations(TypeAnnotation pa, Element p) { - Element pta = new Element("RuntimeVisibleTypeAnnotation"); - p.add(pta); - Position pos = pa.position; - parsePosition(pos, pta); - parseAnnotation(pa.annotation, pta); - } - - @Override - public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) { - Element e = new Element(x.getCpString(rvta.attribute_name_index)); - for (TypeAnnotation pa : rvta.annotations) { - parseTypeAnnotations(pa, e); - } - e.sort(); - p.add(e); - return null; - } - - @Override - public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) { - Element e = new Element(x.getCpString(rita.attribute_name_index)); - for (TypeAnnotation pa : rita.annotations) { - parseTypeAnnotations(pa, e); - } - e.sort(); - p.add(e); - return null; - } - - @Override - public Element visitSignature(Signature_attribute s, Element p) { - String aname = x.getCpString(s.attribute_name_index); - String sname = x.getCpString(s.signature_index); - Element se = new Element(aname); - se.add(sname); - se.trimToSize(); - p.add(se); - return null; - } - - @Override - public Element visitSourceDebugExtension(SourceDebugExtension_attribute sde, - Element p) { - String aname = x.getCpString(sde.attribute_name_index); - Element se = new Element(aname); - se.setAttr("val", sde.getValue()); - se.trimToSize(); - p.add(se); - return null; - } - - @Override - public Element visitSourceFile(SourceFile_attribute sf, Element p) { - String aname = x.getCpString(sf.attribute_name_index); - String sname = x.getCpString(sf.sourcefile_index); - Element se = new Element(aname); - se.add(sname); - se.trimToSize(); - p.add(se); - return null; - } - - @Override - public Element visitSourceID(SourceID_attribute sid, Element p) { - Element e = new Element(x.getCpString(sid.attribute_name_index)); - e.add(x.getCpString(sid.sourceID_index)); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitStackMap(StackMap_attribute sm, Element p) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public Element visitStackMapTable(StackMapTable_attribute smt, Element p) { - Element stackmap = new Element(x.getCpString(smt.attribute_name_index)); - for (StackMapTable_attribute.stack_map_frame f : smt.entries) { - StackMapVisitor smv = new StackMapVisitor(x, cf, stackmap); - stackmap.add(smv.visit(f)); - } - stackmap.trimToSize(); - p.add(stackmap); - return null; - } - - @Override - public Element visitSynthetic(Synthetic_attribute s, Element p) { - Element e = new Element(x.getCpString(s.attribute_name_index)); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitModuleHashes(ModuleHashes_attribute attr, Element p) { - Element e = new Element(x.getCpString(attr.attribute_name_index)); - e.setAttr("Algorithm", x.getCpString(attr.algorithm_index)); - for (Entry entry : attr.hashes_table) { - Element ee = new Element("Entry"); - String mn = x.getCpString(entry.module_name_index); - ee.setAttr("module_name", mn); - ee.setAttr("hash_length", "" + entry.hash.length); - StringBuilder sb = new StringBuilder(); - for (byte b: entry.hash) { - sb.append(String.format("%02x", b & 0xff)); - } - ee.setAttr("hash", sb.toString()); - ee.trimToSize(); - e.add(ee); - } - e.trimToSize(); - e.sort(); - p.add(e); - return null; - } - - @Override - public Element visitModuleMainClass(ModuleMainClass_attribute attr, Element p) { - Element e = new Element(x.getCpString(attr.attribute_name_index)); - e.add(x.getCpString(attr.main_class_index)); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitModuleResolution(ModuleResolution_attribute attr, Element p) { - Element e = new Element("ModuleResolution"); - e.setAttr("flags", Integer.toString(attr.resolution_flags)); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitModuleTarget(ModuleTarget_attribute attr, Element p) { - Element e = new Element(x.getCpString(attr.attribute_name_index)); - e.add(x.getCpString(attr.target_platform_index)); - e.trimToSize(); - p.add(e); - return null; - } - - @Override - public Element visitNestHost(NestHost_attribute attr, Element p) { - String aname = x.getCpString(attr.attribute_name_index); - String hname = x.getCpString(attr.top_index); - Element se = new Element(aname); - se.add(hname); - se.trimToSize(); - p.add(se); - return null; - } - - @Override - public Element visitNestMembers(NestMembers_attribute attr, Element p) { - Element ee = new Element(x.getCpString(attr.attribute_name_index)); - for (int idx : attr.members_indexes) { - Element n = new Element("Item"); - n.setAttr("class", x.getCpString(idx)); - ee.add(n); - } - ee.trimToSize(); - p.add(ee); - return null; - } -} - -class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor { - - final ClassFile cf; - final ClassReader x; - final Element parent; - - public StackMapVisitor(ClassReader x, ClassFile cf, Element parent) { - this.x = x; - this.cf = cf; - this.parent = parent; - } - - public Element visit(StackMapTable_attribute.stack_map_frame frame) { - return frame.accept(this, null); - } - - @Override - public Element visit_same_frame(same_frame sm_frm, Void p) { - Element e = new Element("SameFrame"); - e.setAttr("tag", "" + sm_frm.frame_type); - return e; - } - - @Override - public Element visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame s, Void p) { - Element e = new Element("SameLocals1StackItemFrame"); - e.setAttr("tag", "" + s.frame_type); - e.addAll(getVerificationTypeInfo("Stack", s.stack)); - e.trimToSize(); - return e; - } - - @Override - public Element visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended s, Void p) { - Element e = new Element("SameLocals1StackItemFrameExtended"); - e.setAttr("tag", "" + s.frame_type); - e.addAll(getVerificationTypeInfo("Stack", s.stack)); - e.trimToSize(); - return e; - } - - @Override - public Element visit_chop_frame(chop_frame c, Void p) { - Element e = new Element("Chop" + (251 - c.frame_type)); - e.setAttr("tag", "" + c.frame_type); - e.setAttr("offset", "" + c.offset_delta); - return e; - } - - @Override - public Element visit_same_frame_extended(same_frame_extended s, Void p) { - Element e = new Element("SameFrameExtended"); - e.setAttr("tag", "" + s.frame_type); - e.setAttr("offset", "" + s.offset_delta); - return e; - } - - @Override - public Element visit_append_frame(append_frame a, Void p) { - Element e = new Element("AppendFrame" + (a.frame_type - 251)); - e.setAttr("tag", "" + a.frame_type); - e.addAll(getVerificationTypeInfo("Local", a.locals)); - e.trimToSize(); - return e; - } - - @Override - public Element visit_full_frame(full_frame fl_frm, Void p) { - Element e = new Element("FullFrame"); - e.setAttr("tag", "" + fl_frm.frame_type); - e.addAll(getVerificationTypeInfo("Local", fl_frm.locals)); - e.trimToSize(); - return e; - } - - private Element getVerificationTypeInfo(String kind, - StackMapTable_attribute.verification_type_info velems[]) { - Element container = new Element(velems.length); - for (StackMapTable_attribute.verification_type_info v : velems) { - Element ve = null; - int offset = 0; - int index = 0; - switch (v.tag) { - case StackMapTable_attribute.verification_type_info.ITEM_Top: - ve = new Element("ITEM_Top"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Integer: - ve = new Element("ITEM_Integer"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Float: - ve = new Element("ITEM_Float"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Long: - ve = new Element("ITEM_Long"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Double: - ve = new Element("ITEM_Double"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Null: - ve = new Element("ITEM_Null"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: - ve = new Element("ITEM_Uninitialized"); - offset = ((StackMapTable_attribute.Uninitialized_variable_info) v).offset; - ve.setAttr("offset", "" + offset); - break; - case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis: - ve = new Element("ITEM_UnitializedtThis"); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Object: - ve = new Element("ITEM_Object"); - index = ((StackMapTable_attribute.Object_variable_info) v).cpool_index; - ve.setAttr("class", x.getCpString(index)); - break; - default: - ve = new Element("Unknown"); - } - Element kindE = new Element(kind); - kindE.setAttr("tag", "" + v.tag); - container.add(kindE); - kindE.add(ve); - } - container.trimToSize(); - return container; - } -} - -class InstructionVisitor implements Instruction.KindVisitor { - - final ClassReader x; - final ClassFile cf; - - public InstructionVisitor(ClassReader x, ClassFile cf) { - this.x = x; - this.cf = cf; - } - - public Element visit(Instruction i) { - Element ie = i.accept(this, null); - ie.trimToSize(); - return ie; - } - - @Override - public Element visitNoOperands(Instruction i, Void p) { - Opcode o = i.getOpcode(); - Element e = new Element(i.getMnemonic()); - if (o.opcode > 0xab && o.opcode <= 0xb1) { - e.setAttr("pc", "" + i.getPC()); - } - return e; - } - - @Override - public Element visitArrayType(Instruction i, TypeKind tk, Void p) { - Element ie = new Element(i.getMnemonic()); - ie.setAttr("num", "" + tk.value); - ie.setAttr("val", tk.name); - return ie; - } - - @Override - public Element visitBranch(Instruction i, int i1, Void p) { - Element ie = new Element(i.getMnemonic()); - ie.setAttr("lab", "" + (i.getPC() + i1)); - return ie; - } - - @Override - public Element visitConstantPoolRef(Instruction i, int i1, Void p) { - Element ie = new Element(i.getMnemonic()); - ie.setAttr("ref", x.getCpString(i1)); - return ie; - } - - @Override - public Element visitConstantPoolRefAndValue(Instruction i, int i1, int i2, Void p) { - // workaround for a potential bug in classfile - Element ie = new Element(i.getMnemonic()); - if (i.getOpcode().equals(Opcode.IINC_W)) { - ie.setAttr("loc", "" + i1); - ie.setAttr("num", "" + i2); - } else { - ie.setAttr("ref", x.getCpString(i1)); - ie.setAttr("val", "" + i2); - } - return ie; - } - - @Override - public Element visitLocal(Instruction i, int i1, Void p) { - Element ie = new Element(i.getMnemonic()); - ie.setAttr("loc", "" + i1); - return ie; - } - - @Override - public Element visitLocalAndValue(Instruction i, int i1, int i2, Void p) { - Element ie = new Element(i.getMnemonic()); - ie.setAttr("loc", "" + i1); - ie.setAttr("num", "" + i2); - return ie; - } - - @Override - public Element visitLookupSwitch(Instruction i, int i1, int i2, int[] ints, - int[] ints1, Void p) { - Element ie = new Element(i.getMnemonic()); - int pc = i.getPC(); - ie.setAttr("lab", "" + (pc + i1)); - for (int k = 0 ; k < i2 ; k++) { - Element c = new Element("Case"); - c.setAttr("num", "" + (ints[k])); - c.setAttr("lab", "" + (pc + ints1[k])); - c.trimToSize(); - ie.add(c); - } - return ie; - } - - @Override - public Element visitTableSwitch(Instruction i, int i1, int i2, int i3, - int[] ints, Void p) { - Element ie = new Element(i.getMnemonic()); - int pc = i.getPC(); - ie.setAttr("lab", "" + (pc + i1)); - for (int k : ints) { - Element c = new Element("Case"); - c.setAttr("num", "" + (k + i2)); - c.setAttr("lab", "" + (pc + k)); - c.trimToSize(); - ie.add(c); - } - return ie; - } - - @Override - public Element visitValue(Instruction i, int i1, Void p) { - Element ie = new Element(i.getMnemonic()); - ie.setAttr("num", "" + i1); - return ie; - } - - @Override - public Element visitUnknown(Instruction i, Void p) { - Element e = new Element(i.getMnemonic()); - e.setAttr("pc", "" + i.getPC()); - e.setAttr("opcode", "" + i.getOpcode().opcode); - return e; - } -} - -class AnnotationsElementVisitor implements Annotation.element_value.Visitor { - final ClassReader x; - final ClassFile cf; - - public AnnotationsElementVisitor(ClassReader x, ClassFile cf) { - this.x = x; - this.cf = cf; - } - - public Element visit(Annotation.element_value v, Element p) { - return v.accept(this, p); - } - - @Override - public Element visitPrimitive(Primitive_element_value e, Element p) { - Element el = new Element("String"); - el.setAttr("val", x.getCpString(e.const_value_index)); - el.trimToSize(); - return el; - } - - @Override - public Element visitEnum(Enum_element_value e, Element p) { - Element el = new Element("Enum"); - el.setAttr("name", x.getCpString(e.const_name_index)); - el.setAttr("type", x.getCpString(e.type_name_index)); - el.trimToSize(); - return el; - } - - @Override - public Element visitClass(Class_element_value c, Element p) { - Element el = new Element("Class"); - el.setAttr("name", x.getCpString(c.class_info_index)); - el.trimToSize(); - return el; - } - - @Override - public Element visitAnnotation(Annotation_element_value a, Element p) { - Element el = new Element("Annotation"); - Annotation anno = a.annotation_value; - for (Annotation.element_value_pair evp : anno.element_value_pairs) { - Element child = visit(evp.value, el); - if (child != null) { - el.add(child); - } - } - el.trimToSize(); - return el; - } - - @Override - public Element visitArray(Array_element_value a, Element p) { - Element el = new Element("Array"); - for (Annotation.element_value v : a.values) { - Element child = visit(v, el); - if (child != null) { - el.add(child); - } - } - el.trimToSize(); - return el; - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java b/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java deleted file mode 100644 index 160f4e5d514..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -import java.util.*; -/* - * @author jrose - */ -public class CommandLineParser { - - public CommandLineParser(String optionString) { - setOptionMap(optionString); - } - TreeMap optionMap; - - public void setOptionMap(String options) { - // Convert options string into optLines dictionary. - TreeMap optmap = new TreeMap(); - loadOptmap: - for (String optline : options.split("\n")) { - String[] words = optline.split("\\p{Space}+"); - if (words.length == 0) { - continue loadOptmap; - } - String opt = words[0]; - words[0] = ""; // initial word is not a spec - if (opt.length() == 0 && words.length >= 1) { - opt = words[1]; // initial "word" is empty due to leading ' ' - words[1] = ""; - } - if (opt.length() == 0) { - continue loadOptmap; - } - String[] prevWords = optmap.put(opt, words); - if (prevWords != null) { - throw new RuntimeException("duplicate option: " - + optline.trim()); - } - } - optionMap = optmap; - } - - public String getOptionMap() { - TreeMap optmap = optionMap; - StringBuffer sb = new StringBuffer(); - for (String opt : optmap.keySet()) { - sb.append(opt); - for (String spec : optmap.get(opt)) { - sb.append(' ').append(spec); - } - sb.append('\n'); - } - return sb.toString(); - } - - /** - * Remove a set of command-line options from args, - * storing them in the properties map in a canonicalized form. - */ - public String parse(List args, Map properties) { - //System.out.println(args+" // "+properties); - - String resultString = null; - TreeMap optmap = optionMap; - - // State machine for parsing a command line. - ListIterator argp = args.listIterator(); - ListIterator pbp = new ArrayList().listIterator(); - doArgs: - for (;;) { - // One trip through this loop per argument. - // Multiple trips per option only if several options per argument. - String arg; - if (pbp.hasPrevious()) { - arg = pbp.previous(); - pbp.remove(); - } else if (argp.hasNext()) { - arg = argp.next(); - } else { - // No more arguments at all. - break doArgs; - } - tryOpt: - for (int optlen = arg.length();; optlen--) { - // One time through this loop for each matching arg prefix. - String opt; - // Match some prefix of the argument to a key in optmap. - findOpt: - for (;;) { - opt = arg.substring(0, optlen); - if (optmap.containsKey(opt)) { - break findOpt; - } - if (optlen == 0) { - break tryOpt; - } - // Decide on a smaller prefix to search for. - SortedMap pfxmap = optmap.headMap(opt); - // pfxmap.lastKey is no shorter than any prefix in optmap. - int len = pfxmap.isEmpty() ? 0 : pfxmap.lastKey().length(); - optlen = Math.min(len, optlen - 1); - opt = arg.substring(0, optlen); - // (Note: We could cut opt down to its common prefix with - // pfxmap.lastKey, but that wouldn't save many cycles.) - } - opt = opt.intern(); - assert (arg.startsWith(opt)); - assert (opt.length() == optlen); - String val = arg.substring(optlen); // arg == opt+val - - // Execute the option processing specs for this opt. - // If no actions are taken, then look for a shorter prefix. - boolean didAction = false; - boolean isError = false; - - int pbpMark = pbp.nextIndex(); // in case of backtracking - String[] specs = optmap.get(opt); - eachSpec: - for (String spec : specs) { - if (spec.length() == 0) { - continue eachSpec; - } - if (spec.startsWith("#")) { - break eachSpec; - } - int sidx = 0; - char specop = spec.charAt(sidx++); - - // Deal with '+'/'*' prefixes (spec conditions). - boolean ok; - switch (specop) { - case '+': - // + means we want an non-empty val suffix. - ok = (val.length() != 0); - specop = spec.charAt(sidx++); - break; - case '*': - // * means we accept empty or non-empty - ok = true; - specop = spec.charAt(sidx++); - break; - default: - // No condition prefix means we require an exact - // match, as indicated by an empty val suffix. - ok = (val.length() == 0); - break; - } - if (!ok) { - continue eachSpec; - } - - String specarg = spec.substring(sidx); - switch (specop) { - case '.': // terminate the option sequence - resultString = (specarg.length() != 0) ? specarg.intern() : opt; - break doArgs; - case '?': // abort the option sequence - resultString = (specarg.length() != 0) ? specarg.intern() : arg; - isError = true; - break eachSpec; - case '@': // change the effective opt name - opt = specarg.intern(); - break; - case '>': // shift remaining arg val to next arg - pbp.add(specarg + val); // push a new argument - val = ""; - break; - case '!': // negation option - String negopt = (specarg.length() != 0) ? specarg.intern() : opt; - properties.remove(negopt); - properties.put(negopt, null); // leave placeholder - didAction = true; - break; - case '$': // normal "boolean" option - String boolval; - if (specarg.length() != 0) { - // If there is a given spec token, store it. - boolval = specarg; - } else { - String old = properties.get(opt); - if (old == null || old.length() == 0) { - boolval = "1"; - } else { - // Increment any previous value as a numeral. - boolval = "" + (1 + Integer.parseInt(old)); - } - } - properties.put(opt, boolval); - didAction = true; - break; - case '=': // "string" option - case '&': // "collection" option - // Read an option. - boolean append = (specop == '&'); - String strval; - if (pbp.hasPrevious()) { - strval = pbp.previous(); - pbp.remove(); - } else if (argp.hasNext()) { - strval = argp.next(); - } else { - resultString = arg + " ?"; - isError = true; - break eachSpec; - } - if (append) { - String old = properties.get(opt); - if (old != null) { - // Append new val to old with embedded delim. - String delim = specarg; - if (delim.length() == 0) { - delim = " "; - } - strval = old + specarg + strval; - } - } - properties.put(opt, strval); - didAction = true; - break; - default: - throw new RuntimeException("bad spec for " - + opt + ": " + spec); - } - } - - // Done processing specs. - if (didAction && !isError) { - continue doArgs; - } - - // The specs should have done something, but did not. - while (pbp.nextIndex() > pbpMark) { - // Remove anything pushed during these specs. - pbp.previous(); - pbp.remove(); - } - - if (isError) { - throw new IllegalArgumentException(resultString); - } - - if (optlen == 0) { - // We cannot try a shorter matching option. - break tryOpt; - } - } - - // If we come here, there was no matching option. - // So, push back the argument, and return to caller. - pbp.add(arg); - break doArgs; - } - // Report number of arguments consumed. - args.subList(0, argp.nextIndex()).clear(); - // Report any unconsumed partial argument. - while (pbp.hasPrevious()) { - args.add(0, pbp.previous()); - } - //System.out.println(args+" // "+properties+" -> "+resultString); - return resultString; - } -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/TokenList.java b/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/TokenList.java deleted file mode 100644 index bd7e5ee104f..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/TokenList.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -import java.util.*; - -/** - * A List of Strings each representing a word or token. - * This object itself is a CharSequence whose characters consist - * of all the tokens, separated by blanks. - * - * @author jrose - */ -public class TokenList extends ArrayList implements CharSequence { - - protected String separator; - protected boolean frozen; - - public TokenList() { - this.separator = " "; - } - - public TokenList(Collection tokens) { - super(tokens.size()); - this.separator = " "; - addTokens(tokens); - } - - public TokenList(Collection tokens, String separator) { - super(tokens.size()); - this.separator = separator; - addTokens(tokens); - } - - public TokenList(Object[] tokens) { - super(tokens.length); - this.separator = " "; - addTokens(tokens, 0, tokens.length); - } - - public TokenList(Object[] tokens, int beg, int end) { - super(end - beg); // capacity - this.separator = " "; - addTokens(tokens, beg, end); - } - - public TokenList(Object[] tokens, int beg, int end, String separator) { - super(end - beg); // capacity - this.separator = separator; - addTokens(tokens, beg, end); - } - - public TokenList(String tokenStr) { - this(tokenStr, " ", false); - } - - public TokenList(String tokenStr, String separator) { - this(tokenStr, separator, true); - } - - public TokenList(String tokenStr, String separator, boolean allowNulls) { - super(tokenStr.length() / 5); - this.separator = separator; - addTokens(tokenStr, allowNulls); - } - static public final TokenList EMPTY; - - static { - TokenList tl = new TokenList(new Object[0]); - tl.freeze(); - EMPTY = tl; - } - - public void freeze() { - if (!frozen) { - for (ListIterator i = listIterator(); i.hasNext();) { - i.set(i.next().toString()); - } - trimToSize(); - frozen = true; - } - } - - public boolean isFrozen() { - return frozen; - } - - void checkNotFrozen() { - if (isFrozen()) { - throw new UnsupportedOperationException("cannot modify frozen TokenList"); - } - } - - public String getSeparator() { - return separator; - } - - public void setSeparator(String separator) { - checkNotFrozen(); - this.separator = separator; - } - - /// All normal List mutators must check the frozen bit: - public String set(int index, String o) { - checkNotFrozen(); - return super.set(index, o); - } - - public boolean add(String o) { - checkNotFrozen(); - return super.add(o); - } - - public void add(int index, String o) { - checkNotFrozen(); - super.add(index, o); - } - - public boolean addAll(Collection c) { - checkNotFrozen(); - return super.addAll(c); - } - - public boolean addAll(int index, Collection c) { - checkNotFrozen(); - return super.addAll(index, c); - } - - public boolean remove(Object o) { - checkNotFrozen(); - return super.remove(o); - } - - public String remove(int index) { - checkNotFrozen(); - return super.remove(index); - } - - public void clear() { - checkNotFrozen(); - super.clear(); - } - - /** Add a collection of tokens to the list, applying toString to each. */ - public boolean addTokens(Collection tokens) { - // Note that if this sequence is empty, no tokens are added. - // This is different from adding a null string, which is - // a single token. - boolean added = false; - for (Object token : tokens) { - add(token.toString()); - added = true; - } - return added; - } - - public boolean addTokens(Object[] tokens, int beg, int end) { - boolean added = false; - for (int i = beg; i < end; i++) { - add(tokens[i].toString()); - added = true; - } - return added; - } - - public boolean addTokens(String tokenStr) { - return addTokens(tokenStr, false); - } - - public boolean addTokens(String tokenStr, boolean allowNulls) { - boolean added = false; - int pos = 0, limit = tokenStr.length(), sep = limit; - while (pos < limit) { - sep = tokenStr.indexOf(separator, pos); - if (sep < 0) { - sep = limit; - } - if (sep == pos) { - if (allowNulls) { - add(""); - added = true; - } - pos += separator.length(); - } else { - add(tokenStr.substring(pos, sep)); - added = true; - pos = sep + separator.length(); - } - } - if (allowNulls && sep < limit) { - // Input was something like "tok1 tok2 ". - add(""); - added = true; - } - return added; - } - - public boolean addToken(Object token) { - return add(token.toString()); - } - - /** Format the token string, using quotes and escapes. - * Quotes must contain an odd number of 3 or more elements, - * a sequence of begin/end quote pairs, plus a superquote. - * For each token, the first begin/end pair is used for - * which the end quote does not occur in the token. - * If the token contains all end quotes, the last pair - * is used, with all occurrences of the end quote replaced - * by the superquote. If an end quote is the empty string, - * the separator is used instead. - */ - public String format(String separator, String[] quotes) { - return ""; //@@ - } - protected int[] lengths; - protected static final int MODC = 0, HINT = 1, BEG0 = 2, END0 = 3; - - // Layout of lengths: - // { modCount, hint, -1==beg[0], end[0]==beg[1], ..., length } - // Note that each beg[i]..end[i] span includes a leading separator, - // which is not part of the corresponding token. - protected final CharSequence getCS(int i) { - return (CharSequence) get(i); - } - - // Produce (and cache) an table of indexes for each token. - protected int[] getLengths() { - int[] lengths = this.lengths; - ; - int sepLength = separator.length(); - if (lengths == null || lengths[MODC] != modCount) { - int size = this.size(); - lengths = new int[END0 + size + (size == 0 ? 1 : 0)]; - lengths[MODC] = modCount; - int end = -sepLength; // cancels leading separator - lengths[BEG0] = end; - for (int i = 0; i < size; i++) { - end += sepLength; // count leading separator - end += getCS(i).length(); - lengths[END0 + i] = end; - } - this.lengths = lengths; - } - return lengths; - } - - public int length() { - int[] lengths = getLengths(); - return lengths[lengths.length - 1]; - } - - // Which token does the given index belong to? - protected int which(int i) { - if (i < 0) { - return -1; - } - int[] lengths = getLengths(); - for (int hint = lengths[HINT];; hint = 0) { - for (int wh = hint; wh < lengths.length - END0; wh++) { - int beg = lengths[BEG0 + wh]; - int end = lengths[END0 + wh]; - if (i >= beg && i < end) { - lengths[HINT] = wh; - return wh; - } - } - if (hint == 0) { - return size(); // end of the line - } - } - } - - public char charAt(int i) { - if (i < 0) { - return "".charAt(i); - } - int wh = which(i); - int beg = lengths[BEG0 + wh]; - int j = i - beg; - int sepLength = separator.length(); - if (j < sepLength) { - return separator.charAt(j); - } - return getCS(wh).charAt(j - sepLength); - } - - public CharSequence subSequence(int beg, int end) { - //System.out.println("i: "+beg+".."+end); - if (beg == end) { - return ""; - } - if (beg < 0) { - charAt(beg); // raise exception - } - if (beg > end) { - charAt(-1); // raise exception - } - int begWh = which(beg); - int endWh = which(end); - if (endWh == size() || end == lengths[BEG0 + endWh]) { - --endWh; - } - //System.out.println("wh: "+begWh+".."+endWh); - int begBase = lengths[BEG0 + begWh]; - int endBase = lengths[BEG0 + endWh]; - int sepLength = separator.length(); - int begFrag = 0; - if ((beg - begBase) < sepLength) { - begFrag = sepLength - (beg - begBase); - beg += begFrag; - } - int endFrag = 0; - if ((end - endBase) < sepLength) { - endFrag = (end - endBase); - end = endBase; - endBase = lengths[BEG0 + --endWh]; - } - if (false) { - System.out.print("beg[wbf]end[wbf]"); - int pr[] = {begWh, begBase, begFrag, beg, endWh, endBase, endFrag, end}; - for (int k = 0; k < pr.length; k++) { - System.out.print((k == 4 ? " " : " ") + (pr[k])); - } - System.out.println(); - } - if (begFrag > 0 && (end + endFrag) - begBase <= sepLength) { - // Special case: Slice the separator. - beg -= begFrag; - end += endFrag; - return separator.substring(beg - begBase, end - begBase); - } - if (begWh == endWh && (begFrag + endFrag) == 0) { - // Special case: Slice a single token. - return getCS(begWh).subSequence(beg - begBase - sepLength, - end - endBase - sepLength); - } - Object[] subTokens = new Object[1 + (endWh - begWh) + 1]; - int fillp = 0; - if (begFrag == sepLength) { - // Insert a leading null token to force an initial separator. - subTokens[fillp++] = ""; - begFrag = 0; - } - for (int wh = begWh; wh <= endWh; wh++) { - CharSequence cs = getCS(wh); - if (wh == begWh || wh == endWh) { - // Slice it. - int csBeg = (wh == begWh) ? (beg - begBase) - sepLength : 0; - int csEnd = (wh == endWh) ? (end - endBase) - sepLength : cs.length(); - cs = cs.subSequence(csBeg, csEnd); - if (begFrag > 0 && wh == begWh) { - cs = separator.substring(sepLength - begFrag) + cs; - } - if (endFrag > 0 && wh == endWh) { - cs = cs.toString() + separator.substring(0, endFrag); - } - } - subTokens[fillp++] = cs; - } - return new TokenList(subTokens, 0, fillp, separator); - } - - /** Returns the concatenation of all tokens, - * with intervening separator characters. - */ - public String toString() { - StringBuilder buf = new StringBuilder(length()); - int size = this.size(); - for (int i = 0; i < size; i++) { - if (i > 0) { - buf.append(separator); - } - buf.append(get(i)); - } - return buf.toString(); - } - - /*---- TESTING CODE ---- - public static void main(String[] av) { - if (av.length == 0) av = new String[]{"one", "2", "", "four"}; - TokenList ts = new TokenList(); - final String SEP = ", "; - ts.setSeparator(SEP); - for (int i = -1; i < av.length; i++) { - if (i >= 0) ts.addToken(av[i]); - { - TokenList tsCopy = new TokenList(ts.toString(), SEP); - if (!tsCopy.equals(ts)) { - tsCopy.setSeparator(")("); - System.out.println("!= ("+tsCopy+")"); - } - } - { - TokenList tsBar = new TokenList(ts, "|"); - tsBar.add(0, "["); - tsBar.add("]"); - System.out.println(tsBar); - } - if (false) { - int[] ls = ts.getLengths(); - System.out.println("ts: "+ts); - System.out.print("ls: {"); - for (int j = 0; j < ls.length; j++) System.out.print(" "+ls[j]); - System.out.println(" }"); - } - assert0(ts.size() == i+1); - assert0(i < 0 || ts.get(i) == av[i]); - String tss = ts.toString(); - int tslen = tss.length(); - assert0(ts.length() == tss.length()); - for (int n = 0; n < tslen; n++) { - assert0(ts.charAt(n) == tss.charAt(n)); - } - for (int j = 0; j < tslen; j++) { - for (int k = tslen; k >= j; k--) { - CharSequence sub = ts.subSequence(j, k); - //System.out.println("|"+sub+"|"); - assert0(sub.toString().equals(tss.substring(j, k))); - } - } - } - } - static void assert0(boolean z) { - if (!z) throw new RuntimeException("assert failed"); - } - // ---- TESTING CODE ----*/ -} diff --git a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java b/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java deleted file mode 100644 index a453bb45a92..00000000000 --- a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java +++ /dev/null @@ -1,4328 +0,0 @@ -/* - * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -// XML Implementation packages: -import java.util.*; - -import java.io.Reader; -import java.io.Writer; -import java.io.OutputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.StringReader; - -import java.io.IOException; - -import org.xml.sax.XMLReader; -import org.xml.sax.InputSource; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.Attributes; -import org.xml.sax.ext.LexicalHandler; -import org.xml.sax.helpers.AttributesImpl; - -/** - * A kit of methods and classes useful for manipulating XML trees in - * memory. They are very compact and easy to use. An XML element - * occupies six pointers of overhead (like two arrays) plus a pointer - * for its name, each attribute name and value, and each sub-element. - * Many useful XML operations (or Lisp-like calls) can be accomplished - * with a single method call on an element itself. - *

    - * There is strong integration with the Java collection classes. - * There are viewing and conversion operators to and from various - * collection types. Elements directly support list iterators. - * Most List methods work analogously on elements. - *

    - * Because of implementation compromises, these XML trees are less - * functional than many standard XML classes. - *

      - *
    • There are no parent or sibling pointers in the tree.
    • - *
    • Attribute names are simple strings, with no namespaces.
    • - *
    • There is no internal support for schemas or validation.
    • - *
    - *

    - * Here is a summary of functionality in XMLKit. - * (Overloaded groups of methods are summarized by marking some - * arguments optional with their default values. Some overloaded - * arguments are marked with their alternative types separated by - * a bar "|". Arguments or return values for which a null is - * specially significant are marked by an alternative "|null". - * Accessors which have corresponding setters are marked - * by "/set". Removers which have corresponding retainers are marked - * by "/retain".) - *

    - * --- element construction
    - * new Element(int elemCapacity=4), String name=""
    - * new Element(String name, String[] attrs={}, Element[] elems={}, int elemCapacity=4)
    - * new Element(String name, String[] attrs, Object[] elems, int elemCapacity=4)
    - * new Element(Element original) // shallow copy
    - * new Element(String name="", Collection elems) // coercion
    - *
    - * Element shallowCopy()
    - * Element shallowFreeze() // side-effecting
    - * Element deepCopy()
    - * Element deepFreeze() // not side-effecting
    - *
    - * EMPTY // frozen empty anonymous element
    - * void ensureExtraCapacity(int)
    - * void trimToSize()
    - * void sortAttrs() // sort by key
    - *
    - * --- field accessors
    - * String getName()/set
    - * int size()
    - * boolean isEmpty()
    - * boolean isFrozen()
    - * boolean isAnonymous()
    - * int getExtraCapacity()/set
    - * int attrSize()
    - *
    - * --- attribute accessors
    - * String getAttr(int i)/set
    - * String getAttrName(int i)
    - *
    - * String getAttr(String key)/set
    - * List getAttrList(String key)/set
    - * Number getAttrNumber(String key)/set
    - * long getAttrLong(String key)/set
    - * double getAttrDouble(String key)/set
    - *
    - * String getAttr(String key, String dflt=null)
    - * long getAttrLong(String key, long dflt=0)
    - * double getAttrDouble(String key, double dflt=0)
    - *
    - * Element copyAttrsOnly()
    - * Element getAttrs()/set => <><key>value</key>...</>
    - * void addAttrs(Element attrs)
    - *
    - * void removeAttr(int i)
    - * void clearAttrs()
    - *
    - * --- element accessors
    - * Object get(int i)/set
    - * Object getLast() | null
    - * Object[] toArray()
    - * Element copyContentOnly()
    - *
    - * void add(int i=0, Object subElem)
    - * int addAll(int i=0, Collection | Element elems)
    - * int addContent(int i=0, TokenList|Element|Object|null)
    - * void XMLKit.addContent(TokenList|Element|Object|null, Collection sink|null)
    - *
    - * void clear(int beg=0, int end=size)
    - * void sort(Comparator=contentOrder())
    - * void reverse()
    - * void shuffle(Random rnd=(anonymous))
    - * void rotate(int distance)
    - * Object min/max(Comparator=contentOrder())
    - *
    - * --- text accessors
    - * CharSequence getText()/set
    - * CharSequence getUnmarkedText()
    - * int addText(int i=size, CharSequence)
    - * void trimText();
    - *
    - * --- views
    - * List asList() // element view
    - * ListIterator iterator()
    - * PrintWriter asWriter()
    - * Map asAttrMap()
    - * Iterable texts()
    - * Iterable elements()
    - * Iterable partsOnly(Class)
    - * String[] toStrings()
    - *
    - * --- queries
    - * boolean equals(Element | Object)
    - * int compareTo(Element | Object)
    - * boolean equalAttrs(Element)
    - * int hashCode()
    - * boolean isText() // every sub-elem is CharSequence
    - * boolean hasText() // some sub-elem is CharSequence
    - *
    - * boolean contains(Object)
    - * boolean containsAttr(String)
    - *
    - * int indexOf(Object)
    - * int indexOf(Filter, int fromIndex=0)
    - * int lastIndexOf(Object)
    - * int lastIndexOf(Filter, int fromIndex=size-1)
    - *
    - * int indexOfAttr(String)
    - *
    - * // finders, removers, and replacers do addContent of each filtered value
    - * // (i.e., TokenLists and anonymous Elements are broken out into their parts)
    - * boolean matches(Filter)
    - *
    - * Object find(Filter, int fromIndex=0)
    - * Object findLast(Filter, int fromIndex=size-1)
    - * Element findAll(Filter, int fromIndex=0 & int toIndex=size)
    - * int findAll(Filter, Collection sink | null, int fromIndex=0 & int toIndex=size)
    - *
    - * Element removeAllInTree(Filter)/retain
    - * int findAllInTree(Filter, Collection sink | null)
    - * int countAllInTree(Filter)
    - * Element removeAllInTree(Filter)/retain
    - * int removeAllInTree(Filter, Collection sink | null)/retain
    - * void replaceAllInTree(Filter)
    - *
    - * Element findElement(String name=any)
    - * Element findAllElements(String name=any)
    - *
    - * Element findWithAttr(String key, String value=any)
    - * Element findAllWithAttr(String key, String value=any)
    - *
    - * Element removeElement(String name=any)
    - * Element removeAllElements(String name=any)/retain
    - *
    - * Element removeWithAttr(String key, String value=any)
    - * Element removeAllWithAttr(String key, String value=any)/retain
    - *
    - * //countAll is the same as findAll but with null sink
    - * int countAll(Filter)
    - * int countAllElements(String name=any)
    - * int countAllWithAttr(String key, String value=any)
    - *
    - * void replaceAll(Filter, int fromIndex=0 & int toIndex=size)
    - * void replaceAllInTree(Filter)
    - * void XMLKit.replaceAll(Filter, List target) //if(fx){remove x;addContent fx}
    - *
    - * --- element mutators
    - * boolean remove(Object)
    - * Object remove(int)
    - * Object removeLast() | null
    - *
    - * Object remove(Filter, int fromIndex=0)
    - * Object removeLast(Filter, int fromIndex=size-1)
    - * Element sink = removeAll(Filter, int fromIndex=0 & int toIndex=size)/retain
    - * int count = removeAll(Filter, int fromIndex=0 & int toIndex=size, Collection sink | null)/retain
    - *
    - * Element removeAllElements(String name=any)
    - *
    - * --- attribute mutators
    - * ??int addAllAttrsFrom(Element attrSource)
    - *
    - * --- parsing and printing
    - * void tokenize(String delims=whitespace, returnDelims=false)
    - * void writeTo(Writer)
    - * void writePrettyTo(Writer)
    - * String prettyString()
    - * String toString()
    - *
    - * ContentHandler XMLKit.makeBuilder(Collection sink, tokenizing=false, makeFrozen=false) // for standard XML parser
    - * Element XMLKit.readFrom(Reader, tokenizing=false, makeFrozen=false)
    - * void XMLKit.prettyPrintTo(Writer | OutputStream, Element)
    - * class XMLKit.Printer(Writer) { void print/Recursive(Element) }
    - * void XMLKit.output(Object elem, ContentHandler, LexicalHandler=null)
    - * void XMLKit.writeToken(String, char quote, Writer)
    - * void XMLKit.writeCData(String, Writer)
    - * Number XMLKit.convertToNumber(String, Number dflt=null)
    - * long XMLKit.convertToLong(String, long dflt=0)
    - * double XMLKit.convertToDouble(String, double dflt=0)
    - *
    - * --- filters
    - * XMLKit.ElementFilter { Element filter(Element) }
    - * XMLKit.elementFilter(String name=any | Collection nameSet)
    - * XMLKit.AttrFilter(String key) { boolean test(String value) }
    - * XMLKit.attrFilter(String key, String value=any)
    - * XMLKit.attrFilter(Element matchThis, String key)
    - * XMLKit.classFilter(Class)
    - * XMLKit.textFilter() // matches any CharSequence
    - * XMLKit.specialFilter() // matches any Special element
    - * XMLKit.methodFilter(Method m, Object[] args=null, falseResult=null)
    - * XMLKit.testMethodFilter(Method m, Object[] args=null)
    - * XMLKit.not(Filter) // inverts sense of Filter
    - * XMLKit.and(Filter&Filter | Filter[])
    - * XMLKit.or(Filter&Filter | Filter[])
    - * XMLKit.stack(Filter&Filter | Filter[]) // result is (fx && g(fx))
    - * XMLKit.content(Filter, Collection sink) // copies content to sink
    - * XMLKit.replaceInTree(Filter pre, Filter post=null) // pre-replace else recur
    - * XMLKit.findInTree(Filter pre, Collection sink=null) // pre-find else recur
    - * XMLKit.nullFilter() // ignores input, always returns null (i.e., false)
    - * XMLKit.selfFilter( ) // always returns input (i.e., true)
    - * XMLKit.emptyFilter() // ignores input, always returns EMPTY
    - * XMLKit.constantFilter(Object) // ignores input, always returns constant
    - *
    - * --- misc
    - * Comparator XMLKit.contentOrder() // for comparing/sorting mixed content
    - * Method XMLKit.Element.method(String name) // returns Element method
    - * 
    - * - * @author jrose - */ -public abstract class XMLKit { - - private XMLKit() { - } - // We need at least this much slop if the element is to stay unfrozen. - static final int NEED_SLOP = 1; - static final Object[] noPartsFrozen = {}; - static final Object[] noPartsNotFrozen = new Object[NEED_SLOP]; - static final String WHITESPACE_CHARS = " \t\n\r\f"; - static final String ANON_NAME = new String("*"); // unique copy of "*" - - public static final class Element implements Comparable, Iterable { - // Note: Does not implement List, because it has more - // significant parts besides its sub-elements. Therefore, - // hashCode and equals must be more distinctive than Lists. - - // of element - String name; - // number of child elements, in parts[0..size-1] - int size; - // The parts start with child elements:: {e0, e1, e2, ...}. - // Following that are optional filler elements, all null. - // Following that are attributes as key/value pairs. - // They are in reverse: {...key2, val2, key1, val1, key0, val0}. - // Child elements and attr keys and values are never null. - Object[] parts; - - // Build a partially-constructed node. - // Caller is responsible for initializing promised attributes. - Element(String name, int size, int capacity) { - this.name = name.toString(); - this.size = size; - assert (size <= capacity); - this.parts = capacity > 0 ? new Object[capacity] : noPartsFrozen; - } - - /** An anonymous, empty element. - * Optional elemCapacity argument is expected number of sub-elements. - */ - public Element() { - this(ANON_NAME, 0, NEED_SLOP + 4); - } - - public Element(int extraCapacity) { - this(ANON_NAME, 0, NEED_SLOP + Math.max(0, extraCapacity)); - } - - /** An empty element with the given name. - * Optional extraCapacity argument is expected number of sub-elements. - */ - public Element(String name) { - this(name, 0, NEED_SLOP + 4); - } - - public Element(String name, int extraCapacity) { - this(name, 0, NEED_SLOP + Math.max(0, extraCapacity)); - } - - /** An empty element with the given name and attributes. - * Optional extraCapacity argument is expected number of sub-elements. - */ - public Element(String name, String... attrs) { - this(name, attrs, (Element[]) null, 0); - } - - public Element(String name, String[] attrs, int extraCapacity) { - this(name, attrs, (Element[]) null, extraCapacity); - } - - /** An empty element with the given name and sub-elements. - * Optional extraCapacity argument is expected extra sub-elements. - */ - public Element(String name, Element... elems) { - this(name, (String[]) null, elems, 0); - } - - public Element(String name, Element[] elems, int extraCapacity) { - this(name, (String[]) null, elems, extraCapacity); - } - - /** An empty element with the given name, attributes, and sub-elements. - * Optional extraCapacity argument is expected extra sub-elements. - */ - public Element(String name, String[] attrs, Object... elems) { - this(name, attrs, elems, 0); - } - - public Element(String name, String[] attrs, Object[] elems, int extraCapacity) { - this(name, 0, - ((elems == null) ? 0 : elems.length) - + Math.max(0, extraCapacity) - + NEED_SLOP - + ((attrs == null) ? 0 : attrs.length)); - int ne = ((elems == null) ? 0 : elems.length); - int na = ((attrs == null) ? 0 : attrs.length); - int fillp = 0; - for (int i = 0; i < ne; i++) { - if (elems[i] != null) { - parts[fillp++] = elems[i]; - } - } - size = fillp; - for (int i = 0; i < na; i += 2) { - setAttr(attrs[i + 0], attrs[i + 1]); - } - } - - public Element(Collection c) { - this(c.size()); - addAll(c); - } - - public Element(String name, Collection c) { - this(name, c.size()); - addAll(c); - } - - /** Shallow copy. Same as old.shallowCopy(). - * Optional extraCapacity argument is expected extra sub-elements. - */ - public Element(Element old) { - this(old, 0); - } - - public Element(Element old, int extraCapacity) { - this(old.name, old.size, - old.size - + Math.max(0, extraCapacity) + NEED_SLOP - + old.attrLength()); - // copy sub-elements - System.arraycopy(old.parts, 0, parts, 0, size); - int alen = parts.length - - (size + Math.max(0, extraCapacity) + NEED_SLOP); - // copy attributes - System.arraycopy(old.parts, old.parts.length - alen, - parts, parts.length - alen, - alen); - assert (!isFrozen()); - } - - /** Shallow copy. Same as new Element(this). */ - public Element shallowCopy() { - return new Element(this); - } - static public final Element EMPTY = new Element(ANON_NAME, 0, 0); - - Element deepFreezeOrCopy(boolean makeFrozen) { - if (makeFrozen && isFrozen()) { - return this; // no need to copy it - } - int alen = attrLength(); - int plen = size + (makeFrozen ? 0 : NEED_SLOP) + alen; - Element copy = new Element(name, size, plen); - // copy attributes - System.arraycopy(parts, parts.length - alen, copy.parts, plen - alen, alen); - // copy sub-elements - for (int i = 0; i < size; i++) { - Object e = parts[i]; - String str; - if (e instanceof Element) { // recursion is common case - e = ((Element) e).deepFreezeOrCopy(makeFrozen); - } else if (makeFrozen) { - // Freeze StringBuffers, etc. - e = fixupString(e); - } - copy.setRaw(i, e); - } - return copy; - } - - /** Returns new Element(this), and also recursively copies sub-elements. */ - public Element deepCopy() { - return deepFreezeOrCopy(false); - } - - /** Returns frozen version of deepCopy. */ - public Element deepFreeze() { - return deepFreezeOrCopy(true); - } - - /** Freeze this element. - * Throw an IllegalArgumentException if any sub-element is not already frozen. - * (Use deepFreeze() to make a frozen copy of an entire element tree.) - */ - public void shallowFreeze() { - if (isFrozen()) { - return; - } - int alen = attrLength(); - Object[] nparts = new Object[size + alen]; - // copy attributes - System.arraycopy(parts, parts.length - alen, nparts, size, alen); - // copy sub-elements - for (int i = 0; i < size; i++) { - Object e = parts[i]; - String str; - if (e instanceof Element) { // recursion is common case - if (!((Element) e).isFrozen()) { - throw new IllegalArgumentException("Sub-element must be frozen."); - } - } else { - // Freeze StringBuffers, etc. - e = fixupString(e); - } - nparts[i] = e; - } - parts = nparts; - assert (isFrozen()); - } - - /** Return the name of this element. */ - public String getName() { - return name; - } - - /** Change the name of this element. */ - public void setName(String name) { - checkNotFrozen(); - this.name = name.toString(); - } - - /** Reports if the element's name is a particular string (spelled "*"). - * Such elements are created by the nullary Element constructor, - * and by query functions which return multiple values, - * such as findAll. - */ - public boolean isAnonymous() { - return name == ANON_NAME; - } - - /** Return number of elements. (Does not include attributes.) */ - public int size() { - return size; - } - - /** True if no elements. (Does not consider attributes.) */ - public boolean isEmpty() { - return size == 0; - } - - /** True if this element does not allow modification. */ - public boolean isFrozen() { - // It is frozen iff there is no slop space. - return !hasNulls(NEED_SLOP); - } - - void checkNotFrozen() { - if (isFrozen()) { - throw new UnsupportedOperationException("cannot modify frozen element"); - } - } - - /** Remove specified elements. (Does not affect attributes.) */ - public void clear() { - clear(0, size); - } - - public void clear(int beg) { - clear(beg, size); - } - - public void clear(int beg, int end) { - if (end > size) { - badIndex(end); - } - if (beg < 0 || beg > end) { - badIndex(beg); - } - if (beg == end) { - return; - } - checkNotFrozen(); - if (end == size) { - if (beg == 0 - && parts.length > 0 && parts[parts.length - 1] == null) { - // If no attributes, free the parts array. - parts = noPartsNotFrozen; - size = 0; - } else { - clearParts(beg, size); - size = beg; - } - } else { - close(beg, end - beg); - } - } - - void clearParts(int beg, int end) { - for (int i = beg; i < end; i++) { - parts[i] = null; - } - } - - /** True if name, attributes, and elements are the same. */ - public boolean equals(Element that) { - if (!this.name.equals(that.name)) { - return false; - } - if (this.size != that.size) { - return false; - } - // elements must be equal and ordered - Object[] thisParts = this.parts; - Object[] thatParts = that.parts; - for (int i = 0; i < size; i++) { - Object thisPart = thisParts[i]; - Object thatPart = thatParts[i]; - - if (thisPart instanceof Element) { // recursion is common case - if (!thisPart.equals(thatPart)) { - return false; - } - } else { - // If either is a non-string char sequence, normalize it. - thisPart = fixupString(thisPart); - thatPart = fixupString(thatPart); - if (!thisPart.equals(thatPart)) { - return false; - } - } - } - // finally, attributes must be equal (unordered) - return this.equalAttrs(that); - } - // bridge method - - public boolean equals(Object o) { - if (!(o instanceof Element)) { - return false; - } - return equals((Element) o); - } - - public int hashCode() { - int hc = 0; - int alen = attrLength(); - for (int i = parts.length - alen; i < parts.length; i += 2) { - hc += (parts[i + 0].hashCode() ^ parts[i + 1].hashCode()); - } - hc ^= hc << 11; - hc += name.hashCode(); - for (int i = 0; i < size; i++) { - hc ^= hc << 7; - Object p = parts[i]; - if (p instanceof Element) { - hc += p.hashCode(); // recursion is common case - } else { - hc += fixupString(p).hashCode(); - } - } - hc ^= hc >>> 19; - return hc; - } - - /** Compare lexicographically. Earlier-spelled attrs are more sigificant. */ - public int compareTo(Element that) { - int r; - // Primary key is element name. - r = this.name.compareTo(that.name); - if (r != 0) { - return r; - } - - // Secondary key is attributes, as if in normal key order. - // The key/value pairs are sorted as a token sequence. - int thisAlen = this.attrLength(); - int thatAlen = that.attrLength(); - if (thisAlen != 0 || thatAlen != 0) { - r = compareAttrs(thisAlen, that, thatAlen, true); - assert (assertAttrCompareOK(r, that)); - if (r != 0) { - return r; - } - } - - // Finally, elements should be equal and ordered, - // and the first difference rules. - Object[] thisParts = this.parts; - Object[] thatParts = that.parts; - int minSize = this.size; - if (minSize > that.size) { - minSize = that.size; - } - Comparator cc = contentOrder(); - for (int i = 0; i < minSize; i++) { - r = cc.compare(thisParts[i], thatParts[i]); - if (r != 0) { - return r; - } - } - //if (this.size < that.size) return -1; - return this.size - that.size; - } - - private boolean assertAttrCompareOK(int r, Element that) { - Element e0 = this.copyAttrsOnly(); - Element e1 = that.copyAttrsOnly(); - e0.sortAttrs(); - e1.sortAttrs(); - int r2; - for (int k = 0;; k++) { - boolean con0 = e0.containsAttr(k); - boolean con1 = e1.containsAttr(k); - if (con0 != con1) { - if (!con0) { - r2 = 0 - 1; - break; - } - if (!con1) { - r2 = 1 - 0; - break; - } - } - if (!con0) { - r2 = 0; - break; - } - String k0 = e0.getAttrName(k); - String k1 = e1.getAttrName(k); - r2 = k0.compareTo(k1); - if (r2 != 0) { - break; - } - String v0 = e0.getAttr(k); - String v1 = e1.getAttr(k); - r2 = v0.compareTo(v1); - if (r2 != 0) { - break; - } - } - if (r != 0) { - r = (r > 0) ? 1 : -1; - } - if (r2 != 0) { - r2 = (r2 > 0) ? 1 : -1; - } - if (r != r2) { - System.out.println("*** wrong attr compare, " + r + " != " + r2); - System.out.println(" this = " + this); - System.out.println(" attr->" + e0); - System.out.println(" that = " + that); - System.out.println(" attr->" + e1); - } - return r == r2; - } - - private void badIndex(int i) { - Object badRef = (new Object[0])[i]; - } - - public Object get(int i) { - if (i >= size) { - badIndex(i); - } - return parts[i]; - } - - public Object set(int i, Object e) { - if (i >= size) { - badIndex(i); - } - Objects.requireNonNull(e); - checkNotFrozen(); - Object old = parts[i]; - setRaw(i, e); - return old; - } - - void setRaw(int i, Object e) { - parts[i] = e; - } - - public boolean remove(Object e) { - int i = indexOf(e); - if (i < 0) { - return false; - } - close(i, 1); - return true; - } - - public Object remove(int i) { - if (i >= size) { - badIndex(i); - } - Object e = parts[i]; - close(i, 1); - return e; - } - - public Object removeLast() { - if (size == 0) { - return null; - } - return remove(size - 1); - } - - /** Remove the first element matching the given filter. - * Return the filtered value. - */ - public Object remove(Filter f) { - return findOrRemove(f, 0, true); - } - - public Object remove(Filter f, int fromIndex) { - if (fromIndex < 0) { - fromIndex = 0; - } - return findOrRemove(f, fromIndex, true); - } - - /** Remove the last element matching the given filter. - * Return the filtered value. - */ - public Object removeLast(Filter f) { - return findOrRemoveLast(f, size - 1, true); - } - - public Object removeLast(Filter f, int fromIndex) { - if (fromIndex >= size) { - fromIndex = size - 1; - } - return findOrRemoveLast(f, fromIndex, true); - } - - /** Remove all elements matching the given filter. - * If there is a non-null collection given as a sink, - * transfer removed elements to the given collection. - * The int result is the number of removed elements. - * If there is a null sink given, the removed elements - * are discarded. If there is no sink given, the removed - * elements are returned in an anonymous container element. - */ - public Element removeAll(Filter f) { - Element result = new Element(); - findOrRemoveAll(f, false, 0, size, result.asList(), true); - return result; - } - - public Element removeAll(Filter f, int fromIndex, int toIndex) { - Element result = new Element(); - findOrRemoveAll(f, true, fromIndex, toIndex, result.asList(), true); - return result; - } - - public int removeAll(Filter f, Collection sink) { - return findOrRemoveAll(f, false, 0, size, sink, true); - } - - public int removeAll(Filter f, int fromIndex, int toIndex, Collection sink) { - return findOrRemoveAll(f, false, fromIndex, toIndex, sink, true); - } - - /** Remove all elements not matching the given filter. - * If there is a non-null collection given as a sink, - * transfer removed elements to the given collection. - * The int result is the number of removed elements. - * If there is a null sink given, the removed elements - * are discarded. If there is no sink given, the removed - * elements are returned in an anonymous container element. - */ - public Element retainAll(Filter f) { - Element result = new Element(); - findOrRemoveAll(f, true, 0, size, result.asList(), true); - return result; - } - - public Element retainAll(Filter f, int fromIndex, int toIndex) { - Element result = new Element(); - findOrRemoveAll(f, true, fromIndex, toIndex, result.asList(), true); - return result; - } - - public int retainAll(Filter f, Collection sink) { - return findOrRemoveAll(f, true, 0, size, sink, true); - } - - public int retainAll(Filter f, int fromIndex, int toIndex, Collection sink) { - return findOrRemoveAll(f, true, fromIndex, toIndex, sink, true); - } - - public void add(int i, Object e) { - // (The shape of this method is tweaked for common cases.) - Objects.requireNonNull(e); - if (hasNulls(1 + NEED_SLOP)) { - // Common case: Have some slop space. - if (i == size) { - // Most common case: Append. - setRaw(i, e); - size++; - return; - } - if (i > size) { - badIndex(i); - } - // Second most common case: Shift right by one. - open(i, 1); - setRaw(i, e); - return; - } - // Ran out of space. Do something complicated. - size = expand(i, 1); - setRaw(i, e); - } - - public boolean add(Object e) { - add(size, e); - return true; - } - - public Object getLast() { - return size == 0 ? null : parts[size - 1]; - } - - /** Returns the text of this Element. - * All sub-elements of this Element must be of type CharSequence. - * A ClassCastException is raised if there are non-character sub-elements. - * If there is one sub-element, return it. - * Otherwise, returns a TokenList of all sub-elements. - * This results in a space being placed between each adjacent pair of sub-elements. - */ - public CharSequence getText() { - checkTextOnly(); - if (size == 1) { - return parts[0].toString(); - } else { - return new TokenList(parts, 0, size); - } - } - - /** Provides an iterable view of this object as a series of texts. - * All sub-elements of this Element must be of type CharSequence. - * A ClassCastException is raised if there are non-character sub-elements. - */ - public Iterable texts() { - checkTextOnly(); - return (Iterable) (Iterable) this; - } - - /** Returns an array of strings derived from the sub-elements of this object. - * All sub-elements of this Element must be of type CharSequence. - * A ClassCastException is raised if there are non-character sub-elements. - */ - public String[] toStrings() { - //checkTextOnly(); - String[] result = new String[size]; - for (int i = 0; i < size; i++) { - result[i] = ((CharSequence) parts[i]).toString(); - } - return result; - } - - /** Like getText, except that it disregards non-text elements. - * Non-text elements are replaced by their textual contents, if any. - * Text elements which were separated only by non-text element - * boundaries are merged into single tokens. - *

    - * There is no corresponding setter, since this accessor does - * not report the full state of the element. - */ - public CharSequence getFlatText() { - if (size == 1) { - // Simple cases. - if (parts[0] instanceof CharSequence) { - return parts[0].toString(); - } else { - return new TokenList(); - } - } - if (isText()) { - return getText(); - } - // Filter and merge. - Element result = new Element(size); - boolean merge = false; - for (int i = 0; i < size; i++) { - Object text = parts[i]; - if (!(text instanceof CharSequence)) { - // Skip, but erase this boundary. - if (text instanceof Element) { - Element te = (Element) text; - if (!te.isEmpty()) { - result.addText(te.getFlatText()); - } - } - merge = true; - continue; - } - if (merge) { - // Merge w/ previous token. - result.addText((CharSequence) text); - merge = false; - } else { - result.add(text); - } - } - if (result.size() == 1) { - return (CharSequence) result.parts[0]; - } else { - return result.getText(); - } - } - - /** Return true if all sub-elements are of type CharSequence. */ - public boolean isText() { - for (int i = 0; i < size; i++) { - if (!(parts[i] instanceof CharSequence)) { - return false; - } - } - return true; - } - - /** Return true if at least one sub-element is of type CharSequence. */ - public boolean hasText() { - for (int i = 0; i < size; i++) { - if (parts[i] instanceof CharSequence) { - return true; - } - } - return false; - } - - /** Raise a ClassCastException if !isText. */ - public void checkTextOnly() { - for (int i = 0; i < size; i++) { - ((CharSequence) parts[i]).getClass(); - } - } - - /** Clears out all sub-elements, and replaces them by the given text. - * A ClassCastException is raised if there are non-character sub-elements, - * either before or after the change. - */ - public void setText(CharSequence text) { - checkTextOnly(); - clear(); - if (text instanceof TokenList) { - // TL's contain only strings - addAll(0, (TokenList) text); - } else { - add(text); - } - } - - /** Add text at the given position, merging with any previous - * text element, but preserving token boundaries where possible. - *

    - * In all cases, the new value of getText() is the string - * concatenation of the old value of getText() plus the new text. - *

    - * The total effect is to concatenate the given text to any - * pre-existing text, and to do so efficiently even if there - * are many such concatenations. Also, getText calls which - * return multiple tokens (in a TokenList) are respected. - * For example, if x is empty, x.addText(y.getText()) puts - * an exact structural copy of y's text into x. - *

    - * Internal token boundaries in the original text, and in the new - * text (i.e., if it is a TokenList), are preserved. However, - * at the point where new text joins old text, a StringBuffer - * or new String may be created to join the last old and first - * new token. - *

    - * If the given text is a TokenList, add the tokens as - * separate sub-elements, possibly merging the first token to - * a previous text item (to avoid making a new token boundary). - *

    - * If the element preceding position i is a StringBuffer, - * append the first new token to it. - *

    - * If the preceding element is a CharSequence, replace it by a - * StringBuffer containing both its and the first new token. - *

    - * If tokens are added after a StringBuffer, freeze it into a String. - *

    - * Every token not merged into a previous CharSequence is added - * as a new sub-element, starting at position i. - *

    - * Returns the number of elements added, which is useful - * for further calls to addText. This number is zero - * if the input string was null, or was successfully - * merged into a StringBuffer at position i-1. - *

    - * By contrast, calling add(text) always adds a new sub-element. - * In that case, if there is a previous string, a separating - * space is virtually present also, and will be observed if - * getText() is used to return all the text together. - */ - public int addText(int i, CharSequence text) { - if (text instanceof String) { - return addText(i, (String) text); - } else if (text instanceof TokenList) { - // Text is a list of tokens. - TokenList tl = (TokenList) text; - int tlsize = tl.size(); - if (tlsize == 0) { - return 0; - } - String token0 = tl.get(0).toString(); - if (tlsize == 1) { - return addText(i, token0); - } - if (mergeWithPrev(i, token0, false)) { - // Add the n-1 remaining tokens. - addAll(i, tl.subList(1, tlsize)); - return tlsize - 1; - } else { - addAll(i, (Collection) tl); - return tlsize; - } - } else { - return addText(i, text.toString()); - } - } - - public int addText(CharSequence text) { - return addText(size, text); - } - - private // no reason to make this helper public - int addText(int i, String text) { - if (text.length() == 0) { - return 0; // Trivial success. - } - if (mergeWithPrev(i, text, true)) { - return 0; // Merged with previous token. - } - // No previous token. - add(i, text); - return 1; - } - - // Tries to merge token with previous contents. - // Returns true if token is successfully disposed of. - // If keepSB is false, any previous StringBuffer is frozen. - // If keepSB is true, a StringBuffer may be created to hold - // the merged token. - private boolean mergeWithPrev(int i, String token, boolean keepSB) { - if (i == 0) // Trivial success if the token is length zero. - { - return (token.length() == 0); - } - Object prev = parts[i - 1]; - if (prev instanceof StringBuffer) { - StringBuffer psb = (StringBuffer) prev; - psb.append(token); - if (!keepSB) { - parts[i - 1] = psb.toString(); - } - return true; - } - if (token.length() == 0) { - return true; // Trivial success. - } - if (prev instanceof CharSequence) { - // Must concatenate. - StringBuffer psb = new StringBuffer(prev.toString()); - psb.append(token); - if (keepSB) { - parts[i - 1] = psb; - } else { - parts[i - 1] = psb.toString(); - } - return true; - } - return false; - } - - /** Trim all strings, using String.trim(). - * Remove empty strings. - * Normalize CharSequences to Strings. - */ - public void trimText() { - checkNotFrozen(); - int fillp = 0; - int size = this.size; - Object[] parts = this.parts; - for (int i = 0; i < size; i++) { - Object e = parts[i]; - if (e instanceof CharSequence) { - String tt = e.toString().trim(); - if (tt.length() == 0) { - continue; - } - e = tt; - } - parts[fillp++] = e; - } - while (size > fillp) { - parts[--size] = null; - } - this.size = fillp; - } - - /** Add one or more subelements at the given position. - * If the object reference is null, nothing happens. - * If the object is an anonymous Element, addAll is called. - * If the object is a TokenList, addAll is called (to add the tokens). - * Otherwise, add is called, adding a single subelement or string. - * The net effect is to add zero or more tokens. - * The returned value is the number of added elements. - *

    - * Note that getText() can return a TokenList which preserves - * token boundaries in the text source. Such a text will be - * added as multiple text sub-elements. - *

    - * If a text string is added adjacent to an immediately - * preceding string, there will be a token boundary between - * the strings, which will print as an extra space. - */ - public int addContent(int i, Object e) { - if (e == null) { - return 0; - } else if (e instanceof TokenList) { - return addAll(i, (Collection) e); - } else if (e instanceof Element - && ((Element) e).isAnonymous()) { - return addAll(i, (Element) e); - } else { - add(i, e); - return 1; - } - } - - public int addContent(Object e) { - return addContent(size, e); - } - - public Object[] toArray() { - Object[] result = new Object[size]; - System.arraycopy(parts, 0, result, 0, size); - return result; - } - - public Element copyContentOnly() { - Element content = new Element(size); - System.arraycopy(parts, 0, content.parts, 0, size); - content.size = size; - return content; - } - - public void sort(Comparator c) { - Arrays.sort(parts, 0, size, c); - } - - public void sort() { - sort(CONTENT_ORDER); - } - - /** Equivalent to Collections.reverse(this.asList()). */ - public void reverse() { - for (int i = 0, mid = size >> 1, j = size - 1; i < mid; i++, j--) { - Object p = parts[i]; - parts[i] = parts[j]; - parts[j] = p; - } - } - - /** Equivalent to Collections.shuffle(this.asList() [, rnd]). */ - public void shuffle() { - Collections.shuffle(this.asList()); - } - - public void shuffle(Random rnd) { - Collections.shuffle(this.asList(), rnd); - } - - /** Equivalent to Collections.rotate(this.asList(), dist). */ - public void rotate(int dist) { - Collections.rotate(this.asList(), dist); - } - - /** Equivalent to Collections.min(this.asList(), c). */ - public Object min(Comparator c) { - return Collections.min(this.asList(), c); - } - - public Object min() { - return min(CONTENT_ORDER); - } - - /** Equivalent to Collections.max(this.asList(), c). */ - public Object max(Comparator c) { - return Collections.max(this.asList(), c); - } - - public Object max() { - return max(CONTENT_ORDER); - } - - public int addAll(int i, Collection c) { - if (c instanceof LView) { - return addAll(i, ((LView) c).asElement()); - } else { - int csize = c.size(); - if (csize == 0) { - return 0; - } - openOrExpand(i, csize); - int fill = i; - for (Object part : c) { - parts[fill++] = part; - } - return csize; - } - } - - public int addAll(int i, Element e) { - int esize = e.size; - if (esize == 0) { - return 0; - } - openOrExpand(i, esize); - System.arraycopy(e.parts, 0, parts, i, esize); - return esize; - } - - public int addAll(Collection c) { - return addAll(size, c); - } - - public int addAll(Element e) { - return addAll(size, e); - } - - public int addAllAttrsFrom(Element e) { - int added = 0; - for (int k = 0; e.containsAttr(k); k++) { - String old = setAttr(e.getAttrName(k), e.getAttr(k)); - if (old == null) { - added += 1; - } - } - // Return number of added (not merely changed) attrs. - return added; - } - - // Search. - public boolean matches(Filter f) { - return f.filter(this) != null; - } - - public Object find(Filter f) { - return findOrRemove(f, 0, false); - } - - public Object find(Filter f, int fromIndex) { - if (fromIndex < 0) { - fromIndex = 0; - } - return findOrRemove(f, fromIndex, false); - } - - /** Find the last element matching the given filter. - * Return the filtered value. - */ - public Object findLast(Filter f) { - return findOrRemoveLast(f, size - 1, false); - } - - public Object findLast(Filter f, int fromIndex) { - if (fromIndex >= size) { - fromIndex = size - 1; - } - return findOrRemoveLast(f, fromIndex, false); - } - - /** Find all elements matching the given filter. - * If there is a non-null collection given as a sink, - * transfer matching elements to the given collection. - * The int result is the number of matching elements. - * If there is a null sink given, the matching elements are - * not collected. If there is no sink given, the matching - * elements are returned in an anonymous container element. - * In no case is the receiver element changed. - *

    - * Note that a simple count of matching elements can be - * obtained by passing a null collection argument. - */ - public Element findAll(Filter f) { - Element result = new Element(); - findOrRemoveAll(f, false, 0, size, result.asList(), false); - return result; - } - - public Element findAll(Filter f, int fromIndex, int toIndex) { - Element result = new Element(name); - findOrRemoveAll(f, false, fromIndex, toIndex, result.asList(), false); - return result; - } - - public int findAll(Filter f, Collection sink) { - return findOrRemoveAll(f, false, 0, size, sink, false); - } - - public int findAll(Filter f, int fromIndex, int toIndex, Collection sink) { - return findOrRemoveAll(f, false, fromIndex, toIndex, sink, false); - } - - /// Driver routines. - private Object findOrRemove(Filter f, int fromIndex, boolean remove) { - for (int i = fromIndex; i < size; i++) { - Object x = f.filter(parts[i]); - if (x != null) { - if (remove) { - close(i, 1); - } - return x; - } - } - return null; - } - - private Object findOrRemoveLast(Filter f, int fromIndex, boolean remove) { - for (int i = fromIndex; i >= 0; i--) { - Object x = f.filter(parts[i]); - if (x != null) { - if (remove) { - close(i, 1); - } - return x; - } - } - return null; - } - - private int findOrRemoveAll(Filter f, boolean fInvert, - int fromIndex, int toIndex, - Collection sink, boolean remove) { - if (fromIndex < 0) { - badIndex(fromIndex); - } - if (toIndex > size) { - badIndex(toIndex); - } - int found = 0; - for (int i = fromIndex; i < toIndex; i++) { - Object p = parts[i]; - Object x = f.filter(p); - if (fInvert ? (x == null) : (x != null)) { - if (remove) { - close(i--, 1); - toIndex--; - } - found += XMLKit.addContent(fInvert ? p : x, sink); - } - } - return found; - } - - public void replaceAll(Filter f) { - XMLKit.replaceAll(f, this.asList()); - } - - public void replaceAll(Filter f, int fromIndex, int toIndex) { - XMLKit.replaceAll(f, this.asList().subList(fromIndex, toIndex)); - } - - /// Recursive walks. - // findAllInTree(f) == findAll(findInTree(f,S)), S.toElement - // findAllInTree(f,S) == findAll(findInTree(content(f,S))) - // removeAllInTree(f) == replaceAll(replaceInTree(and(f,emptyF))) - // removeAllInTree(f,S) == replaceAll(replaceInTree(and(content(f,S),emptyF))) - // retainAllInTree(f) == removeAllInTree(not(f)) - // replaceAllInTree(f) == replaceAll(replaceInTree(f)) - public Element findAllInTree(Filter f) { - Element result = new Element(); - findAllInTree(f, result.asList()); - return result; - } - - public int findAllInTree(Filter f, Collection sink) { - int found = 0; - int size = this.size; // cache copy - for (int i = 0; i < size; i++) { - Object p = parts[i]; - Object x = f.filter(p); - if (x != null) { - found += XMLKit.addContent(x, sink); - } else if (p instanceof Element) { - found += ((Element) p).findAllInTree(f, sink); - } - } - return found; - } - - public int countAllInTree(Filter f) { - return findAllInTree(f, null); - } - - public int removeAllInTree(Filter f, Collection sink) { - if (sink == null) { - sink = newCounterColl(); - } - replaceAll(replaceInTree(and(content(f, sink), emptyFilter()))); - return sink.size(); - } - - public Element removeAllInTree(Filter f) { - Element result = new Element(); - removeAllInTree(f, result.asList()); - return result; - } - - public int retainAllInTree(Filter f, Collection sink) { - return removeAllInTree(not(f), sink); - } - - public Element retainAllInTree(Filter f) { - Element result = new Element(); - retainAllInTree(f, result.asList()); - return result; - } - - public void replaceAllInTree(Filter f) { - replaceAll(replaceInTree(f)); - } - - /** Raise a ClassCastException if any subelements are the wrong type. */ - public void checkPartsOnly(Class elementClass) { - for (int i = 0; i < size; i++) { - elementClass.cast(parts[i]).getClass(); - } - } - - /** Return true if all sub-elements are of the given type. */ - public boolean isPartsOnly(Class elementClass) { - for (int i = 0; i < size; i++) { - if (!elementClass.isInstance(parts[i])) { - return false; - } - } - return true; - } - - /** Provides an iterable view of this object as a series of elements. - * All sub-elements of this Element must be of type Element. - * A ClassCastException is raised if there are non-Element sub-elements. - */ - public Iterable partsOnly(Class elementClass) { - checkPartsOnly(elementClass); - return (Iterable) (Iterable) this; - } - - public Iterable elements() { - return partsOnly(Element.class); - } - - /// Useful shorthands. - // Finding or removing elements w/o regard to their type or content. - public Element findElement() { - return (Element) find(elementFilter()); - } - - public Element findAllElements() { - return findAll(elementFilter()); - } - - public Element removeElement() { - return (Element) remove(elementFilter()); - } - - public Element removeAllElements() { - return (Element) removeAll(elementFilter()); - } - - // Finding or removing by element tag or selected attribute, - // as if by elementFilter(name) or attrFilter(name, value). - // Roughly akin to Common Lisp ASSOC. - public Element findElement(String name) { - return (Element) find(elementFilter(name)); - } - - public Element removeElement(String name) { - return (Element) remove(elementFilter(name)); - } - - public Element findWithAttr(String key) { - return (Element) find(attrFilter(name)); - } - - public Element findWithAttr(String key, String value) { - return (Element) find(attrFilter(name, value)); - } - - public Element removeWithAttr(String key) { - return (Element) remove(attrFilter(name)); - } - - public Element removeWithAttr(String key, String value) { - return (Element) remove(attrFilter(name, value)); - } - - public Element findAllElements(String name) { - return findAll(elementFilter(name)); - } - - public Element removeAllElements(String name) { - return removeAll(elementFilter(name)); - } - - public Element retainAllElements(String name) { - return retainAll(elementFilter(name)); - } - - public Element findAllWithAttr(String key) { - return findAll(attrFilter(key)); - } - - public Element removeAllWithAttr(String key) { - return removeAll(attrFilter(key)); - } - - public Element retainAllWithAttr(String key) { - return retainAll(attrFilter(key)); - } - - public Element findAllWithAttr(String key, String value) { - return findAll(attrFilter(key, value)); - } - - public Element removeAllWithAttr(String key, String value) { - return removeAll(attrFilter(key, value)); - } - - public Element retainAllWithAttr(String key, String value) { - return retainAll(attrFilter(key, value)); - } - - public int countAll(Filter f) { - return findAll(f, null); - } - - public int countAllElements() { - return countAll(elementFilter()); - } - - public int countAllElements(String name) { - return countAll(elementFilter(name)); - } - - public int countAllWithAttr(String key) { - return countAll(attrFilter(name)); - } - - public int countAllWithAttr(String key, String value) { - return countAll(attrFilter(key, value)); - } - - public int indexOf(Object e) { - for (int i = 0; i < size; i++) { - if (e.equals(parts[i])) { - return i; - } - } - return -1; - } - - public int lastIndexOf(Object e) { - for (int i = size - 1; i >= 0; i--) { - if (e.equals(parts[i])) { - return i; - } - } - return -1; - } - - /** Remove the first element matching the given filter. - * Return the filtered value. - */ - public int indexOf(Filter f) { - return indexOf(f, 0); - } - - public int indexOf(Filter f, int fromIndex) { - if (fromIndex < 0) { - fromIndex = 0; - } - for (int i = fromIndex; i < size; i++) { - Object x = f.filter(parts[i]); - if (x != null) { - return i; - } - } - return -1; - } - - /** Remove the last element matching the given filter. - * Return the filtered value. - */ - public int lastIndexOf(Filter f) { - return lastIndexOf(f, size - 1); - } - - public int lastIndexOf(Filter f, int fromIndex) { - if (fromIndex >= size) { - fromIndex = size - 1; - } - for (int i = fromIndex; i >= 0; i--) { - Object x = f.filter(parts[i]); - if (x != null) { - return i; - } - } - return -1; - } - - public boolean contains(Object e) { - return indexOf(e) >= 0; - } - - // attributes - private int findOrCreateAttr(String key, boolean create) { - key.toString(); // null check - int attrBase = parts.length; - for (int i = parts.length - 2; i >= size; i -= 2) { - String akey = (String) parts[i + 0]; - if (akey == null) { - if (!create) { - return -1; - } - if (i == size) { - break; // NEED_SLOP - } - parts[i + 0] = key; - //parts[i+1] = ""; //caller responsibility - return i; - } - attrBase = i; - if (akey.equals(key)) { - return i; - } - } - // If we fell through, we ran into an element part. - // Therefore we have run out of empty slots. - if (!create) { - return -1; - } - assert (!isFrozen()); - int alen = parts.length - attrBase; - expand(size, 2); // generally expands by more than 2 - // since there was a reallocation, the garbage slots are really null - assert (parts[size + 0] == null && parts[size + 1] == null); - alen += 2; - int i = parts.length - alen; - parts[i + 0] = key; - //parts[i+1] = ""; //caller responsibility - return i; - } - - public int attrSize() { - return attrLength() >>> 1; - } - - public int indexOfAttr(String key) { - return findOrCreateAttr(key, false); - } - - public boolean containsAttr(String key) { - return indexOfAttr(key) >= 0; - } - - public String getAttr(String key) { - return getAttr(key, null); - } - - public String getAttr(String key, String dflt) { - int i = findOrCreateAttr(key, false); - return (i < 0) ? dflt : (String) parts[i + 1]; - } - - public TokenList getAttrList(String key) { - return convertToList(getAttr(key)); - } - - public Number getAttrNumber(String key) { - return convertToNumber(getAttr(key)); - } - - public long getAttrLong(String key) { - return getAttrLong(key, 0); - } - - public double getAttrDouble(String key) { - return getAttrDouble(key, 0.0); - } - - public long getAttrLong(String key, long dflt) { - return convertToLong(getAttr(key), dflt); - } - - public double getAttrDouble(String key, double dflt) { - return convertToDouble(getAttr(key), dflt); - } - - int indexAttr(int k) { - int i = parts.length - (k * 2) - 2; - if (i < size || parts[i] == null) { - return -2; // always oob - } - return i; - } - - public boolean containsAttr(int k) { - return indexAttr(k) >= 0; - } - - public String getAttr(int k) { - return (String) parts[indexAttr(k) + 1]; - } - - public String getAttrName(int k) { - return (String) parts[indexAttr(k) + 0]; - } - - public Iterable attrNames() { - //return asAttrMap().keySet(); - return new Iterable() { - - public Iterator iterator() { - return new ANItr(); - } - }; - } - - // Hand-inlined replacement for asAttrMap().keySet().iterator(): - class ANItr implements Iterator { - - boolean lastRet; - int cursor = -2; // pointer from end of parts - - public boolean hasNext() { - int i = cursor + parts.length; - return i >= size && parts[i] == null; - } - - public String next() { - int i = cursor + parts.length; - Object x; - if (i < size || (x = parts[i]) == null) { - nsee(); - return null; - } - cursor -= 2; - lastRet = true; - return (String) x; - } - - public void remove() { - if (!lastRet) { - throw new IllegalStateException(); - } - Element.this.removeAttr((-4 - cursor) / 2); - cursor += 2; - lastRet = false; - } - - Exception nsee() { - throw new NoSuchElementException("attribute " + (-2 - cursor) / 2); - } - } - - /** Return an anonymous copy of self, but only with attributes. - */ - public Element copyAttrsOnly() { - int alen = attrLength(); - Element attrs = new Element(alen); - Object[] attrParts = attrs.parts; - assert (attrParts.length == NEED_SLOP + alen); - System.arraycopy(parts, parts.length - alen, - attrParts, NEED_SLOP, - alen); - return attrs; - } - - /** Get all attributes, represented as an element with sub-elements. - * The name of each sub-element is the attribute key, and the text - * This is a fresh copy, and can be updated with affecting the original. - * of each sub-element is the corresponding attribute value. - * See also asAttrMap() for a "live" view of all the attributes as a Map. - */ - public Element getAttrs() { - int asize = attrSize(); - Element attrs = new Element(ANON_NAME, asize, NEED_SLOP + asize); - for (int i = 0; i < asize; i++) { - Element attr = new Element(getAttrName(i), 1, NEED_SLOP + 1); - // %%% normalize attrs to token lists? - attr.setRaw(0, getAttr(i)); - attrs.setRaw(i, attr); - } - return attrs; - } - - public void setAttrs(Element attrs) { - int alen = attrLength(); - clearParts(parts.length - alen, alen); - if (!hasNulls(NEED_SLOP + attrs.size * 2)) { - expand(size, attrs.size * 2); - } - addAttrs(attrs); - } - - public void addAttrs(Element attrs) { - for (int i = 0; i < attrs.size; i++) { - Element attr = (Element) attrs.get(i); - setAttr(attr.name, attr.getText().toString()); - } - } - - public void removeAttr(int i) { - checkNotFrozen(); - while ((i -= 2) >= size) { - Object k = parts[i + 0]; - Object v = parts[i + 1]; - if (k == null) { - break; - } - parts[i + 2] = k; - parts[i + 3] = v; - } - parts[i + 2] = null; - parts[i + 3] = null; - } - - public void clearAttrs() { - if (parts.length == 0 || parts[parts.length - 1] == null) { - return; // no attrs to clear - } - checkNotFrozen(); - if (size == 0) { - // If no elements, free the parts array. - parts = noPartsNotFrozen; - return; - } - for (int i = parts.length - 1; parts[i] != null; i--) { - assert (i >= size); - parts[i] = null; - } - } - - public String setAttr(String key, String value) { - String old; - if (value == null) { - int i = findOrCreateAttr(key, false); - if (i >= 0) { - old = (String) parts[i + 1]; - removeAttr(i); - } else { - old = null; - } - } else { - checkNotFrozen(); - int i = findOrCreateAttr(key, true); - old = (String) parts[i + 1]; - parts[i + 1] = value; - } - return old; - } - - public String setAttrList(String key, List l) { - if (l == null) { - return setAttr(key, null); - } - if (!(l instanceof TokenList)) { - l = new TokenList(l); - } - return setAttr(key, l.toString()); - } - - public String setAttrNumber(String key, Number n) { - return setAttr(key, (n == null) ? null : n.toString()); - } - - public String setAttrLong(String key, long n) { - return setAttr(key, (n == 0) ? null : String.valueOf(n)); - } - - public String setAttrDouble(String key, double n) { - return setAttr(key, (n == 0) ? null : String.valueOf(n)); - } - - public String setAttr(int k, String value) { - int i = indexAttr(k); - String old = (String) parts[i + 1]; - if (value == null) { - removeAttr(i); - } else { - checkNotFrozen(); - parts[i + 1] = value; - } - return old; - } - - int attrLength() { - return parts.length - attrBase(); - } - - /** Are the attributes of the two two elements equal? - * Disregards name, sub-elements, and ordering of attributes. - */ - public boolean equalAttrs(Element that) { - int alen = this.attrLength(); - if (alen != that.attrLength()) { - return false; - } - if (alen == 0) { - return true; - } - return compareAttrs(alen, that, alen, false) == 0; - } - - private int compareAttrs(int thisAlen, - Element that, int thatAlen, - boolean fullCompare) { - Object[] thisParts = this.parts; - Object[] thatParts = that.parts; - int thisBase = thisParts.length - thisAlen; - int thatBase = thatParts.length - thatAlen; - // search indexes into unmatched parts of this.attrs: - int firstI = 0; - // search indexes into unmatched parts of that.attrs: - int firstJ = 0; - int lastJ = thatAlen - 2; - // try to find the mismatch with the first key: - String firstKey = null; - int firstKeyValCmp = 0; - int foundKeys = 0; - for (int i = 0; i < thisAlen; i += 2) { - String key = (String) thisParts[thisBase + i + 0]; - String val = (String) thisParts[thisBase + i + 1]; - String otherVal = null; - for (int j = firstJ; j <= lastJ; j += 2) { - if (key.equals(thatParts[thatBase + j + 0])) { - foundKeys += 1; - otherVal = (String) thatParts[thatBase + j + 1]; - // Optimization: Narrow subsequent searches when easy. - if (j == lastJ) { - lastJ -= 2; - } else if (j == firstJ) { - firstJ += 2; - } - if (i == firstI) { - firstI += 2; - } - break; - } - } - int valCmp; - if (otherVal != null) { - // The key was found. - if (!fullCompare) { - if (!val.equals(otherVal)) { - return 1 - 0; //arb. - } - continue; - } - valCmp = val.compareTo(otherVal); - } else { - // Found the key in this but not that. - // Such a mismatch puts the guy missing the key last. - valCmp = 0 - 1; - } - if (valCmp != 0) { - // found a mismatch, key present in both elems - if (firstKey == null - || firstKey.compareTo(key) > 0) { - // found a better key - firstKey = key; - firstKeyValCmp = valCmp; - } - } - } - // We have located the first mismatch of all keys in this.attrs. - // In general we must also look for keys in that.attrs but missing - // from this.attrs; such missing keys, if earlier than firstKey, - // rule the comparison. - - // We can sometimes prove quickly there is no missing key. - if (foundKeys == thatAlen / 2) { - // Exhausted all keys in that.attrs. - return firstKeyValCmp; - } - - // Search for a missing key in that.attrs earlier than firstKey. - findMissingKey: - for (int j = firstJ; j <= lastJ; j += 2) { - String otherKey = (String) thatParts[thatBase + j + 0]; - if (firstKey == null - || firstKey.compareTo(otherKey) > 0) { - // Found a better key; is it missing? - for (int i = firstI; i < thisAlen; i += 2) { - if (otherKey.equals(thisParts[thisBase + i + 0])) { - continue findMissingKey; - } - } - // If we get here, there was no match in this.attrs. - return 1 - 0; - } - } - - // No missing key. Previous comparison value rules. - return firstKeyValCmp; - } - - // Binary search looking for first non-null after size. - int attrBase() { - // Smallest & largest possible attribute indexes: - int kmin = 0; - int kmax = (parts.length - size) >>> 1; - // earlist possible attribute position: - int abase = parts.length - (kmax * 2); - // binary search using scaled indexes: - while (kmin != kmax) { - int kmid = kmin + ((kmax - kmin) >>> 1); - if (parts[abase + (kmid * 2)] == null) { - kmin = kmid + 1; - } else { - kmax = kmid; - } - assert (kmin <= kmax); - } - return abase + (kmax * 2); - } - - /** Sort attributes by name. */ - public void sortAttrs() { - checkNotFrozen(); - int abase = attrBase(); - int alen = parts.length - abase; - String[] buf = new String[alen]; - // collect keys - for (int k = 0; k < alen / 2; k++) { - String akey = (String) parts[abase + (k * 2) + 0]; - buf[k] = akey; - } - Arrays.sort(buf, 0, alen / 2); - // collect values - for (int k = 0; k < alen / 2; k++) { - String akey = buf[k]; - buf[k + alen / 2] = getAttr(akey); - } - // reorder keys and values - int fillp = parts.length; - for (int k = 0; k < alen / 2; k++) { - String akey = buf[k]; - String aval = buf[k + alen / 2]; - fillp -= 2; - parts[fillp + 0] = akey; - parts[fillp + 1] = aval; - } - assert (fillp == abase); - } - - /* - Notes on whitespace and tokenization. - On input, never split CDATA blocks. They remain single tokens. - ?Try to treat encoded characters as CDATA-quoted, also? - - Internally, each String sub-element is logically a token. - However, if there was no token-splitting on input, - consecutive strings are merged by the parser. - - Internally, we need addToken (intervening blank) and addText - (hard concatenation). - - Optionally on input, tokenize unquoted text into words. - Between each adjacent word pair, elide either one space - or all space. - - On output, we always add spaces between tokens. - The Element("a", {"b", "c", Element("d"), "e f"}) - outputs as "b ce f" - */ - /** Split strings into tokens, using a StringTokenizer. */ - public void tokenize(String delims, boolean returnDelims) { - checkNotFrozen(); - if (delims == null) { - delims = WHITESPACE_CHARS; // StringTokenizer default - } - for (int i = 0; i < size; i++) { - if (!(parts[i] instanceof CharSequence)) { - continue; - } - int osize = size; - String str = parts[i].toString(); - StringTokenizer st = new StringTokenizer(str, delims, returnDelims); - int nstrs = st.countTokens(); - switch (nstrs) { - case 0: - close(i--, 1); - break; - case 1: - parts[i] = st.nextToken(); - break; - default: - openOrExpand(i + 1, nstrs - 1); - for (int j = 0; j < nstrs; j++) { - parts[i + j] = st.nextToken(); - } - i += nstrs - 1; - break; - } - } - } - - public void tokenize(String delims) { - tokenize(delims, false); - } - - public void tokenize() { - tokenize(null, false); - } - - // views - class LView extends AbstractList { - - Element asElement() { - return Element.this; - } - - public int size() { - return Element.this.size(); - } - - public Object get(int i) { - return Element.this.get(i); - } - - @Override - public boolean contains(Object e) { - return Element.this.contains(e); - } - - @Override - public Object[] toArray() { - return Element.this.toArray(); - } - - @Override - public int indexOf(Object e) { - return Element.this.indexOf(e); - } - - @Override - public int lastIndexOf(Object e) { - return Element.this.lastIndexOf(e); - } - - @Override - public void add(int i, Object e) { - ++modCount; - Element.this.add(i, e); - } - - @Override - public boolean addAll(int i, Collection c) { - ++modCount; - return Element.this.addAll(i, c) > 0; - } - - @Override - public boolean addAll(Collection c) { - ++modCount; - return Element.this.addAll(c) > 0; - } - - @Override - public Object remove(int i) { - ++modCount; - return Element.this.remove(i); - } - - @Override - public Object set(int i, Object e) { - ++modCount; - return Element.this.set(i, e); - } - - @Override - public void clear() { - ++modCount; - Element.this.clear(); - } - // Others: toArray(Object[]), containsAll, removeAll, retainAll - } - - /** Produce a list view of sub-elements. - * (The list view does not provide access to the element's - * name or attributes.) - * Changes to this view are immediately reflected in the - * element itself. - */ - public List asList() { - return new LView(); - } - - /** Produce a list iterator on all sub-elements. */ - public ListIterator iterator() { - //return asList().listIterator(); - return new Itr(); - } - - // Hand-inlined replacement for LView.listIterator(): - class Itr implements ListIterator { - - int lastRet = -1; - int cursor = 0; - - public boolean hasNext() { - return cursor < size; - } - - public boolean hasPrevious() { - return cursor > 0 && cursor <= size; - } - - public Object next() { - if (!hasNext()) { - nsee(); - } - return parts[lastRet = cursor++]; - } - - public Object previous() { - if (!hasPrevious()) { - nsee(); - } - return parts[--cursor]; - } - - public int nextIndex() { - return cursor; - } - - public int previousIndex() { - return cursor - 1; - } - - public void set(Object x) { - parts[lastRet] = x; - } - - public void add(Object x) { - lastRet = -1; - Element.this.add(cursor++, x); - } - - public void remove() { - if (lastRet < 0) { - throw new IllegalStateException(); - } - Element.this.remove(lastRet); - if (lastRet < cursor) { - --cursor; - } - lastRet = -1; - } - - void nsee() { - throw new NoSuchElementException("element " + cursor); - } - } - - /** A PrintWriter which always appends as if by addText. - * Use of this stream may insert a StringBuffer at the end - * of the Element. The user must not directly modify this - * StringBuffer, or use it in other data structures. - * From time to time, the StringBuffer may be replaced by a - * constant string as a result of using the PrintWriter. - */ - public PrintWriter asWriter() { - return new ElemW(); - } - - class ElemW extends PrintWriter { - - ElemW() { - super(new StringWriter()); - } - final StringBuffer buf = ((StringWriter) out).getBuffer(); - - { - lock = buf; - } // synchronize on this buffer - - @Override - public void println() { - synchronized (buf) { - ensureCursor(); - super.println(); - } - } - - @Override - public void write(int ch) { - synchronized (buf) { - ensureCursor(); - //buf.append(ch); - super.write(ch); - } - } - - @Override - public void write(char buf[], int off, int len) { - synchronized (buf) { - ensureCursor(); - super.write(buf, off, len); - } - } - - @Override - public void write(String s, int off, int len) { - synchronized (buf) { - ensureCursor(); - //buf.append(s.substring(off, off+len)); - super.write(s, off, len); - } - } - - @Override - public void write(String s) { - synchronized (buf) { - ensureCursor(); - //buf.append(s); - super.write(s); - } - } - - private void ensureCursor() { - checkNotFrozen(); - if (getLast() != buf) { - int pos = indexOf(buf); - if (pos >= 0) { - // Freeze the pre-existing use of buf. - setRaw(pos, buf.toString()); - } - add(buf); - } - } - } - - /** Produce a map view of attributes, in which the attribute - * name strings are the keys. - * (The map view does not provide access to the element's - * name or sub-elements.) - * Changes to this view are immediately reflected in the - * element itself. - */ - public Map asAttrMap() { - class Entry implements Map.Entry { - - final int k; - - Entry(int k) { - this.k = k; - assert (((String) getKey()).toString() != null); // check, fail-fast - } - - public String getKey() { - return Element.this.getAttrName(k); - } - - public String getValue() { - return Element.this.getAttr(k); - } - - public String setValue(String v) { - return Element.this.setAttr(k, v.toString()); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Map.Entry)) { - return false; - } - Map.Entry that = (Map.Entry) o; - return (this.getKey().equals(that.getKey()) - && this.getValue().equals(that.getValue())); - } - - @Override - public int hashCode() { - return getKey().hashCode() ^ getValue().hashCode(); - } - } - class EIter implements Iterator> { - - int k = 0; // index of pending next() attribute - - public boolean hasNext() { - return Element.this.containsAttr(k); - } - - public Map.Entry next() { - return new Entry(k++); - } - - public void remove() { - Element.this.removeAttr(--k); - } - } - class ESet extends AbstractSet> { - - public int size() { - return Element.this.attrSize(); - } - - public Iterator> iterator() { - return new EIter(); - } - - @Override - public void clear() { - Element.this.clearAttrs(); - } - } - class AView extends AbstractMap { - - private transient Set> eSet; - - public Set> entrySet() { - if (eSet == null) { - eSet = new ESet(); - } - return eSet; - } - - @Override - public int size() { - return Element.this.attrSize(); - } - - public boolean containsKey(String k) { - return Element.this.containsAttr(k); - } - - public String get(String k) { - return Element.this.getAttr(k); - } - - @Override - public String put(String k, String v) { - return Element.this.setAttr(k, v.toString()); - } - - public String remove(String k) { - return Element.this.setAttr(k, null); - } - } - return new AView(); - } - - /** Reports number of additional elements this object can accommodate - * without reallocation. - */ - public int getExtraCapacity() { - int abase = attrBase(); - return Math.max(0, abase - size - NEED_SLOP); - } - - /** Ensures that at least the given number of additional elements - * can be added to this object without reallocation. - */ - public void ensureExtraCapacity(int cap) { - if (cap == 0 || hasNulls(cap + NEED_SLOP)) { - return; - } - setExtraCapacity(cap); - } - - /** - * Trim excess capacity to zero, or do nothing if frozen. - * This minimizes the space occupied by this Element, - * at the expense of a reallocation if sub-elements or attributes - * are added later. - */ - public void trimToSize() { - if (isFrozen()) { - return; - } - setExtraCapacity(0); - } - - /** Changes the number of additional elements this object can accommodate - * without reallocation. - */ - public void setExtraCapacity(int cap) { - checkNotFrozen(); - int abase = attrBase(); - int alen = parts.length - abase; // slots allocated for attrs - int nlen = size + cap + NEED_SLOP + alen; - if (nlen != parts.length) { - Object[] nparts = new Object[nlen]; - // copy attributes - System.arraycopy(parts, abase, nparts, nlen - alen, alen); - // copy sub-elements - System.arraycopy(parts, 0, nparts, 0, size); - parts = nparts; - } - assert (cap == getExtraCapacity()); - } - - // Return true if there are at least len nulls of slop available. - boolean hasNulls(int len) { - if (len == 0) { - return true; - } - int lastNull = size + len - 1; - if (lastNull >= parts.length) { - return false; - } - return (parts[lastNull] == null); - } - - // Opens up parts array at pos by len spaces. - void open(int pos, int len) { - assert (pos < size); - assert (hasNulls(len + NEED_SLOP)); - checkNotFrozen(); - int nsize = size + len; - int tlen = size - pos; - System.arraycopy(parts, pos, parts, pos + len, tlen); - size = nsize; - } - - // Reallocate and open up at parts[pos] to at least len empty places. - // Shift anything after pos right by len. Reallocate if necessary. - // If pos < size, caller must fill it in with non-null values. - // Returns incremented size; caller is responsible for storing it - // down, if desired. - int expand(int pos, int len) { - assert (pos <= size); - // There must be at least len nulls between elems and attrs. - assert (!hasNulls(NEED_SLOP + len)); // caller responsibility - checkNotFrozen(); - int nsize = size + len; // length of all elements - int tlen = size - pos; // length of elements in post-pos tail - int abase = attrBase(); - int alen = parts.length - abase; // slots allocated for attrs - int nlen = nsize + alen + NEED_SLOP; - nlen += (nlen >>> 1); // add new slop! - Object[] nparts = new Object[nlen]; - // copy head of sub-elements - System.arraycopy(parts, 0, nparts, 0, pos); - // copy tail of sub-elements - System.arraycopy(parts, pos, nparts, pos + len, tlen); - // copy attributes - System.arraycopy(parts, abase, nparts, nlen - alen, alen); - // update self - parts = nparts; - //assert(hasNulls(len)); <- not yet true, since size != nsize - return nsize; - } - - // Open or expand at the given position, as appropriate. - boolean openOrExpand(int pos, int len) { - if (pos < 0 || pos > size) { - badIndex(pos); - } - if (hasNulls(len + NEED_SLOP)) { - if (pos == size) { - size += len; - } else { - open(pos, len); - } - return false; - } else { - size = expand(pos, len); - return true; - } - } - - // Close up at parts[pos] len old places. - // Shift anything after pos left by len. - // Fill unused end of parts with null. - void close(int pos, int len) { - assert (len > 0); - assert ((size - pos) >= len); - checkNotFrozen(); - int tlen = (size - pos) - len; // length of elements in post-pos tail - int nsize = size - len; - System.arraycopy(parts, pos + len, parts, pos, tlen); - // reinitialize the unoccupied slots to null - clearParts(nsize, nsize + len); - // update self - size = nsize; - assert (hasNulls(len)); - } - - public void writeTo(Writer w) throws IOException { - new Printer(w).print(this); - } - - public void writePrettyTo(Writer w) throws IOException { - prettyPrintTo(w, this); - } - - public String prettyString() { - StringWriter sw = new StringWriter(); - try { - writePrettyTo(sw); - } catch (IOException ee) { - throw new Error(ee); // should not happen - } - return sw.toString(); - } - - @Override - public String toString() { - StringWriter sw = new StringWriter(); - try { - writeTo(sw); - } catch (IOException ee) { - throw new Error(ee); // should not happen - } - return sw.toString(); - } - - public String dump() { - // For debugging only. Reveals internal layout. - StringBuilder buf = new StringBuilder(); - buf.append("<").append(name).append("[").append(size).append("]"); - for (int i = 0; i < parts.length; i++) { - Object p = parts[i]; - if (p == null) { - buf.append(" null"); - } else { - buf.append(" {"); - String cname = p.getClass().getName(); - cname = cname.substring(1 + cname.indexOf('/')); - cname = cname.substring(1 + cname.indexOf('$')); - cname = cname.substring(1 + cname.indexOf('#')); - if (!cname.equals("String")) { - buf.append(cname).append(":"); - } - buf.append(p); - buf.append("}"); - } - } - return buf.append(">").toString(); - } - - public static java.lang.reflect.Method method(String name) { - HashMap allM = allMethods; - if (allM == null) { - allM = makeAllMethods(); - } - java.lang.reflect.Method res = (java.lang.reflect.Method) allMethods.get(name); - if (res == null) { - throw new IllegalArgumentException(name); - } - return res; - } - private static HashMap allMethods; - - private static synchronized HashMap makeAllMethods() { - if (allMethods != null) { - return allMethods; - } - java.lang.reflect.Method[] methods = Element.class.getMethods(); - HashMap allM = new HashMap(), - ambig = new HashMap(); - for (int i = 0; i < methods.length; i++) { - java.lang.reflect.Method m = methods[i]; - Class[] args = m.getParameterTypes(); - String name = m.getName(); - assert (java.lang.reflect.Modifier.isPublic(m.getModifiers())); - if (name.startsWith("notify")) { - continue; - } - if (name.endsWith("Attr") - && args.length > 0 && args[0] == int.class) // ignore getAttr(int), etc. - { - continue; - } - if (name.endsWith("All") - && args.length > 1 && args[0] == Filter.class) // ignore findAll(Filter, int...), etc. - { - continue; - } - java.lang.reflect.Method pm = allM.put(name, m); - if (pm != null) { - Class[] pargs = pm.getParameterTypes(); - if (pargs.length > args.length) { - allM.put(name, pm); // put it back - } else if (pargs.length == args.length) { - ambig.put(name, pm); // make a note of it - } - } - } - // Delete ambiguous methods. - for (Map.Entry e : ambig.entrySet()) { - String name = e.getKey(); - java.lang.reflect.Method pm = e.getValue(); - java.lang.reflect.Method m = allM.get(name); - Class[] args = m.getParameterTypes(); - Class[] pargs = pm.getParameterTypes(); - if (pargs.length == args.length) { - //System.out.println("ambig: "+pm); - //System.out.println(" with: "+m); - //ambig: int addAll(int,Element) - // with: int addAll(int,Collection) - allM.put(name, null); // get rid of - } - } - //System.out.println("allM: "+allM); - return allMethods = allM; - } - } - - static Object fixupString(Object part) { - if (part instanceof CharSequence && !(part instanceof String)) { - return part.toString(); - } else { - return part; - } - } - - public static final class Special implements Comparable { - - String kind; - Object value; - - public Special(String kind, Object value) { - this.kind = kind; - this.value = value; - } - - public String getKind() { - return kind; - } - - public Object getValue() { - return value; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Special)) { - return false; - } - Special that = (Special) o; - return this.kind.equals(that.kind) && this.value.equals(that.value); - } - - @Override - public int hashCode() { - return kind.hashCode() * 65 + value.hashCode(); - } - - public int compareTo(Special that) { - int r = this.kind.compareTo(that.kind); - if (r != 0) { - return r; - } - return ((Comparable) this.value).compareTo(that.value); - } - - @Override - public String toString() { - int split = kind.indexOf(' '); - String pref = kind.substring(0, split < 0 ? 0 : split); - String post = kind.substring(split + 1); - return pref + value + post; - } - } - - /** Supports sorting of mixed content. Sorts strings first, - * then Elements, then everything else (as Comparable). - */ - public static Comparator contentOrder() { - return CONTENT_ORDER; - } - private static Comparator CONTENT_ORDER = new ContentComparator(); - - private static class ContentComparator implements Comparator { - - public int compare(Object o1, Object o2) { - boolean cs1 = (o1 instanceof CharSequence); - boolean cs2 = (o2 instanceof CharSequence); - if (cs1 && cs2) { - String s1 = (String) fixupString(o1); - String s2 = (String) fixupString(o2); - return s1.compareTo(s2); - } - if (cs1) { - return 0 - 1; - } - if (cs2) { - return 1 - 0; - } - boolean el1 = (o1 instanceof Element); - boolean el2 = (o2 instanceof Element); - if (el1 && el2) { - return ((Element) o1).compareTo((Element) o2); - } - if (el1) { - return 0 - 1; - } - if (el2) { - return 1 - 0; - } - return ((Comparable) o1).compareTo(o2); - } - } - - /** Used to find, filter, or transform sub-elements. - * When used as a predicate, the filter returns a null - * value for false, and the original object value for true. - * When used as a transformer, the filter may return - * null, for no values, the original object, a new object, - * or an anonymous Element (meaning multiple results). - */ - public interface Filter { - - Object filter(Object value); - } - - /** Use this to find an element, perhaps with a given name. */ - public static class ElementFilter implements Filter { - - /** Subclasses may override this to implement better value tests. - * By default, it returns the element itself, thus recognizing - * all elements, regardless of name. - */ - public Element filter(Element elem) { - return elem; // override this - } - - public final Object filter(Object value) { - if (!(value instanceof Element)) { - return null; - } - return filter((Element) value); - } - - @Override - public String toString() { - return ""; - } - } - private static Filter elementFilter; - - public static Filter elementFilter() { - return (elementFilter != null) ? elementFilter : (elementFilter = new ElementFilter()); - } - - public static Filter elementFilter(final String name) { - name.toString(); // null check - return new ElementFilter() { - - @Override - public Element filter(Element elem) { - return name.equals(elem.name) ? elem : null; - } - - @Override - public String toString() { - return ""; - } - }; - } - - public static Filter elementFilter(final Collection nameSet) { - Objects.requireNonNull(nameSet); - return new ElementFilter() { - - @Override - public Element filter(Element elem) { - return nameSet.contains(elem.name) ? elem : null; - } - - @Override - public String toString() { - return ""; - } - }; - } - - public static Filter elementFilter(String... nameSet) { - Collection ncoll = Arrays.asList(nameSet); - if (nameSet.length > 10) { - ncoll = new HashSet(ncoll); - } - return elementFilter(ncoll); - } - - /** Use this to find an element with a named attribute, - * possibly with a particular value. - * (Note that an attribute is missing if and only if its value is null.) - */ - public static class AttrFilter extends ElementFilter { - - protected final String attrName; - - public AttrFilter(String attrName) { - this.attrName = attrName.toString(); - } - - /** Subclasses may override this to implement better value tests. - * By default, it returns true for any non-null value, thus - * recognizing any attribute of the given name, regardless of value. - */ - public boolean test(String attrVal) { - return attrVal != null; // override this - } - - @Override - public final Element filter(Element elem) { - return test(elem.getAttr(attrName)) ? elem : null; - } - - @Override - public String toString() { - return ""; - } - } - - public static Filter attrFilter(String attrName) { - return new AttrFilter(attrName); - } - - public static Filter attrFilter(String attrName, final String attrVal) { - if (attrVal == null) { - return not(attrFilter(attrName)); - } - return new AttrFilter(attrName) { - - @Override - public boolean test(String attrVal2) { - return attrVal.equals(attrVal2); - } - - @Override - public String toString() { - return ""; - } - }; - } - - public static Filter attrFilter(Element matchThis, String attrName) { - return attrFilter(attrName, matchThis.getAttr(attrName)); - } - - /** Use this to find a sub-element of a given class. */ - public static Filter classFilter(final Class clazz) { - return new Filter() { - - public Object filter(Object value) { - return clazz.isInstance(value) ? value : null; - } - - @Override - public String toString() { - return ""; - } - }; - } - private static Filter textFilter; - - public static Filter textFilter() { - return (textFilter != null) ? textFilter : (textFilter = classFilter(CharSequence.class)); - } - private static Filter specialFilter; - - public static Filter specialFilter() { - return (specialFilter != null) ? specialFilter : (specialFilter = classFilter(Special.class)); - } - private static Filter selfFilter; - - /** This filter always returns its own argument. */ - public static Filter selfFilter() { - if (selfFilter != null) { - return selfFilter; - } - return selfFilter = new Filter() { - - public Object filter(Object value) { - return value; - } - - @Override - public String toString() { - return ""; - } - }; - } - - /** This filter always returns a fixed value, regardless of argument. */ - public static Filter constantFilter(final Object value) { - return new Filter() { - - public Object filter(Object ignore) { - return value; - } - - @Override - public String toString() { - return "" + value + ""; - } - }; - } - private static Filter nullFilter; - - public static Filter nullFilter() { - return (nullFilter != null) ? nullFilter : (nullFilter = constantFilter(null)); - } - private static Filter emptyFilter; - - public static Filter emptyFilter() { - return (emptyFilter != null) ? emptyFilter : (emptyFilter = constantFilter(Element.EMPTY)); - } - - /** Use this to invert the logical sense of the given filter. */ - public static Filter not(final Filter f) { - return new Filter() { - - public Object filter(Object value) { - return f.filter(value) == null ? value : null; - } - - @Override - public String toString() { - return "" + f + ""; - } - }; - } - - /** Use this to combine several filters with logical AND. - * Returns either the first null or the last non-null value. - */ - public static Filter and(final Filter f0, final Filter f1) { - return and(new Filter[]{f0, f1}); - } - - public static Filter and(final Filter... fs) { - switch (fs.length) { - case 0: - return selfFilter(); // always true (on non-null inputs) - case 1: - return fs[0]; - } - return new Filter() { - - public Object filter(Object value) { - Object res = fs[0].filter(value); - if (res != null) { - res = fs[1].filter(value); - for (int i = 2; res != null && i < fs.length; i++) { - res = fs[i].filter(value); - } - } - return res; - } - - @Override - public String toString() { - return opToString("", fs, ""); - } - }; - } - - /** Use this to combine several filters with logical OR. - * Returns either the first non-null or the last null value. - */ - public static Filter or(final Filter f0, final Filter f1) { - return or(new Filter[]{f0, f1}); - } - - public static Filter or(final Filter... fs) { - switch (fs.length) { - case 0: - return nullFilter(); - case 1: - return fs[0]; - } - return new Filter() { - - public Object filter(Object value) { - Object res = fs[0].filter(value); - if (res == null) { - res = fs[1].filter(value); - for (int i = 2; res == null && i < fs.length; i++) { - res = fs[i].filter(value); - } - } - return res; - } - - @Override - public String toString() { - return opToString("", fs, ""); - } - }; - } - - /** Use this to combine several filters with logical AND, - * and where each non-null result is passed as the argument - * to the next filter. - * Returns either the first null or the last non-null value. - */ - public static Filter stack(final Filter f0, final Filter f1) { - return stack(new Filter[]{f0, f1}); - } - - public static Filter stack(final Filter... fs) { - switch (fs.length) { - case 0: - return nullFilter(); - case 1: - return fs[0]; - } - return new Filter() { - - public Object filter(Object value) { - Object res = fs[0].filter(value); - if (res != null) { - res = fs[1].filter(res); - for (int i = 2; res != null && i < fs.length; i++) { - res = fs[i].filter(res); - } - } - return res; - } - - @Override - public String toString() { - return opToString("", fs, ""); - } - }; - } - - /** Copy everything produced by f to sink, using addContent. */ - public static Filter content(final Filter f, final Collection sink) { - return new Filter() { - - public Object filter(Object value) { - Object res = f.filter(value); - addContent(res, sink); - return res; - } - - @Override - public String toString() { - return opToString("", new Object[]{f, sink}, - ""); - } - }; - } - - /** Look down the tree using f, collecting fx, else recursing into x. - * Identities: - * - * findInTree(f, s) == findInTree(content(f, s)) - * findInTree(f) == replaceInTree(and(f, selfFilter())). - * - */ - public static Filter findInTree(Filter f, Collection sink) { - if (sink != null) { - f = content(f, sink); - } - return findInTree(f); - } - - /** Look down the tree using f, recursing into x unless fx. */ - public static Filter findInTree(final Filter f) { - return new Filter() { - - public Object filter(Object value) { - Object res = f.filter(value); - if (res != null) { - return res; - } - if (value instanceof Element) { - // recurse - return ((Element) value).find(this); - } - return null; - } - - @Override - public String toString() { - return opToString("", new Object[]{f}, - ""); - } - }; - } - - /** Look down the tree using f. Replace each x with fx, else recurse. - * If post filter g is given, optionally replace with gx after recursion. - */ - public static Filter replaceInTree(final Filter f, final Filter g) { - return new Filter() { - - public Object filter(Object value) { - Object res = (f == null) ? null : f.filter(value); - if (res != null) { - return res; - } - if (value instanceof Element) { - // recurse - ((Element) value).replaceAll(this); - // Optional postorder traversal: - if (g != null) { - res = g.filter(value); - } - } - return res; // usually null, meaning no replacement - } - - @Override - public String toString() { - return opToString("", - new Object[]{f, g}, - ""); - } - }; - } - - public static Filter replaceInTree(Filter f) { - Objects.requireNonNull(f); - return replaceInTree(f, null); - } - - /** Make a filter which calls this method on the given element. - * If the method is static, the first argument is passed the - * the subtree value being filtered. - * If the method is non-static, the receiver is the subtree value itself. - *

    - * Optionally, additional arguments may be specified. - *

    - * If the filtered value does not match the receiver class - * (or else the first argument type, if the method is static), - * the filter returns null without invoking the method. - *

    - * The returned filter value is the result returned from the method. - * Optionally, a non-null special false result value may be specified. - * If the result returned from the method is equal to that false value, - * the filter will return null. - */ - public static Filter methodFilter(java.lang.reflect.Method m, Object[] extraArgs, - Object falseResult) { - return methodFilter(m, false, extraArgs, falseResult); - } - - public static Filter methodFilter(java.lang.reflect.Method m, - Object[] args) { - return methodFilter(m, args, null); - } - - public static Filter methodFilter(java.lang.reflect.Method m) { - return methodFilter(m, null, null); - } - - public static Filter testMethodFilter(java.lang.reflect.Method m, Object[] extraArgs, - Object falseResult) { - return methodFilter(m, true, extraArgs, falseResult); - } - - public static Filter testMethodFilter(java.lang.reflect.Method m, Object[] extraArgs) { - return methodFilter(m, true, extraArgs, zeroArgs.get(m.getReturnType())); - } - - public static Filter testMethodFilter(java.lang.reflect.Method m) { - return methodFilter(m, true, null, zeroArgs.get(m.getReturnType())); - } - - private static Filter methodFilter(final java.lang.reflect.Method m, - final boolean isTest, - Object[] extraArgs, final Object falseResult) { - Class[] params = m.getParameterTypes(); - final boolean isStatic = java.lang.reflect.Modifier.isStatic(m.getModifiers()); - int insertLen = (isStatic ? 1 : 0); - if (insertLen + (extraArgs == null ? 0 : extraArgs.length) > params.length) { - throw new IllegalArgumentException("too many arguments"); - } - final Object[] args = (params.length == insertLen) ? null - : new Object[params.length]; - final Class valueType = !isStatic ? m.getDeclaringClass() : params[0]; - if (valueType.isPrimitive()) { - throw new IllegalArgumentException("filtered value must be reference type"); - } - int fillp = insertLen; - if (extraArgs != null) { - for (int i = 0; i < extraArgs.length; i++) { - args[fillp++] = extraArgs[i]; - } - } - if (args != null) { - while (fillp < args.length) { - Class param = params[fillp]; - args[fillp++] = param.isPrimitive() ? zeroArgs.get(param) : null; - } - } - final Thread curt = Thread.currentThread(); - class MFilt implements Filter { - - public Object filter(Object value) { - if (!valueType.isInstance(value)) { - return null; // filter fails quickly - } - Object[] args1 = args; - if (isStatic) { - if (args1 == null) { - args1 = new Object[1]; - } else if (curt != Thread.currentThread()) // Dirty hack to curtail array copying in common case. - { - args1 = (Object[]) args1.clone(); - } - args1[0] = value; - } - Object res; - try { - res = m.invoke(value, args1); - } catch (java.lang.reflect.InvocationTargetException te) { - Throwable ee = te.getCause(); - if (ee instanceof RuntimeException) { - throw (RuntimeException) ee; - } - if (ee instanceof Error) { - throw (Error) ee; - } - throw new RuntimeException("throw in filter", ee); - } catch (IllegalAccessException ee) { - throw new RuntimeException("access error in filter", ee); - } - if (res == null) { - if (!isTest && m.getReturnType() == Void.TYPE) { - // Void methods return self by convention. - // (But void "tests" always return false.) - res = value; - } - } else { - if (falseResult != null && falseResult.equals(res)) { - res = null; - } else if (isTest) { - // Tests return self by convention. - res = value; - } - } - return res; - } - - @Override - public String toString() { - return "" + m + ""; - } - } - return new MFilt(); - } - private static HashMap zeroArgs = new HashMap(); - - static { - zeroArgs.put(Boolean.TYPE, Boolean.FALSE); - zeroArgs.put(Character.TYPE, new Character((char) 0)); - zeroArgs.put(Byte.TYPE, new Byte((byte) 0)); - zeroArgs.put(Short.TYPE, new Short((short) 0)); - zeroArgs.put(Integer.TYPE, new Integer(0)); - zeroArgs.put(Float.TYPE, new Float(0)); - zeroArgs.put(Long.TYPE, new Long(0)); - zeroArgs.put(Double.TYPE, new Double(0)); - } - - private static String opToString(String s1, Object[] s2, String s3) { - StringBuilder buf = new StringBuilder(s1); - for (int i = 0; i < s2.length; i++) { - if (s2[i] != null) { - buf.append(s2[i]); - } - } - buf.append(s3); - return buf.toString(); - } - - /** Call the filter on each list element x, and replace x with the - * resulting filter value e, or its parts. - * If e is null, keep x. (This eases use of partial-domain filters.) - * If e is a TokenList or an anonymous Element, add e's parts - * to the list instead of x. - * Otherwise, replace x by e. - *

    - * The effect at each list position n may be expressed - * in terms of XMLKit.addContent as follows: - *

    -     *     Object e = f.filter(target.get(n));
    -     *     if (e != null) {
    -     *         target.remove(n);
    -     *         addContent(e, target.subList(n,n));
    -     *     }
    -     *  
    - *

    - * Note: To force deletion of x, simply have the filter return - * Element.EMPTY or TokenList.EMPTY. - * To force null filter values to have this effect, - * use the expression: or(f, emptyFilter()). - */ - public static void replaceAll(Filter f, List target) { - for (ListIterator i = target.listIterator(); i.hasNext();) { - Object x = i.next(); - Object fx = f.filter(x); - if (fx == null) { - // Unliked addContent, a null is a no-op here. - // i.remove(); - } else if (fx instanceof TokenList) { - TokenList tl = (TokenList) fx; - if (tl.size() == 1) { - i.set(tl); - } else { - i.remove(); - for (String part : tl) { - i.add(part); - } - } - } else if (fx instanceof Element - && ((Element) fx).isAnonymous()) { - Element anon = (Element) fx; - if (anon.size() == 1) { - i.set(anon); - } else { - i.remove(); - for (Object part : anon) { - i.add(part); - } - } - } else if (x != fx) { - i.set(fx); - } - } - } - - /** If e is null, return zero. - * If e is a TokenList or an anonymous Element, add e's parts - * to the collection, and return the number of parts. - * Otherwise, add e to the collection, and return one. - * If the collection reference is null, the result is as if - * a throwaway collection were used. - */ - public static int addContent(Object e, Collection sink) { - if (e == null) { - return 0; - } else if (e instanceof TokenList) { - TokenList tl = (TokenList) e; - if (sink != null) { - sink.addAll(tl); - } - return tl.size(); - } else if (e instanceof Element - && ((Element) e).isAnonymous()) { - Element anon = (Element) e; - if (sink != null) { - sink.addAll(anon.asList()); - } - return anon.size(); - } else { - if (sink != null) { - sink.add(e); - } - return 1; - } - } - - static Collection newCounterColl() { - return new AbstractCollection() { - - int size; - - public int size() { - return size; - } - - @Override - public boolean add(Object o) { - ++size; - return true; - } - - public Iterator iterator() { - throw new UnsupportedOperationException(); - } - }; - } - - /** SAX2 document handler for building Element trees. */ - private static class Builder implements ContentHandler, LexicalHandler { - /*, EntityResolver, DTDHandler, ErrorHandler*/ - - Collection sink; - boolean makeFrozen; - boolean tokenizing; - - Builder(Collection sink, boolean tokenizing, boolean makeFrozen) { - this.sink = sink; - this.tokenizing = tokenizing; - this.makeFrozen = makeFrozen; - } - Object[] parts = new Object[30]; - int nparts = 0; - int[] attrBases = new int[10]; // index into parts - int[] elemBases = new int[10]; // index into parts - int depth = -1; // index into attrBases, elemBases - // Parts is organized this way: - // | name0 | akey aval ... | subelem ... | name1 | ... | - // The position of the first "akey" after name0 is attrBases[0]. - // The position of the first "subelem" after name0 is elemBases[0]. - // The position after the last part is always nparts. - int mergeableToken = -1; // index into parts of recent CharSequence - boolean inCData = false; - - void addPart(Object x) { - //System.out.println("addPart "+x); - if (nparts == parts.length) { - Object[] newParts = new Object[parts.length * 2]; - System.arraycopy(parts, 0, newParts, 0, parts.length); - parts = newParts; - } - parts[nparts++] = x; - } - - Object getMergeableToken() { - if (mergeableToken == nparts - 1) { - assert (parts[mergeableToken] instanceof CharSequence); - return parts[nparts - 1]; - } else { - return null; - } - } - - void clearMergeableToken() { - if (mergeableToken >= 0) { - // Freeze temporary StringBuffers into strings. - assert (parts[mergeableToken] instanceof CharSequence); - parts[mergeableToken] = parts[mergeableToken].toString(); - mergeableToken = -1; - } - } - - void setMergeableToken() { - if (mergeableToken != nparts - 1) { - clearMergeableToken(); - mergeableToken = nparts - 1; - assert (parts[mergeableToken] instanceof CharSequence); - } - } - - // ContentHandler callbacks - public void startElement(String ns, String localName, String name, Attributes atts) { - clearMergeableToken(); - addPart(name.intern()); - ++depth; - if (depth == attrBases.length) { - int oldlen = depth; - int newlen = depth * 2; - int[] newAB = new int[newlen]; - int[] newEB = new int[newlen]; - System.arraycopy(attrBases, 0, newAB, 0, oldlen); - System.arraycopy(elemBases, 0, newEB, 0, oldlen); - attrBases = newAB; - elemBases = newEB; - } - attrBases[depth] = nparts; - // Collect attributes. - int na = atts.getLength(); - for (int k = 0; k < na; k++) { - addPart(atts.getQName(k).intern()); - addPart(atts.getValue(k)); - } - // Get ready to collect elements. - elemBases[depth] = nparts; - } - - public void endElement(String ns, String localName, String name) { - assert (depth >= 0); - clearMergeableToken(); - int ebase = elemBases[depth]; - int elen = nparts - ebase; - int abase = attrBases[depth]; - int alen = ebase - abase; - int nbase = abase - 1; - int cap = alen + (makeFrozen ? 0 : NEED_SLOP) + elen; - Element e = new Element((String) parts[nbase], elen, cap); - // Set up attributes. - for (int k = 0; k < alen; k += 2) { - e.parts[cap - k - 2] = parts[abase + k + 0]; - e.parts[cap - k - 1] = parts[abase + k + 1]; - } - // Set up sub-elements. - System.arraycopy(parts, ebase, e.parts, 0, elen); - // Back out of this level. - --depth; - nparts = nbase; - assert (e.isFrozen() == makeFrozen); - assert (e.size() == elen); - assert (e.attrSize() * 2 == alen); - if (depth >= 0) { - addPart(e); - } else { - sink.add(e); - } - } - - public void startCDATA() { - inCData = true; - } - - public void endCDATA() { - inCData = false; - } - - public void characters(char[] buf, int off, int len) { - boolean headSpace = false; - boolean tailSpace = false; - int firstLen; - if (tokenizing && !inCData) { - // Strip unquoted blanks. - while (len > 0 && isWhitespace(buf[off])) { - headSpace = true; - ++off; - --len; - } - if (len == 0) { - tailSpace = true; // it is all space - } - while (len > 0 && isWhitespace(buf[off + len - 1])) { - tailSpace = true; - --len; - } - firstLen = 0; - while (firstLen < len && !isWhitespace(buf[off + firstLen])) { - ++firstLen; - } - } else { - firstLen = len; - } - if (headSpace) { - clearMergeableToken(); - } - boolean mergeAtEnd = !tailSpace; - // If buffer was empty, or had only ignorable blanks, do nothing. - if (len == 0) { - return; - } - // Decide whether to merge some of these chars into a previous token. - Object prev = getMergeableToken(); - if (prev instanceof StringBuffer) { - ((StringBuffer) prev).append(buf, off, firstLen); - } else if (prev == null) { - addPart(new String(buf, off, firstLen)); - } else { - // Merge two strings. - String prevStr = prev.toString(); - StringBuffer prevBuf = new StringBuffer(prevStr.length() + firstLen); - prevBuf.append(prevStr); - prevBuf.append(buf, off, firstLen); - if (mergeAtEnd && len == firstLen) { - // Replace previous string with new StringBuffer. - parts[nparts - 1] = prevBuf; - } else { - // Freeze it now. - parts[nparts - 1] = prevBuf.toString(); - } - } - off += firstLen; - len -= firstLen; - if (len > 0) { - // Appended only the first token. - clearMergeableToken(); - // Add the rest as separate parts. - while (len > 0) { - while (len > 0 && isWhitespace(buf[off])) { - ++off; - --len; - } - int nextLen = 0; - while (nextLen < len && !isWhitespace(buf[off + nextLen])) { - ++nextLen; - } - assert (nextLen > 0); - addPart(new String(buf, off, nextLen)); - off += nextLen; - len -= nextLen; - } - } - if (mergeAtEnd) { - setMergeableToken(); - } - } - - public void ignorableWhitespace(char[] buf, int off, int len) { - clearMergeableToken(); - if (false) { - characters(buf, off, len); - clearMergeableToken(); - } - } - - public void comment(char[] buf, int off, int len) { - addPart(new Special("", new String(buf, off, len))); - } - - public void processingInstruction(String name, String instruction) { - Element pi = new Element(name); - pi.add(instruction); - addPart(new Special("", pi)); - } - - public void skippedEntity(String name) { - } - - public void startDTD(String name, String publicId, String systemId) { - } - - public void endDTD() { - } - - public void startEntity(String name) { - } - - public void endEntity(String name) { - } - - public void setDocumentLocator(org.xml.sax.Locator locator) { - } - - public void startDocument() { - } - - public void endDocument() { - } - - public void startPrefixMapping(String prefix, String uri) { - } - - public void endPrefixMapping(String prefix) { - } - } - - /** Produce a ContentHandler for use with an XML parser. - * The object is also a LexicalHandler. - * Every top-level Element produced will get added to sink. - * All elements will be frozen iff makeFrozen is true. - */ - public static ContentHandler makeBuilder(Collection sink, boolean tokenizing, boolean makeFrozen) { - return new Builder(sink, tokenizing, makeFrozen); - } - - public static ContentHandler makeBuilder(Collection sink, boolean tokenizing) { - return new Builder(sink, tokenizing, false); - } - - public static ContentHandler makeBuilder(Collection sink) { - return makeBuilder(sink, false, false); - } - - public static Element readFrom(Reader in, boolean tokenizing, boolean makeFrozen) throws IOException { - Element sink = new Element(); - ContentHandler b = makeBuilder(sink.asList(), tokenizing, makeFrozen); - XMLReader parser; - try { - parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); - } catch (SAXException ee) { - throw new Error(ee); - } - //parser.setFastStandalone(true); - parser.setContentHandler(b); - try { - parser.setProperty("http://xml.org/sax/properties/lexical-handler", - (LexicalHandler) b); - } catch (SAXException ee) { - // Ignore. We will miss the comments and whitespace. - } - try { - parser.parse(new InputSource(in)); - } catch (SAXParseException ee) { - throw new RuntimeException("line " + ee.getLineNumber() + " col " + ee.getColumnNumber() + ": ", ee); - } catch (SAXException ee) { - throw new RuntimeException(ee); - } - switch (sink.size()) { - case 0: - return null; - case 1: - if (sink.get(0) instanceof Element) { - return (Element) sink.get(0); - } - // fall through - default: - if (makeFrozen) { - sink.shallowFreeze(); - } - return sink; - } - } - - public static Element readFrom(Reader in, boolean tokenizing) throws IOException { - return readFrom(in, tokenizing, false); - } - - public static Element readFrom(Reader in) throws IOException { - return readFrom(in, false, false); - } - - public static void prettyPrintTo(OutputStream out, Element e) throws IOException { - prettyPrintTo(new OutputStreamWriter(out), e); - } - - public static void prettyPrintTo(Writer out, Element e) throws IOException { - Printer pr = new Printer(out); - pr.pretty = true; - pr.print(e); - } - - static class Outputter { - - ContentHandler ch; - LexicalHandler lh; - - Outputter(ContentHandler ch, LexicalHandler lh) { - this.ch = ch; - this.lh = lh; - } - AttributesImpl atts = new AttributesImpl(); // handy - - void output(Object x) throws SAXException { - // Cf. jdom.org/jdom-b8/src/java/org/jdom/output/SAXOutputter.java - if (x instanceof Element) { - Element e = (Element) x; - atts.clear(); - for (int asize = e.attrSize(), k = 0; k < asize; k++) { - String key = e.getAttrName(k); - String val = e.getAttr(k); - atts.addAttribute("", "", key, "CDATA", val); - } - ch.startElement("", "", e.getName(), atts); - for (int i = 0; i < e.size(); i++) { - output(e.get(i)); - } - ch.endElement("", "", e.getName()); - } else if (x instanceof Special) { - Special sp = (Special) x; - if (sp.kind.startsWith(""); - Element ce = e.copyContentOnly(); - ce.sort(); - prettyPrintTo(new OutputStreamWriter(System.out), ce); - } - { - System.out.println(""); - Element tr = e.deepCopy(); - findInTree(testMethodFilter(Element.method("trimText"))).filter(tr); - System.out.println(tr); - } - { - System.out.println(""); - Element us = e.deepCopy(); - int nr = us.retainAllInTree(elementFilter(), null); - System.out.println("nr=" + nr); - System.out.println(us); - } - { - System.out.println(""); - Element ru = e.deepCopy(); - Filter makeAnonF = - methodFilter(Element.method("setName"), - new Object[]{ANON_NAME}); - Filter testSizeF = - testMethodFilter(Element.method("size")); - Filter walk = - replaceInTree(and(not(elementFilter()), emptyFilter()), - and(testSizeF, makeAnonF)); - ru = (Element) walk.filter(ru); - //System.out.println(ru); - prettyPrintTo(new OutputStreamWriter(System.out), ru); - } - } - - static boolean isWhitespace(char c) { - switch (c) { - case 0x20: - case 0x09: - case 0x0D: - case 0x0A: - return true; - } - return false; - } -} diff --git a/test/jdk/tools/pack200/typeannos/Lambda.java b/test/jdk/tools/pack200/typeannos/Lambda.java deleted file mode 100644 index ed2553b5c92..00000000000 --- a/test/jdk/tools/pack200/typeannos/Lambda.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @Xtest - * @bug 8008077 - * @summary new type annotation location: lambda expressions - * @compile Lambda.java - * @author Werner Dietl - */ - -import java.lang.annotation.*; - -public class Lambda { - - interface LambdaInt { - void generic(S p1, T p2); - } - - static class LambdaImpl implements LambdaInt { - LambdaImpl(S p1, T p2) {} - public void generic(S p1, T p2) {} - } - - LambdaInt getMethodRefTA(LambdaImpl r) { - return r::<@TA Object, @TB Object>generic; - } - - LambdaInt getConstructorRefTA() { - return LambdaImpl::<@TA Object, @TB Object>new; - } - -} - -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@interface TA { } - -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@interface TB { } diff --git a/test/jdk/tools/pack200/typeannos/Readme.txt b/test/jdk/tools/pack200/typeannos/Readme.txt deleted file mode 100644 index c3c2fcffff4..00000000000 --- a/test/jdk/tools/pack200/typeannos/Readme.txt +++ /dev/null @@ -1,11 +0,0 @@ -This directory contains tests which exercises all possible TypeAnnotations -structure. These tests are borrowed from -langtools/test/tools.javac/annotations/typeAnnotations. - -The reason it is copied over is that we need to test pack200 and these -annotation may not be present in any of the JDK/JRE jars, yet we need to test -all these cases. - - -Therefore it would be a good practice to sync these tests with the original -if there are any changes. diff --git a/test/jdk/tools/pack200/typeannos/TargetTypes.java b/test/jdk/tools/pack200/typeannos/TargetTypes.java deleted file mode 100644 index 0af6db159c5..00000000000 --- a/test/jdk/tools/pack200/typeannos/TargetTypes.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; - -import java.util.*; -import java.io.*; - -/* - * @Xtest - * @summary compiler accepts all values - * @author Mahmood Ali - * @author Yuri Gaevsky - * @compile TargetTypes.java - */ - -@Target({TYPE_USE, TYPE_PARAMETER, TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@interface A {} - -/** wildcard bound */ -class T0x1C { - void m0x1C(List lst) {} -} - -/** wildcard bound generic/array */ -class T0x1D { - void m0x1D(List> lst) {} -} - -/** typecast */ -class T0x00 { - void m0x00(Long l1) { - Object l2 = (@A Long) l1; - } -} - -/** typecast generic/array */ -class T0x01 { - void m0x01(List list) { - List l = (List<@A T>) list; - } -} - -/** instanceof */ -class T0x02 { - boolean m0x02(String s) { - return (s instanceof @A String); - } -} - -/** object creation (new) */ -class T0x04 { - void m0x04() { - new @A ArrayList(); - } -} - -/** local variable */ -class T0x08 { - void m0x08() { - @A String s = null; - } -} - -/** method parameter generic/array */ -class T0x0D { - void m0x0D(HashMap<@A Object, List<@A List<@A Class>>> s1) {} -} - -/** method receiver */ -class T0x06 { - void m0x06(@A T0x06 this) {} -} - -/** method return type generic/array */ -class T0x0B { - Class<@A Object> m0x0B() { return null; } -} - -/** field generic/array */ -class T0x0F { - HashMap<@A Object, @A Object> c1; -} - -/** method type parameter */ -class T0x20 { - <@A T, @A U> void m0x20() {} -} - -/** class type parameter */ -class T0x22<@A T, @A U> { -} - -/** class type parameter bound */ -class T0x10 { -} - -/** method type parameter bound */ -class T0x12 { - void m0x12() {} -} - -/** class type parameter bound generic/array */ -class T0x11> { -} - - -/** method type parameter bound generic/array */ -class T0x13 { - static > T m0x13() { - return null; - } -} - -/** class extends/implements generic/array */ -class T0x15 extends ArrayList<@A T> { -} - -/** type test (instanceof) generic/array */ -class T0x03 { - void m0x03(T typeObj, Object obj) { - boolean ok = obj instanceof String @A []; - } -} - -/** object creation (new) generic/array */ -class T0x05 { - void m0x05() { - new ArrayList<@A T>(); - } -} - -/** local variable generic/array */ -class T0x09 { - void g() { - List<@A String> l = null; - } - - void a() { - String @A [] as = null; - } -} - -/** type argument in constructor call generic/array */ -class T0x19 { - T0x19() {} - - void g() { - new > T0x19(); - } -} - -/** type argument in method call generic/array */ -class T0x1B { - void m0x1B() { - Collections.emptyList(); - } -} - -/** type argument in constructor call */ -class T0x18 { - T0x18() {} - - void m() { - new <@A Integer> T0x18(); - } -} - -/** type argument in method call */ -class T0x1A { - public static T m() { return null; } - static void m0x1A() { - T0x1A.<@A Integer, @A Short>m(); - } -} - -/** class extends/implements */ -class T0x14 extends @A Object implements @A Serializable, @A Cloneable { -} - -/** exception type in throws */ -class T0x16 { - void m0x16() throws @A Exception {} -} - -/** resource variables **/ -class ResourceVariables { - void m() throws Exception { - try (@A InputStream is = new @A FileInputStream("x")){} - } -} - -/** exception parameters **/ -class ExceptionParameters { - void multipleExceptions() { - try { - new Object(); - } catch (@A Exception e) {} - try { - new Object(); - } catch (@A Exception e) {} - try { - new Object(); - } catch (@A Exception e) {} - } -} diff --git a/test/jdk/tools/pack200/typeannos/TestTypeAnnotations.java b/test/jdk/tools/pack200/typeannos/TestTypeAnnotations.java deleted file mode 100644 index f00801b5b14..00000000000 --- a/test/jdk/tools/pack200/typeannos/TestTypeAnnotations.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8001163 - * @summary tests simple TypeAnnotations in classfiles - * @compile -XDignore.symbol.file ../Utils.java - * TestTypeAnnotations.java TargetTypes.java - * TypeUseTarget.java Lambda.java - * @run main TestTypeAnnotations - * @author ksrini - */ -import java.io.File; -import java.io.IOException; - -public class TestTypeAnnotations { - public static void main(String... args) throws IOException { - File testFile = new File("ta.jar"); - Utils.jar("cvf", testFile.getName(), - "-C", Utils.TEST_CLS_DIR.getAbsolutePath(), - "."); - Utils.testWithRepack(testFile, "--unknown-attribute=error"); - Utils.cleanup(); - } -} diff --git a/test/jdk/tools/pack200/typeannos/TypeUseTarget.java b/test/jdk/tools/pack200/typeannos/TypeUseTarget.java deleted file mode 100644 index fcad51c65c9..00000000000 --- a/test/jdk/tools/pack200/typeannos/TypeUseTarget.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @Xtest - * @bug 6843077 8006775 - * @summary check that type annotations may appear on all type declarations - * @author Mahmood Ali - * @compile TypeUseTarget.java - */ - -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; - -@B -class TypeUseTarget { - @B String @B [] field; - - @B String test(@B TypeUseTarget this, @B String param, @B String @B ... vararg) { - @B Object o = new @B String @B [3]; - TypeUseTarget<@B String> target; - return (@B String) null; - } - - @B String genericMethod(K k) { return null; } - @Decl @B String genericMethod1(K k) { return null; } - @B @Decl String genericMethod2(K k) { return null; } - @Decl @B String genericMethod3(K k) { return null; } - @Decl String genericMethod4(K k) { return null; } - @B @Decl String genericMethod5(K k) { return null; } -} - -@B -interface MyInterface { } - -@B -@interface MyAnnotation { } - -@Target(ElementType.TYPE_USE) -@interface B { } - -@interface Decl { } From 63ba804f4f1f1b7b11af6be4a5577ee049a014ad Mon Sep 17 00:00:00 2001 From: Mikhailo Seledtsov Date: Mon, 9 Dec 2019 17:24:25 -0800 Subject: [PATCH 32/32] 8235600: Problemlist JFR streaming/TestJVMCrash until after-test cleanup issue is resolved Placed TestJVMCrash test on a problem list Reviewed-by: dcubed --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 4ebc36c778e..694f5ed03af 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -939,6 +939,7 @@ jdk/jfr/event/io/EvilInstrument.java 8221331 gener jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/api/consumer/recordingstream/TestSetStartTime.java 8233217 generic-all +jdk/jfr/api/consumer/streaming/TestJVMCrash.java 8235599 windows-all ############################################################################