提交 130dc864 编写于 作者: L lana

Merge

...@@ -89,7 +89,7 @@ define FullPath ...@@ -89,7 +89,7 @@ define FullPath
$(shell $(CYGPATH_CMD) $1 2> $(DEV_NULL)) $(shell $(CYGPATH_CMD) $1 2> $(DEV_NULL))
endef endef
define OptFullPath define OptFullPath
$(shell if [ "$1" != "" -a -d "$1" ]; then $(CYGPATH_CMD) "$1"; else echo "$1"; fi) $(shell if [ "$1" != "" -a -d "$1" ]; then $(CYGPATH_CMD) "$1" 2> $(DEV_NULL); else echo "$1"; fi)
endef endef
else else
# Temporary until we upgrade to MKS 8.7, MKS pwd returns mixed mode path # Temporary until we upgrade to MKS 8.7, MKS pwd returns mixed mode path
......
...@@ -136,15 +136,20 @@ define GetVersion ...@@ -136,15 +136,20 @@ define GetVersion
$(shell echo $1 | sed -e 's@[^0-9]*\([0-9][0-9]*\.[0-9][.0-9]*\).*@\1@' ) $(shell echo $1 | sed -e 's@[^0-9]*\([0-9][0-9]*\.[0-9][.0-9]*\).*@\1@' )
endef endef
# Return one part of the version numbers, watch out for non digits.
define VersionWord # Number Version
$(word $1,$(subst ., ,$(subst -, ,$2)))
endef
# Given a major.minor.micro version, return the major, minor, or micro number # Given a major.minor.micro version, return the major, minor, or micro number
define MajorVersion define MajorVersion
$(if $(word 1, $(subst ., ,$1)),$(word 1, $(subst ., ,$1)),0) $(if $(call VersionWord,1,$1),$(call VersionWord,1,$1),0)
endef endef
define MinorVersion define MinorVersion
$(if $(word 2, $(subst ., ,$1)),$(word 2, $(subst ., ,$1)),0) $(if $(call VersionWord,2,$1),$(call VersionWord,2,$1),0)
endef endef
define MicroVersion define MicroVersion
$(if $(word 3, $(subst ., ,$1)),$(word 3, $(subst ., ,$1)),0) $(if $(call VersionWord,3,$1),$(call VersionWord,3,$1),0)
endef endef
# Macro that returns missing, same, newer, or older $1=version $2=required # Macro that returns missing, same, newer, or older $1=version $2=required
......
...@@ -340,6 +340,10 @@ PATH="${path4sdk}" ...@@ -340,6 +340,10 @@ PATH="${path4sdk}"
export PATH export PATH
# Export variables required for Zero # Export variables required for Zero
if [ "${SHARK_BUILD}" = true ] ; then
ZERO_BUILD=true
export ZERO_BUILD
fi
if [ "${ZERO_BUILD}" = true ] ; then if [ "${ZERO_BUILD}" = true ] ; then
# ZERO_LIBARCH is the name of the architecture-specific # ZERO_LIBARCH is the name of the architecture-specific
# subdirectory under $JAVA_HOME/jre/lib # subdirectory under $JAVA_HOME/jre/lib
...@@ -417,4 +421,55 @@ if [ "${ZERO_BUILD}" = true ] ; then ...@@ -417,4 +421,55 @@ if [ "${ZERO_BUILD}" = true ] ; then
fi fi
export LIBFFI_CFLAGS export LIBFFI_CFLAGS
export LIBFFI_LIBS export LIBFFI_LIBS
# LLVM_CFLAGS, LLVM_LDFLAGS and LLVM_LIBS tell the compiler how to
# compile and link against LLVM
if [ "${SHARK_BUILD}" = true ] ; then
if [ "${LLVM_CONFIG}" = "" ] ; then
LLVM_CONFIG=$(which llvm-config 2>/dev/null)
fi
if [ ! -x "${LLVM_CONFIG}" ] ; then
echo "ERROR: Unable to locate llvm-config"
exit 1
fi
llvm_components="jit engine nativecodegen"
unset LLVM_CFLAGS
for flag in $("${LLVM_CONFIG}" --cxxflags $llvm_components); do
if echo "${flag}" | grep -q '^-[ID]'; then
if [ "${flag}" != "-D_DEBUG" ] ; then
if [ "${LLVM_CFLAGS}" != "" ] ; then
LLVM_CFLAGS="${LLVM_CFLAGS} "
fi
LLVM_CFLAGS="${LLVM_CFLAGS}${flag}"
fi
fi
done
llvm_version=$("${LLVM_CONFIG}" --version | sed 's/\.//; s/svn.*//')
LLVM_CFLAGS="${LLVM_CFLAGS} -DSHARK_LLVM_VERSION=${llvm_version}"
unset LLVM_LDFLAGS
for flag in $("${LLVM_CONFIG}" --ldflags $llvm_components); do
if echo "${flag}" | grep -q '^-L'; then
if [ "${LLVM_LDFLAGS}" != "" ] ; then
LLVM_LDFLAGS="${LLVM_LDFLAGS} "
fi
LLVM_LDFLAGS="${LLVM_LDFLAGS}${flag}"
fi
done
unset LLVM_LIBS
for flag in $("${LLVM_CONFIG}" --libs $llvm_components); do
if echo "${flag}" | grep -q '^-l'; then
if [ "${LLVM_LIBS}" != "" ] ; then
LLVM_LIBS="${LLVM_LIBS} "
fi
LLVM_LIBS="${LLVM_LIBS}${flag}"
fi
done
export LLVM_CFLAGS
export LLVM_LDFLAGS
export LLVM_LIBS
fi
fi fi
/* /*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,7 +27,6 @@ package com.sun.java.util.jar.pack; ...@@ -27,7 +27,6 @@ package com.sun.java.util.jar.pack;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import com.sun.java.util.jar.pack.Package.Class;
import com.sun.java.util.jar.pack.ConstantPool.*; import com.sun.java.util.jar.pack.ConstantPool.*;
/** /**
...@@ -96,20 +95,20 @@ class Attribute implements Comparable, Constants { ...@@ -96,20 +95,20 @@ class Attribute implements Comparable, Constants {
return this.def.compareTo(that.def); return this.def.compareTo(that.def);
} }
static private final byte[] noBytes = {}; private static final byte[] noBytes = {};
static private final HashMap canonLists = new HashMap(); private static final Map<List<Attribute>, List<Attribute>> canonLists = new HashMap<>();
static private final HashMap attributes = new HashMap(); private static final Map<Layout, Attribute> attributes = new HashMap<>();
static private final HashMap standardDefs = new HashMap(); private static final Map<Layout, Attribute> standardDefs = new HashMap<>();
// Canonicalized lists of trivial attrs (Deprecated, etc.) // Canonicalized lists of trivial attrs (Deprecated, etc.)
// are used by trimToSize, in order to reduce footprint // are used by trimToSize, in order to reduce footprint
// of some common cases. (Note that Code attributes are // of some common cases. (Note that Code attributes are
// always zero size.) // always zero size.)
public static List getCanonList(List al) { public static List getCanonList(List<Attribute> al) {
synchronized (canonLists) { synchronized (canonLists) {
List cl = (List) canonLists.get(al); List<Attribute> cl = canonLists.get(al);
if (cl == null) { if (cl == null) {
cl = new ArrayList(al.size()); cl = new ArrayList<>(al.size());
cl.addAll(al); cl.addAll(al);
cl = Collections.unmodifiableList(cl); cl = Collections.unmodifiableList(cl);
canonLists.put(al, cl); canonLists.put(al, cl);
...@@ -122,7 +121,7 @@ class Attribute implements Comparable, Constants { ...@@ -122,7 +121,7 @@ class Attribute implements Comparable, Constants {
public static Attribute find(int ctype, String name, String layout) { public static Attribute find(int ctype, String name, String layout) {
Layout key = Layout.makeKey(ctype, name, layout); Layout key = Layout.makeKey(ctype, name, layout);
synchronized (attributes) { synchronized (attributes) {
Attribute a = (Attribute) attributes.get(key); Attribute a = attributes.get(key);
if (a == null) { if (a == null) {
a = new Layout(ctype, name, layout).canonicalInstance(); a = new Layout(ctype, name, layout).canonicalInstance();
attributes.put(key, a); attributes.put(key, a);
...@@ -131,24 +130,29 @@ class Attribute implements Comparable, Constants { ...@@ -131,24 +130,29 @@ class Attribute implements Comparable, Constants {
} }
} }
public static Object keyForLookup(int ctype, String name) { public static Layout keyForLookup(int ctype, String name) {
return Layout.makeKey(ctype, name); return Layout.makeKey(ctype, name);
} }
// Find canonical empty attribute with given ctype and name, // Find canonical empty attribute with given ctype and name,
// and with the standard layout. // and with the standard layout.
public static Attribute lookup(Map defs, int ctype, String name) { public static Attribute lookup(Map<Layout, Attribute> defs, int ctype,
if (defs == null) defs = standardDefs; String name) {
return (Attribute) defs.get(Layout.makeKey(ctype, 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) {
public static Attribute define(Map<Layout, Attribute> defs, int ctype,
String name, String layout) {
Attribute a = find(ctype, name, layout); Attribute a = find(ctype, name, layout);
defs.put(Layout.makeKey(ctype, name), a); defs.put(Layout.makeKey(ctype, name), a);
return a; return a;
} }
static { static {
Map sd = standardDefs; Map<Layout, Attribute> sd = standardDefs;
define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH"); define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH");
define(sd, ATTR_CONTEXT_CLASS, "Synthetic", ""); define(sd, ATTR_CONTEXT_CLASS, "Synthetic", "");
define(sd, ATTR_CONTEXT_CLASS, "Deprecated", ""); define(sd, ATTR_CONTEXT_CLASS, "Deprecated", "");
...@@ -244,7 +248,7 @@ class Attribute implements Comparable, Constants { ...@@ -244,7 +248,7 @@ class Attribute implements Comparable, Constants {
+"\n ()[] ]" +"\n ()[] ]"
) )
}; };
Map sd = standardDefs; Map<Layout, Attribute> sd = standardDefs;
String defaultLayout = mdLayouts[2]; String defaultLayout = mdLayouts[2];
String annotationsLayout = mdLayouts[1] + mdLayouts[2]; String annotationsLayout = mdLayouts[1] + mdLayouts[2];
String paramsLayout = mdLayouts[0] + annotationsLayout; String paramsLayout = mdLayouts[0] + annotationsLayout;
...@@ -275,10 +279,6 @@ class Attribute implements Comparable, Constants { ...@@ -275,10 +279,6 @@ class Attribute implements Comparable, Constants {
return null; return null;
} }
public static Map getStandardDefs() {
return new HashMap(standardDefs);
}
/** Base class for any attributed object (Class, Field, Method, Code). /** Base class for any attributed object (Class, Field, Method, Code).
* Flags are included because they are used to help transmit the * Flags are included because they are used to help transmit the
* presence of attributes. That is, flags are a mix of modifier * presence of attributes. That is, flags are a mix of modifier
...@@ -291,7 +291,7 @@ class Attribute implements Comparable, Constants { ...@@ -291,7 +291,7 @@ class Attribute implements Comparable, Constants {
protected abstract Entry[] getCPMap(); protected abstract Entry[] getCPMap();
protected int flags; // defined here for convenience protected int flags; // defined here for convenience
protected List attributes; protected List<Attribute> attributes;
public int attributeSize() { public int attributeSize() {
return (attributes == null) ? 0 : attributes.size(); return (attributes == null) ? 0 : attributes.size();
...@@ -301,16 +301,15 @@ class Attribute implements Comparable, Constants { ...@@ -301,16 +301,15 @@ class Attribute implements Comparable, Constants {
if (attributes == null) { if (attributes == null) {
return; return;
} }
if (attributes.size() == 0) { if (attributes.isEmpty()) {
attributes = null; attributes = null;
return; return;
} }
if (attributes instanceof ArrayList) { if (attributes instanceof ArrayList) {
ArrayList al = (ArrayList) attributes; ArrayList<Attribute> al = (ArrayList<Attribute>)attributes;
al.trimToSize(); al.trimToSize();
boolean allCanon = true; boolean allCanon = true;
for (Iterator i = al.iterator(); i.hasNext(); ) { for (Attribute a : al) {
Attribute a = (Attribute) i.next();
if (!a.isCanonical()) { if (!a.isCanonical()) {
allCanon = false; allCanon = false;
} }
...@@ -330,9 +329,9 @@ class Attribute implements Comparable, Constants { ...@@ -330,9 +329,9 @@ class Attribute implements Comparable, Constants {
public void addAttribute(Attribute a) { public void addAttribute(Attribute a) {
if (attributes == null) if (attributes == null)
attributes = new ArrayList(3); attributes = new ArrayList<>(3);
else if (!(attributes instanceof ArrayList)) else if (!(attributes instanceof ArrayList))
attributes = new ArrayList(attributes); // unfreeze it attributes = new ArrayList<>(attributes); // unfreeze it
attributes.add(a); attributes.add(a);
} }
...@@ -340,32 +339,31 @@ class Attribute implements Comparable, Constants { ...@@ -340,32 +339,31 @@ class Attribute implements Comparable, Constants {
if (attributes == null) return null; if (attributes == null) return null;
if (!attributes.contains(a)) return null; if (!attributes.contains(a)) return null;
if (!(attributes instanceof ArrayList)) if (!(attributes instanceof ArrayList))
attributes = new ArrayList(attributes); // unfreeze it attributes = new ArrayList<>(attributes); // unfreeze it
attributes.remove(a); attributes.remove(a);
return a; return a;
} }
public Attribute getAttribute(int n) { public Attribute getAttribute(int n) {
return (Attribute) attributes.get(n); return attributes.get(n);
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
if (attributes == null) return; if (attributes == null) return;
for (Iterator i = attributes.iterator(); i.hasNext(); ) { for (Attribute a : attributes) {
Attribute a = (Attribute) i.next();
a.visitRefs(this, mode, refs); a.visitRefs(this, mode, refs);
} }
} }
static final List noAttributes = Arrays.asList(new Object[0]); static final List<Attribute> noAttributes = Arrays.asList(new Attribute[0]);
public List getAttributes() { public List<Attribute> getAttributes() {
if (attributes == null) if (attributes == null)
return noAttributes; return noAttributes;
return attributes; return attributes;
} }
public void setAttributes(List attrList) { public void setAttributes(List<Attribute> attrList) {
if (attrList.isEmpty()) if (attrList.isEmpty())
attributes = null; attributes = null;
else else
...@@ -374,8 +372,7 @@ class Attribute implements Comparable, Constants { ...@@ -374,8 +372,7 @@ class Attribute implements Comparable, Constants {
public Attribute getAttribute(String attrName) { public Attribute getAttribute(String attrName) {
if (attributes == null) return null; if (attributes == null) return null;
for (Iterator i = attributes.iterator(); i.hasNext(); ) { for (Attribute a : attributes) {
Attribute a = (Attribute) i.next();
if (a.name().equals(attrName)) if (a.name().equals(attrName))
return a; return a;
} }
...@@ -384,8 +381,7 @@ class Attribute implements Comparable, Constants { ...@@ -384,8 +381,7 @@ class Attribute implements Comparable, Constants {
public Attribute getAttribute(Layout attrDef) { public Attribute getAttribute(Layout attrDef) {
if (attributes == null) return null; if (attributes == null) return null;
for (Iterator i = attributes.iterator(); i.hasNext(); ) { for (Attribute a : attributes) {
Attribute a = (Attribute) i.next();
if (a.layout() == attrDef) if (a.layout() == attrDef)
return a; return a;
} }
...@@ -457,14 +453,8 @@ class Attribute implements Comparable, Constants { ...@@ -457,14 +453,8 @@ class Attribute implements Comparable, Constants {
public String layout() { return layout; } public String layout() { return layout; }
public Attribute canonicalInstance() { return canon; } public Attribute canonicalInstance() { return canon; }
// Cache of name reference.
private Entry nameRef; // name, for use by visitRefs
public Entry getNameRef() { public Entry getNameRef() {
Entry nameRef = this.nameRef; return ConstantPool.getUtf8Entry(name());
if (nameRef == null) {
this.nameRef = nameRef = ConstantPool.getUtf8Entry(name());
}
return nameRef;
} }
public boolean isEmpty() { return layout == ""; } public boolean isEmpty() { return layout == ""; }
...@@ -834,14 +824,14 @@ class Attribute implements Comparable, Constants { ...@@ -834,14 +824,14 @@ class Attribute implements Comparable, Constants {
*/ */
static //private static //private
Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) { Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) {
ArrayList col = new ArrayList(layout.length()); ArrayList<Layout.Element> col = new ArrayList<>(layout.length());
tokenizeLayout(self, curCble, layout, col); tokenizeLayout(self, curCble, layout, col);
Layout.Element[] res = new Layout.Element[col.size()]; Layout.Element[] res = new Layout.Element[col.size()];
col.toArray(res); col.toArray(res);
return res; return res;
} }
static //private static //private
void tokenizeLayout(Layout self, int curCble, String layout, ArrayList col) { void tokenizeLayout(Layout self, int curCble, String layout, ArrayList<Layout.Element> col) {
boolean prevBCI = false; boolean prevBCI = false;
for (int len = layout.length(), i = 0; i < len; ) { for (int len = layout.length(), i = 0; i < len; ) {
int start = i; int start = i;
...@@ -899,7 +889,7 @@ class Attribute implements Comparable, Constants { ...@@ -899,7 +889,7 @@ class Attribute implements Comparable, Constants {
case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']' case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
kind = EK_UN; kind = EK_UN;
i = tokenizeSInt(e, layout, i); i = tokenizeSInt(e, layout, i);
ArrayList cases = new ArrayList(); ArrayList<Layout.Element> cases = new ArrayList<>();
for (;;) { for (;;) {
// Keep parsing cases until we hit the default case. // Keep parsing cases until we hit the default case.
if (layout.charAt(i++) != '(') if (layout.charAt(i++) != '(')
...@@ -1053,7 +1043,7 @@ class Attribute implements Comparable, Constants { ...@@ -1053,7 +1043,7 @@ class Attribute implements Comparable, Constants {
} }
static //private static //private
String[] splitBodies(String layout) { String[] splitBodies(String layout) {
ArrayList bodies = new ArrayList(); ArrayList<String> bodies = new ArrayList<>();
// Parse several independent layout bodies: "[foo][bar]...[baz]" // Parse several independent layout bodies: "[foo][bar]...[baz]"
for (int i = 0; i < layout.length(); i++) { for (int i = 0; i < layout.length(); i++) {
if (layout.charAt(i++) != '[') if (layout.charAt(i++) != '[')
...@@ -1132,7 +1122,9 @@ class Attribute implements Comparable, Constants { ...@@ -1132,7 +1122,9 @@ class Attribute implements Comparable, Constants {
int parseIntBefore(String layout, int dash) { int parseIntBefore(String layout, int dash) {
int end = dash; int end = dash;
int beg = end; int beg = end;
while (beg > 0 && isDigit(layout.charAt(beg-1))) --beg; while (beg > 0 && isDigit(layout.charAt(beg-1))) {
--beg;
}
if (beg == end) return Integer.parseInt("empty"); if (beg == end) return Integer.parseInt("empty");
// skip backward over a sign // skip backward over a sign
if (beg >= 1 && layout.charAt(beg-1) == '-') --beg; if (beg >= 1 && layout.charAt(beg-1) == '-') --beg;
...@@ -1145,7 +1137,9 @@ class Attribute implements Comparable, Constants { ...@@ -1145,7 +1137,9 @@ class Attribute implements Comparable, Constants {
int end = beg; int end = beg;
int limit = layout.length(); int limit = layout.length();
if (end < limit && layout.charAt(end) == '-') ++end; if (end < limit && layout.charAt(end) == '-') ++end;
while (end < limit && isDigit(layout.charAt(end))) ++end; while (end < limit && isDigit(layout.charAt(end))) {
++end;
}
if (beg == end) return Integer.parseInt("empty"); if (beg == end) return Integer.parseInt("empty");
return Integer.parseInt(layout.substring(beg, end)); return Integer.parseInt(layout.substring(beg, end));
} }
......
/* /*
* Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
package com.sun.java.util.jar.pack; package com.sun.java.util.jar.pack;
import java.io.*;
import java.util.*; import java.util.*;
/** /**
...@@ -40,20 +39,13 @@ class ConstantPool implements Constants { ...@@ -40,20 +39,13 @@ class ConstantPool implements Constants {
return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
} }
// Uniquification tables for factory methods:
private static final HashMap utf8Entries = new HashMap();
private static final HashMap classEntries = new HashMap();
private static final HashMap literalEntries = new HashMap();
private static final HashMap signatureEntries = new HashMap();
private static final HashMap descriptorEntries = new HashMap();
private static final HashMap memberEntries = new HashMap();
/** Factory for Utf8 string constants. /** Factory for Utf8 string constants.
* Used for well-known strings like "SourceFile", "<init>", etc. * Used for well-known strings like "SourceFile", "<init>", etc.
* Also used to back up more complex constant pool entries, like Class. * Also used to back up more complex constant pool entries, like Class.
*/ */
public static synchronized Utf8Entry getUtf8Entry(String value) { public static synchronized Utf8Entry getUtf8Entry(String value) {
Utf8Entry e = (Utf8Entry) utf8Entries.get(value); Map<String, Utf8Entry> utf8Entries = Utils.getUtf8Entries();
Utf8Entry e = utf8Entries.get(value);
if (e == null) { if (e == null) {
e = new Utf8Entry(value); e = new Utf8Entry(value);
utf8Entries.put(e.stringValue(), e); utf8Entries.put(e.stringValue(), e);
...@@ -62,9 +54,10 @@ class ConstantPool implements Constants { ...@@ -62,9 +54,10 @@ class ConstantPool implements Constants {
} }
/** Factory for Class constants. */ /** Factory for Class constants. */
public static synchronized ClassEntry getClassEntry(String name) { public static synchronized ClassEntry getClassEntry(String name) {
ClassEntry e = (ClassEntry) classEntries.get(name); Map<String, ClassEntry> classEntries = Utils.getClassEntries();
ClassEntry e = classEntries.get(name);
if (e == null) { if (e == null) {
e = (ClassEntry) new ClassEntry(getUtf8Entry(name)); e = new ClassEntry(getUtf8Entry(name));
assert(name.equals(e.stringValue())); assert(name.equals(e.stringValue()));
classEntries.put(e.stringValue(), e); classEntries.put(e.stringValue(), e);
} }
...@@ -72,7 +65,8 @@ class ConstantPool implements Constants { ...@@ -72,7 +65,8 @@ class ConstantPool implements Constants {
} }
/** Factory for literal constants (String, Integer, etc.). */ /** Factory for literal constants (String, Integer, etc.). */
public static synchronized LiteralEntry getLiteralEntry(Comparable value) { public static synchronized LiteralEntry getLiteralEntry(Comparable value) {
LiteralEntry e = (LiteralEntry) literalEntries.get(value); Map<Object, LiteralEntry> literalEntries = Utils.getLiteralEntries();
LiteralEntry e = literalEntries.get(value);
if (e == null) { if (e == null) {
if (value instanceof String) if (value instanceof String)
e = new StringEntry(getUtf8Entry((String)value)); e = new StringEntry(getUtf8Entry((String)value));
...@@ -89,7 +83,8 @@ class ConstantPool implements Constants { ...@@ -89,7 +83,8 @@ class ConstantPool implements Constants {
/** Factory for signature (type) constants. */ /** Factory for signature (type) constants. */
public static synchronized SignatureEntry getSignatureEntry(String type) { public static synchronized SignatureEntry getSignatureEntry(String type) {
SignatureEntry e = (SignatureEntry) signatureEntries.get(type); Map<String, SignatureEntry> signatureEntries = Utils.getSignatureEntries();
SignatureEntry e = signatureEntries.get(type);
if (e == null) { if (e == null) {
e = new SignatureEntry(type); e = new SignatureEntry(type);
assert(e.stringValue().equals(type)); assert(e.stringValue().equals(type));
...@@ -104,8 +99,9 @@ class ConstantPool implements Constants { ...@@ -104,8 +99,9 @@ class ConstantPool implements Constants {
/** Factory for descriptor (name-and-type) constants. */ /** Factory for descriptor (name-and-type) constants. */
public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) { public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
Map<String, DescriptorEntry> descriptorEntries = Utils.getDescriptorEntries();
String key = DescriptorEntry.stringValueOf(nameRef, typeRef); String key = DescriptorEntry.stringValueOf(nameRef, typeRef);
DescriptorEntry e = (DescriptorEntry) descriptorEntries.get(key); DescriptorEntry e = descriptorEntries.get(key);
if (e == null) { if (e == null) {
e = new DescriptorEntry(nameRef, typeRef); e = new DescriptorEntry(nameRef, typeRef);
assert(e.stringValue().equals(key)) assert(e.stringValue().equals(key))
...@@ -121,8 +117,9 @@ class ConstantPool implements Constants { ...@@ -121,8 +117,9 @@ class ConstantPool implements Constants {
/** Factory for member reference constants. */ /** Factory for member reference constants. */
public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) { public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
Map<String, MemberEntry> memberEntries = Utils.getMemberEntries();
String key = MemberEntry.stringValueOf(tag, classRef, descRef); String key = MemberEntry.stringValueOf(tag, classRef, descRef);
MemberEntry e = (MemberEntry) memberEntries.get(key); MemberEntry e = memberEntries.get(key);
if (e == null) { if (e == null) {
e = new MemberEntry(tag, classRef, descRef); e = new MemberEntry(tag, classRef, descRef);
assert(e.stringValue().equals(key)) assert(e.stringValue().equals(key))
...@@ -489,8 +486,9 @@ class ConstantPool implements Constants { ...@@ -489,8 +486,9 @@ class ConstantPool implements Constants {
String[] parts = structureSignature(value); String[] parts = structureSignature(value);
formRef = getUtf8Entry(parts[0]); formRef = getUtf8Entry(parts[0]);
classRefs = new ClassEntry[parts.length-1]; classRefs = new ClassEntry[parts.length-1];
for (int i = 1; i < parts.length; i++) for (int i = 1; i < parts.length; i++) {
classRefs[i-1] = getClassEntry(parts[i]); classRefs[i - 1] = getClassEntry(parts[i]);
}
hashCode(); // force computation of valueHash hashCode(); // force computation of valueHash
} }
protected int computeValueHash() { protected int computeValueHash() {
...@@ -527,8 +525,9 @@ class ConstantPool implements Constants { ...@@ -527,8 +525,9 @@ class ConstantPool implements Constants {
String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) { String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) {
String[] parts = new String[1+classRefs.length]; String[] parts = new String[1+classRefs.length];
parts[0] = formRef.stringValue(); parts[0] = formRef.stringValue();
for (int i = 1; i < parts.length; i++) for (int i = 1; i < parts.length; i++) {
parts[i] = classRefs[i-1].stringValue(); parts[i] = classRefs[i - 1].stringValue();
}
return flattenSignature(parts).intern(); return flattenSignature(parts).intern();
} }
...@@ -543,19 +542,23 @@ class ConstantPool implements Constants { ...@@ -543,19 +542,23 @@ class ConstantPool implements Constants {
int size = 0; int size = 0;
for (int i = min; i < max; i++) { for (int i = min; i < max; i++) {
switch (form.charAt(i)) { switch (form.charAt(i)) {
case 'D': case 'D':
case 'J': case 'J':
if (countDoublesTwice) size++; if (countDoublesTwice) {
break; size++;
case '[': }
// Skip rest of array info. break;
while (form.charAt(i) == '[') ++i; case '[':
break; // Skip rest of array info.
case ';': while (form.charAt(i) == '[') {
continue; ++i;
default: }
assert(0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i))); break;
break; case ';':
continue;
default:
assert (0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i)));
break;
} }
size++; size++;
} }
...@@ -586,8 +589,9 @@ class ConstantPool implements Constants { ...@@ -586,8 +589,9 @@ class ConstantPool implements Constants {
s = "/" + formRef.stringValue(); s = "/" + formRef.stringValue();
} }
int i; int i;
while ((i = s.indexOf(';')) >= 0) while ((i = s.indexOf(';')) >= 0) {
s = s.substring(0,i) + s.substring(i+1); s = s.substring(0, i) + s.substring(i + 1);
}
return s; return s;
} }
} }
...@@ -732,11 +736,11 @@ class ConstantPool implements Constants { ...@@ -732,11 +736,11 @@ class ConstantPool implements Constants {
clearIndex(); clearIndex();
this.cpMap = cpMap; this.cpMap = cpMap;
} }
protected Index(String debugName, Collection cpMapList) { protected Index(String debugName, Collection<Entry> cpMapList) {
this(debugName); this(debugName);
setMap(cpMapList); setMap(cpMapList);
} }
protected void setMap(Collection cpMapList) { protected void setMap(Collection<Entry> cpMapList) {
cpMap = new Entry[cpMapList.size()]; cpMap = new Entry[cpMapList.size()];
cpMapList.toArray(cpMap); cpMapList.toArray(cpMap);
setMap(cpMap); setMap(cpMap);
...@@ -756,11 +760,13 @@ class ConstantPool implements Constants { ...@@ -756,11 +760,13 @@ class ConstantPool implements Constants {
// //
// As a special hack, if flattenSigs, signatures are // As a special hack, if flattenSigs, signatures are
// treated as equivalent entries of cpMap. This is wrong // treated as equivalent entries of cpMap. This is wrong
// fron a Collection point of view, because contains() // from a Collection point of view, because contains()
// reports true for signatures, but the iterator() // reports true for signatures, but the iterator()
// never produces them! // never produces them!
private int findIndexOf(Entry e) { private int findIndexOf(Entry e) {
if (indexKey == null) initializeIndex(); if (indexKey == null) {
initializeIndex();
}
int probe = findIndexLocation(e); int probe = findIndexLocation(e);
if (indexKey[probe] != e) { if (indexKey[probe] != e) {
if (flattenSigs && e.tag == CONSTANT_Signature) { if (flattenSigs && e.tag == CONSTANT_Signature) {
...@@ -832,7 +838,9 @@ class ConstantPool implements Constants { ...@@ -832,7 +838,9 @@ class ConstantPool implements Constants {
System.out.println("initialize Index "+debugName+" ["+size()+"]"); System.out.println("initialize Index "+debugName+" ["+size()+"]");
int hsize0 = (int)((cpMap.length + 10) * 1.5); int hsize0 = (int)((cpMap.length + 10) * 1.5);
int hsize = 1; int hsize = 1;
while (hsize < hsize0) hsize <<= 1; while (hsize < hsize0) {
hsize <<= 1;
}
indexKey = new Entry[hsize]; indexKey = new Entry[hsize];
indexValue = new int[hsize]; indexValue = new int[hsize];
for (int i = 0; i < cpMap.length; i++) { for (int i = 0; i < cpMap.length; i++) {
...@@ -855,7 +863,7 @@ class ConstantPool implements Constants { ...@@ -855,7 +863,7 @@ class ConstantPool implements Constants {
return toArray(new Entry[size()]); return toArray(new Entry[size()]);
} }
public Object clone() { public Object clone() {
return new Index(debugName, (Entry[]) cpMap.clone()); return new Index(debugName, cpMap.clone());
} }
public String toString() { public String toString() {
return "Index "+debugName+" ["+size()+"]"; return "Index "+debugName+" ["+size()+"]";
...@@ -901,22 +909,24 @@ class ConstantPool implements Constants { ...@@ -901,22 +909,24 @@ class ConstantPool implements Constants {
public static public static
Index[] partition(Index ix, int[] keys) { Index[] partition(Index ix, int[] keys) {
// %%% Should move this into class Index. // %%% Should move this into class Index.
ArrayList parts = new ArrayList(); ArrayList<List<Entry>> parts = new ArrayList<>();
Entry[] cpMap = ix.cpMap; Entry[] cpMap = ix.cpMap;
assert(keys.length == cpMap.length); assert(keys.length == cpMap.length);
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
int key = keys[i]; int key = keys[i];
if (key < 0) continue; if (key < 0) continue;
while (key >= parts.size()) parts.add(null); while (key >= parts.size()) {
ArrayList part = (ArrayList) parts.get(key); parts.add(null);
}
List<Entry> part = parts.get(key);
if (part == null) { if (part == null) {
parts.set(key, part = new ArrayList()); parts.set(key, part = new ArrayList<>());
} }
part.add(cpMap[i]); part.add(cpMap[i]);
} }
Index[] indexes = new Index[parts.size()]; Index[] indexes = new Index[parts.size()];
for (int key = 0; key < indexes.length; key++) { for (int key = 0; key < indexes.length; key++) {
ArrayList part = (ArrayList) parts.get(key); List<Entry> part = parts.get(key);
if (part == null) continue; if (part == null) continue;
indexes[key] = new Index(ix.debugName+"/part#"+key, part); indexes[key] = new Index(ix.debugName+"/part#"+key, part);
assert(indexes[key].indexOf(part.get(0)) == 0); assert(indexes[key].indexOf(part.get(0)) == 0);
...@@ -1048,9 +1058,10 @@ class ConstantPool implements Constants { ...@@ -1048,9 +1058,10 @@ class ConstantPool implements Constants {
whichClasses[i] = whichClass; whichClasses[i] = whichClass;
} }
perClassIndexes = partition(allMembers, whichClasses); perClassIndexes = partition(allMembers, whichClasses);
for (int i = 0; i < perClassIndexes.length; i++) for (int i = 0; i < perClassIndexes.length; i++) {
assert(perClassIndexes[i]==null assert (perClassIndexes[i] == null ||
|| perClassIndexes[i].assertIsSorted()); perClassIndexes[i].assertIsSorted());
}
indexByTagAndClass[tag] = perClassIndexes; indexByTagAndClass[tag] = perClassIndexes;
} }
int whichClass = allClasses.indexOf(classRef); int whichClass = allClasses.indexOf(classRef);
...@@ -1113,7 +1124,7 @@ class ConstantPool implements Constants { ...@@ -1113,7 +1124,7 @@ class ConstantPool implements Constants {
* Also, discard null from cpRefs. * Also, discard null from cpRefs.
*/ */
public static public static
void completeReferencesIn(Set cpRefs, boolean flattenSigs) { void completeReferencesIn(Set<Entry> cpRefs, boolean flattenSigs) {
cpRefs.remove(null); cpRefs.remove(null);
for (ListIterator work = for (ListIterator work =
new ArrayList(cpRefs).listIterator(cpRefs.size()); new ArrayList(cpRefs).listIterator(cpRefs.size());
......
/* /*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
package com.sun.java.util.jar.pack; package com.sun.java.util.jar.pack;
import java.lang.Error;
import java.io.*; import java.io.*;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.*; import java.util.*;
...@@ -35,10 +34,11 @@ import java.util.zip.*; ...@@ -35,10 +34,11 @@ import java.util.zip.*;
/** Command line interface for Pack200. /** Command line interface for Pack200.
*/ */
class Driver { class Driver {
private static final ResourceBundle RESOURCE= ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource"); private static final ResourceBundle RESOURCE =
ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource");
public static void main(String[] ava) throws IOException { public static void main(String[] ava) throws IOException {
ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava)); ArrayList<String> av = new ArrayList<>(Arrays.asList(ava));
boolean doPack = true; boolean doPack = true;
boolean doUnpack = false; boolean doUnpack = false;
...@@ -61,7 +61,7 @@ class Driver { ...@@ -61,7 +61,7 @@ class Driver {
} }
// Collect engine properties here: // Collect engine properties here:
HashMap<String,String> engProps = new HashMap<String,String>(); HashMap<String,String> engProps = new HashMap<>();
engProps.put(verboseProp, System.getProperty(verboseProp)); engProps.put(verboseProp, System.getProperty(verboseProp));
String optionMap; String optionMap;
...@@ -75,7 +75,7 @@ class Driver { ...@@ -75,7 +75,7 @@ class Driver {
} }
// Collect argument properties here: // Collect argument properties here:
HashMap<String,String> avProps = new HashMap<String,String>(); HashMap<String,String> avProps = new HashMap<>();
try { try {
for (;;) { for (;;) {
String state = parseCommandOptions(av, optionMap, avProps); String state = parseCommandOptions(av, optionMap, avProps);
...@@ -133,8 +133,9 @@ class Driver { ...@@ -133,8 +133,9 @@ class Driver {
if (engProps.get(verboseProp) != null) if (engProps.get(verboseProp) != null)
fileProps.list(System.out); fileProps.list(System.out);
propIn.close(); propIn.close();
for (Map.Entry<Object,Object> me : fileProps.entrySet()) for (Map.Entry<Object,Object> me : fileProps.entrySet()) {
engProps.put((String)me.getKey(), (String)me.getValue()); engProps.put((String) me.getKey(), (String) me.getValue());
}
} else if (state == "--version") { } else if (state == "--version") {
System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION), Driver.class.getName(), "1.31, 07/05/05")); System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION), Driver.class.getName(), "1.31, 07/05/05"));
return; return;
...@@ -493,7 +494,7 @@ class Driver { ...@@ -493,7 +494,7 @@ class Driver {
String resultString = null; String resultString = null;
// Convert options string into optLines dictionary. // Convert options string into optLines dictionary.
TreeMap<String,String[]> optmap = new TreeMap<String,String[]>(); TreeMap<String,String[]> optmap = new TreeMap<>();
loadOptmap: loadOptmap:
for (String optline : options.split("\n")) { for (String optline : options.split("\n")) {
String[] words = optline.split("\\p{Space}+"); String[] words = optline.split("\\p{Space}+");
...@@ -687,7 +688,9 @@ class Driver { ...@@ -687,7 +688,9 @@ class Driver {
// Report number of arguments consumed. // Report number of arguments consumed.
args.subList(0, argp.nextIndex()).clear(); args.subList(0, argp.nextIndex()).clear();
// Report any unconsumed partial argument. // Report any unconsumed partial argument.
while (pbp.hasPrevious()) args.add(0, pbp.previous()); while (pbp.hasPrevious()) {
args.add(0, pbp.previous());
}
//System.out.println(args+" // "+properties+" -> "+resultString); //System.out.println(args+" // "+properties+" -> "+resultString);
return resultString; return resultString;
} }
......
/* /*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -28,13 +28,8 @@ package com.sun.java.util.jar.pack; ...@@ -28,13 +28,8 @@ package com.sun.java.util.jar.pack;
import java.nio.*; import java.nio.*;
import java.io.*; import java.io.*;
import java.nio.channels.*;
import java.util.Date;
import java.util.jar.*; import java.util.jar.*;
import java.util.zip.*; import java.util.zip.*;
import java.util.*;
//import com.sun.java.util.jar.pack.Pack200;
class NativeUnpack { class NativeUnpack {
// Pointer to the native unpacker obj // Pointer to the native unpacker obj
...@@ -91,13 +86,13 @@ class NativeUnpack { ...@@ -91,13 +86,13 @@ class NativeUnpack {
NativeUnpack(UnpackerImpl p200) { NativeUnpack(UnpackerImpl p200) {
super(); super();
_p200 = p200; _p200 = p200;
_props = p200._props; _props = p200.props;
p200._nunp = this; p200._nunp = this;
} }
// for JNI callbacks // for JNI callbacks
static private Object currentInstance() { static private Object currentInstance() {
UnpackerImpl p200 = (UnpackerImpl) Utils.currentInstance.get(); UnpackerImpl p200 = (UnpackerImpl) Utils.getTLGlobals();
return (p200 == null)? null: p200._nunp; return (p200 == null)? null: p200._nunp;
} }
...@@ -216,10 +211,10 @@ class NativeUnpack { ...@@ -216,10 +211,10 @@ class NativeUnpack {
++_fileCount; ++_fileCount;
updateProgress(); updateProgress();
} }
presetInput = getUnusedInput();
long consumed = finish(); long consumed = finish();
if (_verbose > 0) if (_verbose > 0)
Utils.log.info("bytes consumed = "+consumed); Utils.log.info("bytes consumed = "+consumed);
presetInput = getUnusedInput();
if (presetInput == null && if (presetInput == null &&
!Utils.isPackMagic(Utils.readMagic(in))) { !Utils.isPackMagic(Utils.readMagic(in))) {
break; break;
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
package com.sun.java.util.jar.pack; package com.sun.java.util.jar.pack;
import com.sun.java.util.jar.pack.Attribute.Layout;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.zip.*;
import java.util.jar.*; import java.util.jar.*;
import java.io.*; import java.io.*;
import com.sun.java.util.jar.pack.ConstantPool.*; import com.sun.java.util.jar.pack.ConstantPool.*;
...@@ -77,10 +77,11 @@ class Package implements Constants { ...@@ -77,10 +77,11 @@ class Package implements Constants {
cp = new ConstantPool.IndexGroup(); cp = new ConstantPool.IndexGroup();
classes.clear(); classes.clear();
files.clear(); files.clear();
BandStructure.nextSeqForDebug = 0;
} }
int getPackageVersion() { int getPackageVersion() {
return (package_majver << 16) + (int)package_minver; return (package_majver << 16) + package_minver;
} }
// Special empty versions of Code and InnerClasses, used for markers. // Special empty versions of Code and InnerClasses, used for markers.
...@@ -89,7 +90,7 @@ class Package implements Constants { ...@@ -89,7 +90,7 @@ class Package implements Constants {
public static final Attribute.Layout attrSourceFileSpecial; public static final Attribute.Layout attrSourceFileSpecial;
public static final Map attrDefs; public static final Map attrDefs;
static { static {
HashMap ad = new HashMap(2); HashMap<Layout, Attribute> ad = new HashMap<>(3);
attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD, attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD,
"Code", "").layout(); "Code", "").layout();
attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS, attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS,
...@@ -159,9 +160,9 @@ class Package implements Constants { ...@@ -159,9 +160,9 @@ class Package implements Constants {
} }
} }
ArrayList classes = new ArrayList(); ArrayList<Package.Class> classes = new ArrayList<>();
public List getClasses() { public List<Package.Class> getClasses() {
return classes; return classes;
} }
...@@ -186,11 +187,11 @@ class Package implements Constants { ...@@ -186,11 +187,11 @@ class Package implements Constants {
ClassEntry[] interfaces; ClassEntry[] interfaces;
// Class parts // Class parts
ArrayList fields; ArrayList<Field> fields;
ArrayList methods; ArrayList<Method> methods;
//ArrayList attributes; // in Attribute.Holder.this.attributes //ArrayList attributes; // in Attribute.Holder.this.attributes
// Note that InnerClasses may be collected at the package level. // Note that InnerClasses may be collected at the package level.
ArrayList innerClasses; ArrayList<InnerClass> innerClasses;
Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) { Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) {
this.magic = JAVA_MAGIC; this.magic = JAVA_MAGIC;
...@@ -270,7 +271,7 @@ class Package implements Constants { ...@@ -270,7 +271,7 @@ class Package implements Constants {
if (a != olda) { if (a != olda) {
if (verbose > 2) if (verbose > 2)
Utils.log.fine("recoding obvious SourceFile="+obvious); Utils.log.fine("recoding obvious SourceFile="+obvious);
List newAttrs = new ArrayList(getAttributes()); List<Attribute> newAttrs = new ArrayList<>(getAttributes());
int where = newAttrs.indexOf(olda); int where = newAttrs.indexOf(olda);
newAttrs.set(where, a); newAttrs.set(where, a);
setAttributes(newAttrs); setAttributes(newAttrs);
...@@ -295,12 +296,12 @@ class Package implements Constants { ...@@ -295,12 +296,12 @@ class Package implements Constants {
boolean hasInnerClasses() { boolean hasInnerClasses() {
return innerClasses != null; return innerClasses != null;
} }
List getInnerClasses() { List<InnerClass> getInnerClasses() {
return innerClasses; return innerClasses;
} }
public void setInnerClasses(Collection ics) { public void setInnerClasses(Collection<InnerClass> ics) {
innerClasses = (ics == null) ? null : new ArrayList(ics); innerClasses = (ics == null) ? null : new ArrayList<InnerClass>(ics);
// Edit the attribute list, if necessary. // Edit the attribute list, if necessary.
Attribute a = getAttribute(attrInnerClassesEmpty); Attribute a = getAttribute(attrInnerClassesEmpty);
if (innerClasses != null && a == null) if (innerClasses != null && a == null)
...@@ -318,19 +319,18 @@ class Package implements Constants { ...@@ -318,19 +319,18 @@ class Package implements Constants {
* The order of the resulting list is consistent * The order of the resulting list is consistent
* with that of Package.this.allInnerClasses. * with that of Package.this.allInnerClasses.
*/ */
public List computeGloballyImpliedICs() { public List<InnerClass> computeGloballyImpliedICs() {
HashSet cpRefs = new HashSet(); HashSet<Entry> cpRefs = new HashSet<>();
{ // This block temporarily displaces this.innerClasses. { // This block temporarily displaces this.innerClasses.
ArrayList innerClassesSaved = innerClasses; ArrayList<InnerClass> innerClassesSaved = innerClasses;
innerClasses = null; // ignore for the moment innerClasses = null; // ignore for the moment
visitRefs(VRM_CLASSIC, cpRefs); visitRefs(VRM_CLASSIC, cpRefs);
innerClasses = innerClassesSaved; innerClasses = innerClassesSaved;
} }
ConstantPool.completeReferencesIn(cpRefs, true); ConstantPool.completeReferencesIn(cpRefs, true);
HashSet icRefs = new HashSet(); HashSet<Entry> icRefs = new HashSet<>();
for (Iterator i = cpRefs.iterator(); i.hasNext(); ) { for (Entry e : cpRefs) {
Entry e = (Entry) i.next();
// Restrict cpRefs to InnerClasses entries only. // Restrict cpRefs to InnerClasses entries only.
if (!(e instanceof ClassEntry)) continue; if (!(e instanceof ClassEntry)) continue;
// For every IC reference, add its outers also. // For every IC reference, add its outers also.
...@@ -345,9 +345,8 @@ class Package implements Constants { ...@@ -345,9 +345,8 @@ class Package implements Constants {
// This loop is structured this way so as to accumulate // This loop is structured this way so as to accumulate
// entries into impliedICs in an order which reflects // entries into impliedICs in an order which reflects
// the order of allInnerClasses. // the order of allInnerClasses.
ArrayList impliedICs = new ArrayList(); ArrayList<InnerClass> impliedICs = new ArrayList<>();
for (Iterator i = allInnerClasses.iterator(); i.hasNext(); ) { for (InnerClass ic : allInnerClasses) {
InnerClass ic = (InnerClass) i.next();
// This one is locally relevant if it describes // This one is locally relevant if it describes
// a member of the current class, or if the current // a member of the current class, or if the current
// class uses it somehow. In the particular case // class uses it somehow. In the particular case
...@@ -366,10 +365,11 @@ class Package implements Constants { ...@@ -366,10 +365,11 @@ class Package implements Constants {
// Helper for both minimizing and expanding. // Helper for both minimizing and expanding.
// Computes a symmetric difference. // Computes a symmetric difference.
private List computeICdiff() { private List<InnerClass> computeICdiff() {
List impliedICs = computeGloballyImpliedICs(); List<InnerClass> impliedICs = computeGloballyImpliedICs();
List actualICs = getInnerClasses(); List<InnerClass> actualICs = getInnerClasses();
if (actualICs == null) actualICs = Collections.EMPTY_LIST; if (actualICs == null)
actualICs = Collections.EMPTY_LIST;
// Symmetric difference is calculated from I, A like this: // Symmetric difference is calculated from I, A like this:
// diff = (I+A) - (I*A) // diff = (I+A) - (I*A)
...@@ -388,8 +388,8 @@ class Package implements Constants { ...@@ -388,8 +388,8 @@ class Package implements Constants {
// Diff is A since I is empty. // Diff is A since I is empty.
} }
// (I*A) is non-trivial // (I*A) is non-trivial
HashSet center = new HashSet(actualICs); HashSet<InnerClass> center = new HashSet<>(actualICs);
center.retainAll(new HashSet(impliedICs)); center.retainAll(new HashSet<>(impliedICs));
impliedICs.addAll(actualICs); impliedICs.addAll(actualICs);
impliedICs.removeAll(center); impliedICs.removeAll(center);
// Diff is now I^A = (I+A)-(I*A). // Diff is now I^A = (I+A)-(I*A).
...@@ -407,9 +407,9 @@ class Package implements Constants { ...@@ -407,9 +407,9 @@ class Package implements Constants {
* to use the globally implied ICs changed. * to use the globally implied ICs changed.
*/ */
void minimizeLocalICs() { void minimizeLocalICs() {
List diff = computeICdiff(); List<InnerClass> diff = computeICdiff();
List actualICs = innerClasses; List<InnerClass> actualICs = innerClasses;
List localICs; // will be the diff, modulo edge cases List<InnerClass> localICs; // will be the diff, modulo edge cases
if (diff.isEmpty()) { if (diff.isEmpty()) {
// No diff, so transmit no attribute. // No diff, so transmit no attribute.
localICs = null; localICs = null;
...@@ -439,12 +439,12 @@ class Package implements Constants { ...@@ -439,12 +439,12 @@ class Package implements Constants {
* Otherwise, return positive if any IC tuples were added. * Otherwise, return positive if any IC tuples were added.
*/ */
int expandLocalICs() { int expandLocalICs() {
List localICs = innerClasses; List<InnerClass> localICs = innerClasses;
List actualICs; List<InnerClass> actualICs;
int changed; int changed;
if (localICs == null) { if (localICs == null) {
// Diff was empty. (Common case.) // Diff was empty. (Common case.)
List impliedICs = computeGloballyImpliedICs(); List<InnerClass> impliedICs = computeGloballyImpliedICs();
if (impliedICs.isEmpty()) { if (impliedICs.isEmpty()) {
actualICs = null; actualICs = null;
changed = 0; changed = 0;
...@@ -490,7 +490,7 @@ class Package implements Constants { ...@@ -490,7 +490,7 @@ class Package implements Constants {
protected Entry[] getCPMap() { protected Entry[] getCPMap() {
return cpMap; return cpMap;
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
if (verbose > 2) Utils.log.fine("visitRefs "+this); if (verbose > 2) Utils.log.fine("visitRefs "+this);
// Careful: The descriptor is used by the package, // Careful: The descriptor is used by the package,
// but the classfile breaks it into component refs. // but the classfile breaks it into component refs.
...@@ -518,7 +518,7 @@ class Package implements Constants { ...@@ -518,7 +518,7 @@ class Package implements Constants {
super(flags, descriptor); super(flags, descriptor);
assert(!descriptor.isMethod()); assert(!descriptor.isMethod());
if (fields == null) if (fields == null)
fields = new ArrayList(); fields = new ArrayList<>();
boolean added = fields.add(this); boolean added = fields.add(this);
assert(added); assert(added);
order = fields.size(); order = fields.size();
...@@ -543,7 +543,7 @@ class Package implements Constants { ...@@ -543,7 +543,7 @@ class Package implements Constants {
super(flags, descriptor); super(flags, descriptor);
assert(descriptor.isMethod()); assert(descriptor.isMethod());
if (methods == null) if (methods == null)
methods = new ArrayList(); methods = new ArrayList<>();
boolean added = methods.add(this); boolean added = methods.add(this);
assert(added); assert(added);
} }
...@@ -573,7 +573,7 @@ class Package implements Constants { ...@@ -573,7 +573,7 @@ class Package implements Constants {
code.strip(attrName); code.strip(attrName);
super.strip(attrName); super.strip(attrName);
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
super.visitRefs(mode, refs); super.visitRefs(mode, refs);
if (code != null) { if (code != null) {
if (mode == VRM_CLASSIC) { if (mode == VRM_CLASSIC) {
...@@ -614,7 +614,7 @@ class Package implements Constants { ...@@ -614,7 +614,7 @@ class Package implements Constants {
super.strip(attrName); super.strip(attrName);
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
if (verbose > 2) Utils.log.fine("visitRefs "+this); if (verbose > 2) Utils.log.fine("visitRefs "+this);
refs.add(thisClass); refs.add(thisClass);
refs.add(superClass); refs.add(superClass);
...@@ -641,7 +641,7 @@ class Package implements Constants { ...@@ -641,7 +641,7 @@ class Package implements Constants {
super.visitRefs(mode, refs); super.visitRefs(mode, refs);
} }
protected void visitInnerClassRefs(int mode, Collection refs) { protected void visitInnerClassRefs(int mode, Collection<Entry> refs) {
Package.visitInnerClassRefs(innerClasses, mode, refs); Package.visitInnerClassRefs(innerClasses, mode, refs);
} }
...@@ -713,16 +713,15 @@ class Package implements Constants { ...@@ -713,16 +713,15 @@ class Package implements Constants {
} }
// What non-class files are in this unit? // What non-class files are in this unit?
ArrayList files = new ArrayList(); ArrayList<File> files = new ArrayList<>();
public List getFiles() { public List<File> getFiles() {
return files; return files;
} }
public List getClassStubs() { public List<File> getClassStubs() {
ArrayList classStubs = new ArrayList(classes.size()); ArrayList<File> classStubs = new ArrayList<>(classes.size());
for (Iterator i = classes.iterator(); i.hasNext(); ) { for (Class cls : classes) {
Class cls = (Class) i.next();
assert(cls.file.isClassStub()); assert(cls.file.isClassStub());
classStubs.add(cls.file); classStubs.add(cls.file);
} }
...@@ -840,7 +839,7 @@ class Package implements Constants { ...@@ -840,7 +839,7 @@ class Package implements Constants {
public InputStream getInputStream() { public InputStream getInputStream() {
InputStream in = new ByteArrayInputStream(append.toByteArray()); InputStream in = new ByteArrayInputStream(append.toByteArray());
if (prepend.size() == 0) return in; if (prepend.size() == 0) return in;
ArrayList isa = new ArrayList(prepend.size()+1); ArrayList<InputStream> isa = new ArrayList<>(prepend.size()+1);
for (Iterator i = prepend.iterator(); i.hasNext(); ) { for (Iterator i = prepend.iterator(); i.hasNext(); ) {
byte[] bytes = (byte[]) i.next(); byte[] bytes = (byte[]) i.next();
isa.add(new ByteArrayInputStream(bytes)); isa.add(new ByteArrayInputStream(bytes));
...@@ -849,7 +848,7 @@ class Package implements Constants { ...@@ -849,7 +848,7 @@ class Package implements Constants {
return new SequenceInputStream(Collections.enumeration(isa)); return new SequenceInputStream(Collections.enumeration(isa));
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
assert(name != null); assert(name != null);
refs.add(name); refs.add(name);
} }
...@@ -877,8 +876,8 @@ class Package implements Constants { ...@@ -877,8 +876,8 @@ class Package implements Constants {
} }
// Is there a globally declared table of inner classes? // Is there a globally declared table of inner classes?
ArrayList allInnerClasses = new ArrayList(); ArrayList<InnerClass> allInnerClasses = new ArrayList<>();
HashMap allInnerClassesByThis; HashMap<ClassEntry, InnerClass> allInnerClassesByThis;
public public
List getAllInnerClasses() { List getAllInnerClasses() {
...@@ -886,15 +885,14 @@ class Package implements Constants { ...@@ -886,15 +885,14 @@ class Package implements Constants {
} }
public public
void setAllInnerClasses(Collection ics) { void setAllInnerClasses(Collection<InnerClass> ics) {
assert(ics != allInnerClasses); assert(ics != allInnerClasses);
allInnerClasses.clear(); allInnerClasses.clear();
allInnerClasses.addAll(ics); allInnerClasses.addAll(ics);
// Make an index: // Make an index:
allInnerClassesByThis = new HashMap(allInnerClasses.size()); allInnerClassesByThis = new HashMap<>(allInnerClasses.size());
for (Iterator i = allInnerClasses.iterator(); i.hasNext(); ) { for (InnerClass ic : allInnerClasses) {
InnerClass ic = (InnerClass) i.next();
Object pic = allInnerClassesByThis.put(ic.thisClass, ic); Object pic = allInnerClassesByThis.put(ic.thisClass, ic);
assert(pic == null); // caller must ensure key uniqueness! assert(pic == null); // caller must ensure key uniqueness!
} }
...@@ -904,7 +902,7 @@ class Package implements Constants { ...@@ -904,7 +902,7 @@ class Package implements Constants {
public public
InnerClass getGlobalInnerClass(Entry thisClass) { InnerClass getGlobalInnerClass(Entry thisClass) {
assert(thisClass instanceof ClassEntry); assert(thisClass instanceof ClassEntry);
return (InnerClass) allInnerClassesByThis.get(thisClass); return allInnerClassesByThis.get(thisClass);
} }
static static
...@@ -963,7 +961,7 @@ class Package implements Constants { ...@@ -963,7 +961,7 @@ class Package implements Constants {
return this.thisClass.compareTo(that.thisClass); return this.thisClass.compareTo(that.thisClass);
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
refs.add(thisClass); refs.add(thisClass);
if (mode == VRM_CLASSIC || !predictable) { if (mode == VRM_CLASSIC || !predictable) {
// If the name can be demangled, the package omits // If the name can be demangled, the package omits
...@@ -980,7 +978,7 @@ class Package implements Constants { ...@@ -980,7 +978,7 @@ class Package implements Constants {
// Helper for building InnerClasses attributes. // Helper for building InnerClasses attributes.
static private static private
void visitInnerClassRefs(Collection innerClasses, int mode, Collection refs) { void visitInnerClassRefs(Collection innerClasses, int mode, Collection<Entry> refs) {
if (innerClasses == null) { if (innerClasses == null) {
return; // no attribute; nothing to do return; // no attribute; nothing to do
} }
...@@ -1165,9 +1163,8 @@ class Package implements Constants { ...@@ -1165,9 +1163,8 @@ class Package implements Constants {
} }
} }
protected void visitRefs(int mode, Collection refs) { protected void visitRefs(int mode, Collection<Entry> refs) {
for (Iterator i = classes.iterator(); i.hasNext(); ) { for ( Class c : classes) {
Class c = (Class)i.next();
c.visitRefs(mode, refs); c.visitRefs(mode, refs);
} }
if (mode != VRM_CLASSIC) { if (mode != VRM_CLASSIC) {
...@@ -1259,7 +1256,7 @@ class Package implements Constants { ...@@ -1259,7 +1256,7 @@ class Package implements Constants {
} }
// Use this before writing the package file. // Use this before writing the package file.
void buildGlobalConstantPool(Set requiredEntries) { void buildGlobalConstantPool(Set<Entry> requiredEntries) {
if (verbose > 1) if (verbose > 1)
Utils.log.fine("Checking for unused CP entries"); Utils.log.fine("Checking for unused CP entries");
requiredEntries.add(getRefString("")); // uconditionally present requiredEntries.add(getRefString("")); // uconditionally present
...@@ -1291,9 +1288,8 @@ class Package implements Constants { ...@@ -1291,9 +1288,8 @@ class Package implements Constants {
// Use this before writing the class files. // Use this before writing the class files.
void ensureAllClassFiles() { void ensureAllClassFiles() {
HashSet fileSet = new HashSet(files); HashSet<File> fileSet = new HashSet<>(files);
for (Iterator i = classes.iterator(); i.hasNext(); ) { for (Class cls : classes) {
Class cls = (Class) i.next();
// Add to the end of ths list: // Add to the end of ths list:
if (!fileSet.contains(cls.file)) if (!fileSet.contains(cls.file))
files.add(cls.file); files.add(cls.file);
......
/* /*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,12 +25,11 @@ ...@@ -25,12 +25,11 @@
package com.sun.java.util.jar.pack; package com.sun.java.util.jar.pack;
import com.sun.java.util.jar.pack.Attribute.Layout;
import java.util.*; import java.util.*;
import java.util.jar.*; import java.util.jar.*;
import java.util.zip.*;
import java.io.*; import java.io.*;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
/* /*
...@@ -41,31 +40,22 @@ import java.beans.PropertyChangeEvent; ...@@ -41,31 +40,22 @@ import java.beans.PropertyChangeEvent;
*/ */
public class PackerImpl implements Pack200.Packer { public class PackerImpl extends TLGlobals implements Pack200.Packer {
/** /**
* Constructs a Packer object and sets the initial state of * Constructs a Packer object and sets the initial state of
* the packer engines. * the packer engines.
*/ */
public PackerImpl() { public PackerImpl() {}
_props = new PropMap();
//_props.getProperty() consults defaultProps invisibly.
//_props.putAll(defaultProps);
}
// Private stuff.
final PropMap _props;
/** /**
* Get the set of options for the pack and unpack engines. * Get the set of options for the pack and unpack engines.
* @return A sorted association of option key strings to option values. * @return A sorted association of option key strings to option values.
*/ */
public SortedMap properties() { public SortedMap<String, String> properties() {
return _props; return props;
} }
//Driver routines //Driver routines
/** /**
...@@ -78,21 +68,22 @@ public class PackerImpl implements Pack200.Packer { ...@@ -78,21 +68,22 @@ public class PackerImpl implements Pack200.Packer {
*/ */
public void pack(JarFile in, OutputStream out) throws IOException { public void pack(JarFile in, OutputStream out) throws IOException {
assert(Utils.currentInstance.get() == null); assert(Utils.currentInstance.get() == null);
TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
TimeZone.getDefault(); ? null
: TimeZone.getDefault();
try { try {
Utils.currentInstance.set(this); Utils.currentInstance.set(this);
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) { if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) {
Utils.copyJarFile(in, out); Utils.copyJarFile(in, out);
} else { } else {
(new DoPack()).run(in, out); (new DoPack()).run(in, out);
in.close();
} }
} finally { } finally {
Utils.currentInstance.set(null); Utils.currentInstance.set(null);
if (tz != null) TimeZone.setDefault(tz); if (tz != null) TimeZone.setDefault(tz);
in.close();
} }
} }
...@@ -112,21 +103,20 @@ public class PackerImpl implements Pack200.Packer { ...@@ -112,21 +103,20 @@ public class PackerImpl implements Pack200.Packer {
*/ */
public void pack(JarInputStream in, OutputStream out) throws IOException { public void pack(JarInputStream in, OutputStream out) throws IOException {
assert(Utils.currentInstance.get() == null); assert(Utils.currentInstance.get() == null);
TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
TimeZone.getDefault(); TimeZone.getDefault();
try { try {
Utils.currentInstance.set(this); Utils.currentInstance.set(this);
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) { if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) {
Utils.copyJarFile(in, out); Utils.copyJarFile(in, out);
} else { } else {
(new DoPack()).run(in, out); (new DoPack()).run(in, out);
in.close();
} }
} finally { } finally {
Utils.currentInstance.set(null); Utils.currentInstance.set(null);
if (tz != null) TimeZone.setDefault(tz); if (tz != null) TimeZone.setDefault(tz);
in.close();
} }
} }
/** /**
...@@ -134,7 +124,7 @@ public class PackerImpl implements Pack200.Packer { ...@@ -134,7 +124,7 @@ public class PackerImpl implements Pack200.Packer {
* @param listener An object to be invoked when a property is changed. * @param listener An object to be invoked when a property is changed.
*/ */
public void addPropertyChangeListener(PropertyChangeListener listener) { public void addPropertyChangeListener(PropertyChangeListener listener) {
_props.addListener(listener); props.addListener(listener);
} }
/** /**
...@@ -142,7 +132,7 @@ public class PackerImpl implements Pack200.Packer { ...@@ -142,7 +132,7 @@ public class PackerImpl implements Pack200.Packer {
* @param listener The PropertyChange listener to be removed. * @param listener The PropertyChange listener to be removed.
*/ */
public void removePropertyChangeListener(PropertyChangeListener listener) { public void removePropertyChangeListener(PropertyChangeListener listener) {
_props.removeListener(listener); props.removeListener(listener);
} }
...@@ -151,11 +141,11 @@ public class PackerImpl implements Pack200.Packer { ...@@ -151,11 +141,11 @@ public class PackerImpl implements Pack200.Packer {
// The packer worker. // The packer worker.
private class DoPack { private class DoPack {
final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
{ {
_props.setInteger(Pack200.Packer.PROGRESS, 0); props.setInteger(Pack200.Packer.PROGRESS, 0);
if (verbose > 0) Utils.log.info(_props.toString()); if (verbose > 0) Utils.log.info(props.toString());
} }
// Here's where the bits are collected before getting packed: // Here's where the bits are collected before getting packed:
...@@ -163,7 +153,7 @@ public class PackerImpl implements Pack200.Packer { ...@@ -163,7 +153,7 @@ public class PackerImpl implements Pack200.Packer {
final String unknownAttrCommand; final String unknownAttrCommand;
{ {
String uaMode = _props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); String uaMode = props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
if (!(Pack200.Packer.STRIP.equals(uaMode) || if (!(Pack200.Packer.STRIP.equals(uaMode) ||
Pack200.Packer.PASS.equals(uaMode) || Pack200.Packer.PASS.equals(uaMode) ||
Pack200.Packer.ERROR.equals(uaMode))) { Pack200.Packer.ERROR.equals(uaMode))) {
...@@ -191,13 +181,12 @@ public class PackerImpl implements Pack200.Packer { ...@@ -191,13 +181,12 @@ public class PackerImpl implements Pack200.Packer {
}; };
for (int i = 0; i < ctypes.length; i++) { for (int i = 0; i < ctypes.length; i++) {
String pfx = keys[i]; String pfx = keys[i];
Map map = _props.prefixMap(pfx); Map<String, String> map = props.prefixMap(pfx);
for (Iterator j = map.keySet().iterator(); j.hasNext(); ) { for (String key : map.keySet()) {
String key = (String) j.next();
assert(key.startsWith(pfx)); assert(key.startsWith(pfx));
String name = key.substring(pfx.length()); String name = key.substring(pfx.length());
String layout = _props.getProperty(key); String layout = props.getProperty(key);
Object lkey = Attribute.keyForLookup(ctypes[i], name); Layout lkey = Attribute.keyForLookup(ctypes[i], name);
if (Pack200.Packer.STRIP.equals(layout) || if (Pack200.Packer.STRIP.equals(layout) ||
Pack200.Packer.PASS.equals(layout) || Pack200.Packer.PASS.equals(layout) ||
Pack200.Packer.ERROR.equals(layout)) { Pack200.Packer.ERROR.equals(layout)) {
...@@ -222,25 +211,25 @@ public class PackerImpl implements Pack200.Packer { ...@@ -222,25 +211,25 @@ public class PackerImpl implements Pack200.Packer {
} }
final boolean keepFileOrder final boolean keepFileOrder
= _props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER); = props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER);
final boolean keepClassOrder final boolean keepClassOrder
= _props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER); = props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER);
final boolean keepModtime final boolean keepModtime
= Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME)); = Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME));
final boolean latestModtime final boolean latestModtime
= Pack200.Packer.LATEST.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME)); = Pack200.Packer.LATEST.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME));
final boolean keepDeflateHint final boolean keepDeflateHint
= Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.DEFLATE_HINT)); = Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.DEFLATE_HINT));
{ {
if (!keepModtime && !latestModtime) { if (!keepModtime && !latestModtime) {
int modtime = _props.getTime(Pack200.Packer.MODIFICATION_TIME); int modtime = props.getTime(Pack200.Packer.MODIFICATION_TIME);
if (modtime != Constants.NO_MODTIME) { if (modtime != Constants.NO_MODTIME) {
pkg.default_modtime = modtime; pkg.default_modtime = modtime;
} }
} }
if (!keepDeflateHint) { if (!keepDeflateHint) {
boolean deflate_hint = _props.getBoolean(Pack200.Packer.DEFLATE_HINT); boolean deflate_hint = props.getBoolean(Pack200.Packer.DEFLATE_HINT);
if (deflate_hint) { if (deflate_hint) {
pkg.default_options |= Constants.AO_DEFLATE_HINT; pkg.default_options |= Constants.AO_DEFLATE_HINT;
} }
...@@ -254,10 +243,10 @@ public class PackerImpl implements Pack200.Packer { ...@@ -254,10 +243,10 @@ public class PackerImpl implements Pack200.Packer {
final long segmentLimit; final long segmentLimit;
{ {
long limit; long limit;
if (_props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals("")) if (props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals(""))
limit = -1; limit = -1;
else else
limit = _props.getLong(Pack200.Packer.SEGMENT_LIMIT); limit = props.getLong(Pack200.Packer.SEGMENT_LIMIT);
limit = Math.min(Integer.MAX_VALUE, limit); limit = Math.min(Integer.MAX_VALUE, limit);
limit = Math.max(-1, limit); limit = Math.max(-1, limit);
if (limit == -1) if (limit == -1)
...@@ -265,10 +254,10 @@ public class PackerImpl implements Pack200.Packer { ...@@ -265,10 +254,10 @@ public class PackerImpl implements Pack200.Packer {
segmentLimit = limit; segmentLimit = limit;
} }
final List passFiles; // parsed pack.pass.file options final List<String> passFiles; // parsed pack.pass.file options
{ {
// Which class files will be passed through? // Which class files will be passed through?
passFiles = _props.getProperties(Pack200.Packer.PASS_FILE_PFX); passFiles = props.getProperties(Pack200.Packer.PASS_FILE_PFX);
for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) { for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) {
String file = (String) i.next(); String file = (String) i.next();
if (file == null) { i.remove(); continue; } if (file == null) { i.remove(); continue; }
...@@ -283,28 +272,28 @@ public class PackerImpl implements Pack200.Packer { ...@@ -283,28 +272,28 @@ public class PackerImpl implements Pack200.Packer {
{ {
// Fill in permitted range of major/minor version numbers. // Fill in permitted range of major/minor version numbers.
int ver; int ver;
if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0) if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0)
pkg.min_class_majver = (short) ver; pkg.min_class_majver = (short) ver;
if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0) if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0)
pkg.min_class_minver = (short) ver; pkg.min_class_minver = (short) ver;
if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0) if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0)
pkg.max_class_majver = (short) ver; pkg.max_class_majver = (short) ver;
if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0) if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0)
pkg.max_class_minver = (short) ver; pkg.max_class_minver = (short) ver;
if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0) if ((ver = props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0)
pkg.package_minver = (short) ver; pkg.package_minver = (short) ver;
if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0) if ((ver = props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0)
pkg.package_majver = (short) ver; pkg.package_majver = (short) ver;
} }
{ {
// Hook for testing: Forces use of special archive modes. // Hook for testing: Forces use of special archive modes.
int opt = _props.getInteger(Utils.COM_PREFIX+"archive.options"); int opt = props.getInteger(Utils.COM_PREFIX+"archive.options");
if (opt != 0) if (opt != 0)
pkg.default_options |= opt; pkg.default_options |= opt;
} }
// (Done collecting options from _props.) // (Done collecting options from props.)
boolean isClassFile(String name) { boolean isClassFile(String name) {
if (!name.endsWith(".class")) return false; if (!name.endsWith(".class")) return false;
...@@ -423,16 +412,18 @@ public class PackerImpl implements Pack200.Packer { ...@@ -423,16 +412,18 @@ public class PackerImpl implements Pack200.Packer {
Package.File file = null; Package.File file = null;
// (5078608) : discount the resource files in META-INF // (5078608) : discount the resource files in META-INF
// from segment computation. // from segment computation.
long inflen = (isMetaInfFile(name)) ? 0L : long inflen = (isMetaInfFile(name))
inFile.getInputLength(); ? 0L
: inFile.getInputLength();
if ((segmentSize += inflen) > segmentLimit) { if ((segmentSize += inflen) > segmentLimit) {
segmentSize -= inflen; segmentSize -= inflen;
int nextCount = -1; // don't know; it's a stream int nextCount = -1; // don't know; it's a stream
flushPartial(out, nextCount); flushPartial(out, nextCount);
} }
if (verbose > 1) if (verbose > 1) {
Utils.log.fine("Reading " + name); Utils.log.fine("Reading " + name);
}
assert(je.isDirectory() == name.endsWith("/")); assert(je.isDirectory() == name.endsWith("/"));
...@@ -450,18 +441,18 @@ public class PackerImpl implements Pack200.Packer { ...@@ -450,18 +441,18 @@ public class PackerImpl implements Pack200.Packer {
} }
void run(JarFile in, OutputStream out) throws IOException { void run(JarFile in, OutputStream out) throws IOException {
List inFiles = scanJar(in); List<InFile> inFiles = scanJar(in);
if (verbose > 0) if (verbose > 0)
Utils.log.info("Reading " + inFiles.size() + " files..."); Utils.log.info("Reading " + inFiles.size() + " files...");
int numDone = 0; int numDone = 0;
for (Iterator i = inFiles.iterator(); i.hasNext(); ) { for (InFile inFile : inFiles) {
InFile inFile = (InFile) i.next();
String name = inFile.name; String name = inFile.name;
// (5078608) : discount the resource files completely from segmenting // (5078608) : discount the resource files completely from segmenting
long inflen = (isMetaInfFile(name)) ? 0L : long inflen = (isMetaInfFile(name))
inFile.getInputLength() ; ? 0L
: inFile.getInputLength() ;
if ((segmentSize += inflen) > segmentLimit) { if ((segmentSize += inflen) > segmentLimit) {
segmentSize -= inflen; segmentSize -= inflen;
// Estimate number of remaining segments: // Estimate number of remaining segments:
...@@ -530,11 +521,11 @@ public class PackerImpl implements Pack200.Packer { ...@@ -530,11 +521,11 @@ public class PackerImpl implements Pack200.Packer {
} }
void flushPartial(OutputStream out, int nextCount) throws IOException { void flushPartial(OutputStream out, int nextCount) throws IOException {
if (pkg.files.size() == 0 && pkg.classes.size() == 0) { if (pkg.files.isEmpty() && pkg.classes.isEmpty()) {
return; // do not flush an empty segment return; // do not flush an empty segment
} }
flushPackage(out, Math.max(1, nextCount)); flushPackage(out, Math.max(1, nextCount));
_props.setInteger(Pack200.Packer.PROGRESS, 25); props.setInteger(Pack200.Packer.PROGRESS, 25);
// In case there will be another segment: // In case there will be another segment:
makeNextPackage(); makeNextPackage();
segmentCount += 1; segmentCount += 1;
...@@ -543,10 +534,10 @@ public class PackerImpl implements Pack200.Packer { ...@@ -543,10 +534,10 @@ public class PackerImpl implements Pack200.Packer {
} }
void flushAll(OutputStream out) throws IOException { void flushAll(OutputStream out) throws IOException {
_props.setInteger(Pack200.Packer.PROGRESS, 50); props.setInteger(Pack200.Packer.PROGRESS, 50);
flushPackage(out, 0); flushPackage(out, 0);
out.flush(); out.flush();
_props.setInteger(Pack200.Packer.PROGRESS, 100); props.setInteger(Pack200.Packer.PROGRESS, 100);
segmentCount += 1; segmentCount += 1;
segmentTotalSize += segmentSize; segmentTotalSize += segmentSize;
segmentSize = 0; segmentSize = 0;
...@@ -582,11 +573,11 @@ public class PackerImpl implements Pack200.Packer { ...@@ -582,11 +573,11 @@ public class PackerImpl implements Pack200.Packer {
pkg.trimStubs(); pkg.trimStubs();
// Do some stripping, maybe. // Do some stripping, maybe.
if (_props.getBoolean(Utils.COM_PREFIX+"strip.debug")) pkg.stripAttributeKind("Debug"); 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.compile")) pkg.stripAttributeKind("Compile");
if (_props.getBoolean(Utils.COM_PREFIX+"strip.constants")) pkg.stripAttributeKind("Constant"); 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.exceptions")) pkg.stripAttributeKind("Exceptions");
if (_props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses"); if (props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses");
// Must choose an archive version; PackageWriter does not. // Must choose an archive version; PackageWriter does not.
if (pkg.package_majver <= 0) pkg.choosePackageVersion(); if (pkg.package_majver <= 0) pkg.choosePackageVersion();
...@@ -606,11 +597,10 @@ public class PackerImpl implements Pack200.Packer { ...@@ -606,11 +597,10 @@ public class PackerImpl implements Pack200.Packer {
} }
} }
List scanJar(JarFile jf) throws IOException { List<InFile> scanJar(JarFile jf) throws IOException {
// Collect jar entries, preserving order. // Collect jar entries, preserving order.
List inFiles = new ArrayList(); List<InFile> inFiles = new ArrayList<>();
for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { for (JarEntry je : Collections.list(jf.entries())) {
JarEntry je = (JarEntry) e.nextElement();
InFile inFile = new InFile(jf, je); InFile inFile = new InFile(jf, je);
assert(je.isDirectory() == inFile.name.endsWith("/")); assert(je.isDirectory() == inFile.name.endsWith("/"));
inFiles.add(inFile); inFiles.add(inFile);
......
...@@ -91,7 +91,7 @@ class PropMap extends TreeMap { ...@@ -91,7 +91,7 @@ class PropMap extends TreeMap {
String.valueOf(Boolean.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))); String.valueOf(Boolean.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)));
// The segment size is unlimited // The segment size is unlimited
props.put(Pack200.Packer.SEGMENT_LIMIT, ""); props.put(Pack200.Packer.SEGMENT_LIMIT, "-1");
// Preserve file ordering by default. // Preserve file ordering by default.
props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE); props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE);
......
/*
* 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 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.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<String, Utf8Entry> utf8Entries;
private final Map<String, ClassEntry> classEntries;
private final Map<Object, LiteralEntry> literalEntries;
private final Map<String, SignatureEntry> signatureEntries;
private final Map<String, DescriptorEntry> descriptorEntries;
private final Map<String, MemberEntry> memberEntries;
TLGlobals() {
utf8Entries = new HashMap<>();
classEntries = new HashMap<>();
literalEntries = new HashMap<>();
signatureEntries = new HashMap<>();
descriptorEntries = new HashMap<>();
memberEntries = new HashMap<>();
props = new PropMap();
}
SortedMap<Object, Object> getPropMap() {
return props;
}
Map<String, Utf8Entry> getUtf8Entries() {
return utf8Entries;
}
Map<String, ClassEntry> getClassEntries() {
return classEntries;
}
Map<Object, LiteralEntry> getLiteralEntries() {
return literalEntries;
}
Map<String, DescriptorEntry> getDescriptorEntries() {
return descriptorEntries;
}
Map<String, SignatureEntry> getSignatureEntries() {
return signatureEntries;
}
Map<String, MemberEntry> getMemberEntries() {
return memberEntries;
}
}
/* /*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,7 +30,6 @@ import java.util.jar.*; ...@@ -30,7 +30,6 @@ import java.util.jar.*;
import java.util.zip.*; import java.util.zip.*;
import java.io.*; import java.io.*;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
/* /*
* Implementation of the Pack provider. * Implementation of the Pack provider.
...@@ -40,7 +39,7 @@ import java.beans.PropertyChangeEvent; ...@@ -40,7 +39,7 @@ import java.beans.PropertyChangeEvent;
*/ */
public class UnpackerImpl implements Pack200.Unpacker { public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
/** /**
...@@ -48,7 +47,7 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -48,7 +47,7 @@ public class UnpackerImpl implements Pack200.Unpacker {
* @param listener An object to be invoked when a property is changed. * @param listener An object to be invoked when a property is changed.
*/ */
public void addPropertyChangeListener(PropertyChangeListener listener) { public void addPropertyChangeListener(PropertyChangeListener listener) {
_props.addListener(listener); props.addListener(listener);
} }
...@@ -57,25 +56,19 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -57,25 +56,19 @@ public class UnpackerImpl implements Pack200.Unpacker {
* @param listener The PropertyChange listener to be removed. * @param listener The PropertyChange listener to be removed.
*/ */
public void removePropertyChangeListener(PropertyChangeListener listener) { public void removePropertyChangeListener(PropertyChangeListener listener) {
_props.removeListener(listener); props.removeListener(listener);
} }
public UnpackerImpl() { public UnpackerImpl() {}
_props = new PropMap();
//_props.getProperty() consults defaultProps invisibly.
//_props.putAll(defaultProps);
}
// Private stuff.
final PropMap _props;
/** /**
* Get the set of options for the pack and unpack engines. * Get the set of options for the pack and unpack engines.
* @return A sorted association of option key strings to option values. * @return A sorted association of option key strings to option values.
*/ */
public SortedMap properties() { public SortedMap<String, String> properties() {
return _props; return props;
} }
// Back-pointer to NativeUnpacker, when active. // Back-pointer to NativeUnpacker, when active.
...@@ -101,19 +94,20 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -101,19 +94,20 @@ public class UnpackerImpl implements Pack200.Unpacker {
*/ */
public void unpack(InputStream in0, JarOutputStream out) throws IOException { public void unpack(InputStream in0, JarOutputStream out) throws IOException {
assert(Utils.currentInstance.get() == null); assert(Utils.currentInstance.get() == null);
TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
TimeZone.getDefault(); ? null
: TimeZone.getDefault();
try { try {
Utils.currentInstance.set(this); Utils.currentInstance.set(this);
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
BufferedInputStream in = new BufferedInputStream(in0); BufferedInputStream in = new BufferedInputStream(in0);
if (Utils.isJarMagic(Utils.readMagic(in))) { if (Utils.isJarMagic(Utils.readMagic(in))) {
if (verbose > 0) if (verbose > 0)
Utils.log.info("Copying unpacked JAR file..."); Utils.log.info("Copying unpacked JAR file...");
Utils.copyJarFile(new JarInputStream(in), out); Utils.copyJarFile(new JarInputStream(in), out);
} else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) { } else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
(new DoUnpack()).run(in, out); (new DoUnpack()).run(in, out);
in.close(); in.close();
Utils.markJarFile(out); Utils.markJarFile(out);
...@@ -142,36 +136,38 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -142,36 +136,38 @@ public class UnpackerImpl implements Pack200.Unpacker {
// %%% Reconsider if native unpacker learns to memory-map the file. // %%% Reconsider if native unpacker learns to memory-map the file.
FileInputStream instr = new FileInputStream(in); FileInputStream instr = new FileInputStream(in);
unpack(instr, out); unpack(instr, out);
if (_props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) { if (props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
in.delete(); in.delete();
} }
} }
private class DoUnpack { private class DoUnpack {
final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
{ {
_props.setInteger(Pack200.Unpacker.PROGRESS, 0); props.setInteger(Pack200.Unpacker.PROGRESS, 0);
} }
// Here's where the bits are read from disk: // Here's where the bits are read from disk:
final Package pkg = new Package(); final Package pkg = new Package();
final boolean keepModtime final boolean keepModtime
= Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP)); = Pack200.Packer.KEEP.equals(
props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
final boolean keepDeflateHint final boolean keepDeflateHint
= Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP)); = Pack200.Packer.KEEP.equals(
props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
final int modtime; final int modtime;
final boolean deflateHint; final boolean deflateHint;
{ {
if (!keepModtime) { if (!keepModtime) {
modtime = _props.getTime(Utils.UNPACK_MODIFICATION_TIME); modtime = props.getTime(Utils.UNPACK_MODIFICATION_TIME);
} else { } else {
modtime = pkg.default_modtime; modtime = pkg.default_modtime;
} }
deflateHint = (keepDeflateHint) ? false : deflateHint = (keepDeflateHint) ? false :
_props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT); props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
} }
// Checksum apparatus. // Checksum apparatus.
...@@ -181,7 +177,7 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -181,7 +177,7 @@ public class UnpackerImpl implements Pack200.Unpacker {
public void run(BufferedInputStream in, JarOutputStream out) throws IOException { public void run(BufferedInputStream in, JarOutputStream out) throws IOException {
if (verbose > 0) { if (verbose > 0) {
_props.list(System.out); props.list(System.out);
} }
for (int seg = 1; ; seg++) { for (int seg = 1; ; seg++) {
unpackSegment(in, out); unpackSegment(in, out);
...@@ -194,25 +190,26 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -194,25 +190,26 @@ public class UnpackerImpl implements Pack200.Unpacker {
} }
private void unpackSegment(InputStream in, JarOutputStream out) throws IOException { private void unpackSegment(InputStream in, JarOutputStream out) throws IOException {
_props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0"); props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
// Process the output directory or jar output. // Process the output directory or jar output.
new PackageReader(pkg, in).read(); new PackageReader(pkg, in).read();
if (_props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug"); if (props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug");
if (_props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile"); if (props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile");
_props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50"); props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
pkg.ensureAllClassFiles(); pkg.ensureAllClassFiles();
// Now write out the files. // Now write out the files.
HashSet classesToWrite = new HashSet(pkg.getClasses()); HashSet<Package.Class> classesToWrite = new HashSet<>(pkg.getClasses());
for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) { for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) {
Package.File file = (Package.File) i.next(); Package.File file = (Package.File) i.next();
String name = file.nameString; String name = file.nameString;
JarEntry je = new JarEntry(Utils.getJarEntryName(name)); JarEntry je = new JarEntry(Utils.getJarEntryName(name));
boolean deflate; boolean deflate;
deflate = (keepDeflateHint) ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) || deflate = (keepDeflateHint)
((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) : ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
deflateHint; ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0))
: deflateHint;
boolean needCRC = !deflate; // STORE mode requires CRC boolean needCRC = !deflate; // STORE mode requires CRC
...@@ -250,7 +247,7 @@ public class UnpackerImpl implements Pack200.Unpacker { ...@@ -250,7 +247,7 @@ public class UnpackerImpl implements Pack200.Unpacker {
Utils.log.info("Writing "+Utils.zeString((ZipEntry)je)); Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
} }
assert(classesToWrite.isEmpty()); assert(classesToWrite.isEmpty());
_props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100"); props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
pkg.reset(); // reset for the next segment, if any pkg.reset(); // reset for the next segment, if any
} }
} }
......
/* /*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,13 @@ ...@@ -25,6 +25,13 @@
package com.sun.java.util.jar.pack; package com.sun.java.util.jar.pack;
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.LiteralEntry;
import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
import java.util.*; import java.util.*;
import java.util.jar.*; import java.util.jar.*;
import java.util.zip.*; import java.util.zip.*;
...@@ -113,17 +120,46 @@ class Utils { ...@@ -113,17 +120,46 @@ class Utils {
*/ */
static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
// Keep a TLS point to the current Packer or Unpacker. // Keep a TLS point to the global data and environment.
// This makes it simpler to supply environmental options // This makes it simpler to supply environmental options
// to the engine code, especially the native code. // to the engine code, especially the native code.
static final ThreadLocal currentInstance = new ThreadLocal(); static final ThreadLocal<TLGlobals> currentInstance = new ThreadLocal<>();
// convenience methods to access the TL globals
static TLGlobals getTLGlobals() {
return currentInstance.get();
}
static Map<String, Utf8Entry> getUtf8Entries() {
return getTLGlobals().getUtf8Entries();
}
static Map<String, ClassEntry> getClassEntries() {
return getTLGlobals().getClassEntries();
}
static Map<Object, LiteralEntry> getLiteralEntries() {
return getTLGlobals().getLiteralEntries();
}
static Map<String, DescriptorEntry> getDescriptorEntries() {
return getTLGlobals().getDescriptorEntries();
}
static Map<String, SignatureEntry> getSignatureEntries() {
return getTLGlobals().getSignatureEntries();
}
static Map<String, MemberEntry> getMemberEntries() {
return getTLGlobals().getMemberEntries();
}
static PropMap currentPropMap() { static PropMap currentPropMap() {
Object obj = currentInstance.get(); Object obj = currentInstance.get();
if (obj instanceof PackerImpl) if (obj instanceof PackerImpl)
return ((PackerImpl)obj)._props; return ((PackerImpl)obj).props;
if (obj instanceof UnpackerImpl) if (obj instanceof UnpackerImpl)
return ((UnpackerImpl)obj)._props; return ((UnpackerImpl)obj).props;
return null; return null;
} }
......
...@@ -813,7 +813,8 @@ public final class Connection implements Runnable { ...@@ -813,7 +813,8 @@ public final class Connection implements Runnable {
try { try {
while (true) { while (true) {
try { try {
inbuf = new byte[10]; // type and length (at most 128 octets for long form)
inbuf = new byte[129];
offset = 0; offset = 0;
seqlen = 0; seqlen = 0;
......
...@@ -470,7 +470,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { ...@@ -470,7 +470,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
public AbstractStringBuilder append(CharSequence s, int start, int end) { public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null) if (s == null)
s = "null"; s = "null";
if ((start < 0) || (end < 0) || (start > end) || (end > s.length())) if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException( throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() " "start " + start + ", end " + end + ", s.length() "
+ s.length()); + s.length());
...@@ -529,7 +529,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { ...@@ -529,7 +529,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* or {@code offset+len > str.length} * or {@code offset+len > str.length}
*/ */
public AbstractStringBuilder append(char str[], int offset, int len) { public AbstractStringBuilder append(char str[], int offset, int len) {
ensureCapacityInternal(count + len); if (len > 0) // let arraycopy report AIOOBE for len < 0
ensureCapacityInternal(count + len);
System.arraycopy(str, offset, value, count, len); System.arraycopy(str, offset, value, count, len);
count += len; count += len;
return this; return this;
......
...@@ -413,6 +413,18 @@ class Thread implements Runnable { ...@@ -413,6 +413,18 @@ class Thread implements Runnable {
tid = nextThreadID(); tid = nextThreadID();
} }
/**
* Throws CloneNotSupportedException as a Thread can not be meaningfully
* cloned. Construct a new Thread instead.
*
* @throws CloneNotSupportedException
* always
*/
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/** /**
* Allocates a new {@code Thread} object. This constructor has the same * Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
......
...@@ -200,7 +200,16 @@ public class Throwable implements Serializable { ...@@ -200,7 +200,16 @@ public class Throwable implements Serializable {
* @serial * @serial
* @since 1.7 * @since 1.7
*/ */
private List<Throwable> suppressedExceptions = Collections.emptyList(); private List<Throwable> suppressedExceptions = null;
/*
* This field is lazily initialized when the first suppressed
* exception is added.
*
* OutOfMemoryError is preallocated in the VM for better OOM
* diagnosability during VM initialization. Constructor can't
* be not invoked. If a new field to be added in the future must
* be initialized to non-null, it requires a synchronized VM change.
*/
/** Message for trying to suppress a null exception. */ /** Message for trying to suppress a null exception. */
private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception."; private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
...@@ -329,7 +338,7 @@ public class Throwable implements Serializable { ...@@ -329,7 +338,7 @@ public class Throwable implements Serializable {
* cause is nonexistent or unknown. * cause is nonexistent or unknown.
* @since 1.4 * @since 1.4
*/ */
public Throwable getCause() { public synchronized Throwable getCause() {
return (cause==this ? null : cause); return (cause==this ? null : cause);
} }
...@@ -563,7 +572,7 @@ public class Throwable implements Serializable { ...@@ -563,7 +572,7 @@ public class Throwable implements Serializable {
s.println("\tat " + traceElement); s.println("\tat " + traceElement);
// Print suppressed exceptions, if any // Print suppressed exceptions, if any
for (Throwable se : suppressedExceptions) for (Throwable se : getSuppressedExceptions())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
// Print cause, if any // Print cause, if any
...@@ -604,7 +613,7 @@ public class Throwable implements Serializable { ...@@ -604,7 +613,7 @@ public class Throwable implements Serializable {
s.println(prefix + "\t... " + framesInCommon + " more"); s.println(prefix + "\t... " + framesInCommon + " more");
// Print suppressed exceptions, if any // Print suppressed exceptions, if any
for (Throwable se : suppressedExceptions) for (Throwable se : getSuppressedExceptions())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
prefix +"\t", dejaVu); prefix +"\t", dejaVu);
...@@ -747,7 +756,9 @@ public class Throwable implements Serializable { ...@@ -747,7 +756,9 @@ public class Throwable implements Serializable {
if (defensiveCopy[i] == null) if (defensiveCopy[i] == null)
throw new NullPointerException("stackTrace[" + i + "]"); throw new NullPointerException("stackTrace[" + i + "]");
this.stackTrace = defensiveCopy; synchronized (this) {
this.stackTrace = defensiveCopy;
}
} }
/** /**
...@@ -772,11 +783,11 @@ public class Throwable implements Serializable { ...@@ -772,11 +783,11 @@ public class Throwable implements Serializable {
private void readObject(ObjectInputStream s) private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException {
s.defaultReadObject(); // read in all fields s.defaultReadObject(); // read in all fields
List<Throwable> suppressed = Collections.emptyList(); List<Throwable> suppressed = null;
if (suppressedExceptions != null && if (suppressedExceptions != null &&
!suppressedExceptions.isEmpty()) { // Copy Throwables to new list !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
suppressed = new ArrayList<Throwable>(); suppressed = new ArrayList<Throwable>();
for(Throwable t : suppressedExceptions) { for (Throwable t : suppressedExceptions) {
if (t == null) if (t == null)
throw new NullPointerException(NULL_CAUSE_MESSAGE); throw new NullPointerException(NULL_CAUSE_MESSAGE);
suppressed.add(t); suppressed.add(t);
...@@ -819,7 +830,7 @@ public class Throwable implements Serializable { ...@@ -819,7 +830,7 @@ public class Throwable implements Serializable {
if (exception == this) if (exception == this)
throw new IllegalArgumentException("Self-suppression not permitted"); throw new IllegalArgumentException("Self-suppression not permitted");
if (suppressedExceptions.size() == 0) if (suppressedExceptions == null)
suppressedExceptions = new ArrayList<Throwable>(); suppressedExceptions = new ArrayList<Throwable>();
suppressedExceptions.add(exception); suppressedExceptions.add(exception);
} }
...@@ -835,7 +846,10 @@ public class Throwable implements Serializable { ...@@ -835,7 +846,10 @@ public class Throwable implements Serializable {
* suppressed to deliver this exception. * suppressed to deliver this exception.
* @since 1.7 * @since 1.7
*/ */
public Throwable[] getSuppressedExceptions() { public synchronized Throwable[] getSuppressedExceptions() {
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); if (suppressedExceptions == null)
return EMPTY_THROWABLE_ARRAY;
else
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
} }
} }
...@@ -1093,14 +1093,8 @@ public final class HttpCookie implements Cloneable { ...@@ -1093,14 +1093,8 @@ public final class HttpCookie implements Cloneable {
return sb.toString(); return sb.toString();
} }
private static SimpleDateFormat[] cDateFormats = null; static final TimeZone GMT = TimeZone.getTimeZone("GMT");
static {
cDateFormats = new SimpleDateFormat[COOKIE_DATE_FORMATS.length];
for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
cDateFormats[i] = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US);
cDateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT"));
}
}
/* /*
* @param dateString a date string in one of the formats * @param dateString a date string in one of the formats
* defined in Netscape cookie spec * defined in Netscape cookie spec
...@@ -1109,12 +1103,14 @@ public final class HttpCookie implements Cloneable { ...@@ -1109,12 +1103,14 @@ public final class HttpCookie implements Cloneable {
* time and the time specified by dateString * time and the time specified by dateString
*/ */
private long expiryDate2DeltaSeconds(String dateString) { private long expiryDate2DeltaSeconds(String dateString) {
for (SimpleDateFormat df : cDateFormats) { for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
SimpleDateFormat df = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US);
df.setTimeZone(GMT);
try { try {
Date date = df.parse(dateString); Date date = df.parse(dateString);
return (date.getTime() - whenCreated) / 1000; return (date.getTime() - whenCreated) / 1000;
} catch (Exception e) { } catch (Exception e) {
// Ignore, try the next date format
} }
} }
return 0; return 0;
......
...@@ -856,9 +856,7 @@ public final class URI ...@@ -856,9 +856,7 @@ public final class URI
try { try {
return new URI(str); return new URI(str);
} catch (URISyntaxException x) { } catch (URISyntaxException x) {
IllegalArgumentException y = new IllegalArgumentException(); throw new IllegalArgumentException(x.getMessage(), x);
y.initCause(x);
throw y;
} }
} }
......
/* /*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -131,17 +131,19 @@ import javax.security.auth.callback.*; ...@@ -131,17 +131,19 @@ import javax.security.auth.callback.*;
* to read existing entries from the keystore, or to write new entries * to read existing entries from the keystore, or to write new entries
* into the keystore: * into the keystore:
* <pre> * <pre>
* KeyStore.ProtectionParameter protParam =
* new KeyStore.PasswordProtection(password);
*
* // get my private key * // get my private key
* KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) * KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
* ks.getEntry("privateKeyAlias", password); * ks.getEntry("privateKeyAlias", protParam);
* PrivateKey myPrivateKey = pkEntry.getPrivateKey(); * PrivateKey myPrivateKey = pkEntry.getPrivateKey();
* *
* // save my secret key * // save my secret key
* javax.crypto.SecretKey mySecretKey; * javax.crypto.SecretKey mySecretKey;
* KeyStore.SecretKeyEntry skEntry = * KeyStore.SecretKeyEntry skEntry =
* new KeyStore.SecretKeyEntry(mySecretKey); * new KeyStore.SecretKeyEntry(mySecretKey);
* ks.setEntry("secretKeyAlias", skEntry, * ks.setEntry("secretKeyAlias", skEntry, protParam);
* new KeyStore.PasswordProtection(password));
* *
* // store away the keystore * // store away the keystore
* java.io.FileOutputStream fos = null; * java.io.FileOutputStream fos = null;
......
...@@ -103,27 +103,46 @@ public class Date extends java.util.Date { ...@@ -103,27 +103,46 @@ public class Date extends java.util.Date {
* JDBC date escape format (yyyy-mm-dd) * JDBC date escape format (yyyy-mm-dd)
*/ */
public static Date valueOf(String s) { public static Date valueOf(String s) {
int year; final int YEAR_LENGTH = 4;
int month; final int MONTH_LENGTH = 2;
int day; final int DAY_LENGTH = 2;
final int MAX_MONTH = 12;
final int MAX_DAY = 31;
int firstDash; int firstDash;
int secondDash; int secondDash;
Date d = null;
if (s == null) throw new java.lang.IllegalArgumentException(); if (s == null) {
throw new java.lang.IllegalArgumentException();
}
firstDash = s.indexOf('-'); firstDash = s.indexOf('-');
secondDash = s.indexOf('-', firstDash+1); secondDash = s.indexOf('-', firstDash + 1);
if ((firstDash > 0) & (secondDash > 0) & (secondDash < s.length()-1)) {
year = Integer.parseInt(s.substring(0, firstDash)) - 1900; if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
month = Integer.parseInt(s.substring(firstDash+1, secondDash)) - 1; String yyyy = s.substring(0, firstDash);
day = Integer.parseInt(s.substring(secondDash+1)); String mm = s.substring(firstDash + 1, secondDash);
} else { String dd = s.substring(secondDash + 1);
if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH &&
dd.length() == DAY_LENGTH) {
int year = Integer.parseInt(yyyy);
int month = Integer.parseInt(mm);
int day = Integer.parseInt(dd);
if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
d = new Date(year - 1900, month - 1, day);
}
}
}
if (d == null) {
throw new java.lang.IllegalArgumentException(); throw new java.lang.IllegalArgumentException();
} }
return new Date(year, month, day); return d;
} }
/** /**
* Formats a date in the date escape format yyyy-mm-dd. * Formats a date in the date escape format yyyy-mm-dd.
* <P> * <P>
......
...@@ -59,7 +59,7 @@ public class FileURLConnection extends URLConnection { ...@@ -59,7 +59,7 @@ public class FileURLConnection extends URLConnection {
String filename; String filename;
boolean isDirectory = false; boolean isDirectory = false;
boolean exists = false; boolean exists = false;
List files; List<String> files;
long length = -1; long length = -1;
long lastModified = 0; long lastModified = 0;
...@@ -81,7 +81,10 @@ public class FileURLConnection extends URLConnection { ...@@ -81,7 +81,10 @@ public class FileURLConnection extends URLConnection {
filename = file.toString(); filename = file.toString();
isDirectory = file.isDirectory(); isDirectory = file.isDirectory();
if (isDirectory) { if (isDirectory) {
files = (List) Arrays.asList(file.list()); String[] fileList = file.list();
if (fileList == null)
throw new FileNotFoundException(filename + " exists, but is not accessible");
files = Arrays.<String>asList(fileList);
} else { } else {
is = new BufferedInputStream(new FileInputStream(filename)); is = new BufferedInputStream(new FileInputStream(filename));
...@@ -197,7 +200,7 @@ public class FileURLConnection extends URLConnection { ...@@ -197,7 +200,7 @@ public class FileURLConnection extends URLConnection {
Collections.sort(files, Collator.getInstance()); Collections.sort(files, Collator.getInstance());
for (int i = 0 ; i < files.size() ; i++) { for (int i = 0 ; i < files.size() ; i++) {
String fileName = (String)files.get(i); String fileName = files.get(i);
buf.append(fileName); buf.append(fileName);
buf.append("\n"); buf.append("\n");
} }
......
...@@ -1768,6 +1768,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection { ...@@ -1768,6 +1768,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
// Not really necessary for a tunnel, but can't hurt // Not really necessary for a tunnel, but can't hurt
requests.setIfNotSet("Accept", acceptString); requests.setIfNotSet("Accept", acceptString);
if (http.getHttpKeepAliveSet()) {
requests.setIfNotSet("Proxy-Connection", "keep-alive");
}
setPreemptiveProxyAuthentication(requests); setPreemptiveProxyAuthentication(requests);
/* Log the CONNECT request */ /* Log the CONNECT request */
......
...@@ -536,9 +536,11 @@ class DatagramChannelImpl ...@@ -536,9 +536,11 @@ class DatagramChannelImpl
} }
} }
private long read0(ByteBuffer[] bufs) throws IOException { public long read(ByteBuffer[] dsts, int offset, int length)
if (bufs == null) throws IOException
throw new NullPointerException(); {
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
synchronized (readLock) { synchronized (readLock) {
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpen();
...@@ -552,7 +554,7 @@ class DatagramChannelImpl ...@@ -552,7 +554,7 @@ class DatagramChannelImpl
return 0; return 0;
readerThread = NativeThread.current(); readerThread = NativeThread.current();
do { do {
n = IOUtil.read(fd, bufs, nd); n = IOUtil.read(fd, dsts, offset, length, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n); return IOStatus.normalize(n);
} finally { } finally {
...@@ -563,15 +565,6 @@ class DatagramChannelImpl ...@@ -563,15 +565,6 @@ class DatagramChannelImpl
} }
} }
public long read(ByteBuffer[] dsts, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
// ## Fix IOUtil.write so that we can avoid this array copy
return read0(Util.subsequence(dsts, offset, length));
}
public int write(ByteBuffer buf) throws IOException { public int write(ByteBuffer buf) throws IOException {
if (buf == null) if (buf == null)
throw new NullPointerException(); throw new NullPointerException();
...@@ -599,9 +592,11 @@ class DatagramChannelImpl ...@@ -599,9 +592,11 @@ class DatagramChannelImpl
} }
} }
private long write0(ByteBuffer[] bufs) throws IOException { public long write(ByteBuffer[] srcs, int offset, int length)
if (bufs == null) throws IOException
throw new NullPointerException(); {
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
synchronized (writeLock) { synchronized (writeLock) {
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpen();
...@@ -615,7 +610,7 @@ class DatagramChannelImpl ...@@ -615,7 +610,7 @@ class DatagramChannelImpl
return 0; return 0;
writerThread = NativeThread.current(); writerThread = NativeThread.current();
do { do {
n = IOUtil.write(fd, bufs, nd); n = IOUtil.write(fd, srcs, offset, length, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n); return IOStatus.normalize(n);
} finally { } finally {
...@@ -626,15 +621,6 @@ class DatagramChannelImpl ...@@ -626,15 +621,6 @@ class DatagramChannelImpl
} }
} }
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
// ## Fix IOUtil.write so that we can avoid this array copy
return write0(Util.subsequence(srcs, offset, length));
}
protected void implConfigureBlocking(boolean block) throws IOException { protected void implConfigureBlocking(boolean block) throws IOException {
IOUtil.configureBlocking(fd, block); IOUtil.configureBlocking(fd, block);
} }
......
...@@ -143,7 +143,11 @@ public class FileChannelImpl ...@@ -143,7 +143,11 @@ public class FileChannelImpl
} }
} }
private long read0(ByteBuffer[] dsts) throws IOException { public long read(ByteBuffer[] dsts, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
ensureOpen(); ensureOpen();
if (!readable) if (!readable)
throw new NonReadableChannelException(); throw new NonReadableChannelException();
...@@ -156,7 +160,7 @@ public class FileChannelImpl ...@@ -156,7 +160,7 @@ public class FileChannelImpl
if (!isOpen()) if (!isOpen())
return 0; return 0;
do { do {
n = IOUtil.read(fd, dsts, nd); n = IOUtil.read(fd, dsts, offset, length, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n); return IOStatus.normalize(n);
} finally { } finally {
...@@ -167,15 +171,6 @@ public class FileChannelImpl ...@@ -167,15 +171,6 @@ public class FileChannelImpl
} }
} }
public long read(ByteBuffer[] dsts, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
// ## Fix IOUtil.write so that we can avoid this array copy
return read0(Util.subsequence(dsts, offset, length));
}
public int write(ByteBuffer src) throws IOException { public int write(ByteBuffer src) throws IOException {
ensureOpen(); ensureOpen();
if (!writable) if (!writable)
...@@ -200,7 +195,11 @@ public class FileChannelImpl ...@@ -200,7 +195,11 @@ public class FileChannelImpl
} }
} }
private long write0(ByteBuffer[] srcs) throws IOException { public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
ensureOpen(); ensureOpen();
if (!writable) if (!writable)
throw new NonWritableChannelException(); throw new NonWritableChannelException();
...@@ -213,7 +212,7 @@ public class FileChannelImpl ...@@ -213,7 +212,7 @@ public class FileChannelImpl
if (!isOpen()) if (!isOpen())
return 0; return 0;
do { do {
n = IOUtil.write(fd, srcs, nd); n = IOUtil.write(fd, srcs, offset, length, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n); return IOStatus.normalize(n);
} finally { } finally {
...@@ -224,16 +223,6 @@ public class FileChannelImpl ...@@ -224,16 +223,6 @@ public class FileChannelImpl
} }
} }
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
// ## Fix IOUtil.write so that we can avoid this array copy
return write0(Util.subsequence(srcs, offset, length));
}
// -- Other operations -- // -- Other operations --
public long position() throws IOException { public long position() throws IOException {
...@@ -440,24 +429,45 @@ public class FileChannelImpl ...@@ -440,24 +429,45 @@ public class FileChannelImpl
} }
} }
private long transferToTrustedChannel(long position, int icount, // Maximum size to map when using a mapped buffer
private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L;
private long transferToTrustedChannel(long position, long count,
WritableByteChannel target) WritableByteChannel target)
throws IOException throws IOException
{ {
if ( !((target instanceof FileChannelImpl) boolean isSelChImpl = (target instanceof SelChImpl);
|| (target instanceof SelChImpl))) if (!((target instanceof FileChannelImpl) || isSelChImpl))
return IOStatus.UNSUPPORTED; return IOStatus.UNSUPPORTED;
// Trusted target: Use a mapped buffer // Trusted target: Use a mapped buffer
MappedByteBuffer dbb = null; long remaining = count;
try { while (remaining > 0L) {
dbb = map(MapMode.READ_ONLY, position, icount); long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
// ## Bug: Closing this channel will not terminate the write try {
return target.write(dbb); MappedByteBuffer dbb = map(MapMode.READ_ONLY, position, size);
} finally { try {
if (dbb != null) // ## Bug: Closing this channel will not terminate the write
unmap(dbb); int n = target.write(dbb);
assert n >= 0;
remaining -= n;
if (isSelChImpl) {
// one attempt to write to selectable channel
break;
}
assert n > 0;
position += n;
} finally {
unmap(dbb);
}
} catch (IOException ioe) {
// Only throw exception if no bytes have been written
if (remaining == count)
throw ioe;
break;
}
} }
return count - remaining;
} }
private long transferToArbitraryChannel(long position, int icount, private long transferToArbitraryChannel(long position, int icount,
...@@ -535,20 +545,34 @@ public class FileChannelImpl ...@@ -535,20 +545,34 @@ public class FileChannelImpl
long position, long count) long position, long count)
throws IOException throws IOException
{ {
// Note we could loop here to accumulate more at once
synchronized (src.positionLock) { synchronized (src.positionLock) {
long p = src.position(); long pos = src.position();
int icount = (int)Math.min(Math.min(count, Integer.MAX_VALUE), long max = Math.min(count, src.size() - pos);
src.size() - p);
// ## Bug: Closing this channel will not terminate the write long remaining = max;
MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, icount); long p = pos;
try { while (remaining > 0L) {
long n = write(bb, position); long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
src.position(p + n); // ## Bug: Closing this channel will not terminate the write
return n; MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, size);
} finally { try {
unmap(bb); long n = write(bb, position);
assert n > 0;
p += n;
position += n;
remaining -= n;
} catch (IOException ioe) {
// Only throw exception if no bytes have been written
if (remaining == max)
throw ioe;
break;
} finally {
unmap(bb);
}
} }
long nwritten = max - remaining;
src.position(pos + nwritten);
return nwritten;
} }
} }
......
...@@ -38,34 +38,6 @@ class IOUtil { ...@@ -38,34 +38,6 @@ class IOUtil {
private IOUtil() { } // No instantiation private IOUtil() { } // No instantiation
/*
* Returns the index of first buffer in bufs with remaining,
* or -1 if there is nothing left
*/
private static int remaining(ByteBuffer[] bufs) {
int numBufs = bufs.length;
for (int i=0; i<numBufs; i++) {
if (bufs[i].hasRemaining()) {
return i;
}
}
return -1;
}
/*
* Returns a new ByteBuffer array with only unfinished buffers in it
*/
private static ByteBuffer[] skipBufs(ByteBuffer[] bufs,
int nextWithRemaining)
{
int newSize = bufs.length - nextWithRemaining;
ByteBuffer[] temp = new ByteBuffer[newSize];
for (int i=0; i<newSize; i++) {
temp[i] = bufs[i + nextWithRemaining];
}
return temp;
}
static int write(FileDescriptor fd, ByteBuffer src, long position, static int write(FileDescriptor fd, ByteBuffer src, long position,
NativeDispatcher nd, Object lock) NativeDispatcher nd, Object lock)
throws IOException throws IOException
...@@ -93,7 +65,7 @@ class IOUtil { ...@@ -93,7 +65,7 @@ class IOUtil {
} }
return n; return n;
} finally { } finally {
Util.releaseTemporaryDirectBuffer(bb); Util.offerFirstTemporaryDirectBuffer(bb);
} }
} }
...@@ -125,88 +97,81 @@ class IOUtil { ...@@ -125,88 +97,81 @@ class IOUtil {
static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
throws IOException throws IOException
{ {
int nextWithRemaining = remaining(bufs); return write(fd, bufs, 0, bufs.length, nd);
// if all bufs are empty we should return immediately }
if (nextWithRemaining < 0)
return 0;
// If some bufs are empty we should skip them
if (nextWithRemaining > 0)
bufs = skipBufs(bufs, nextWithRemaining);
int numBufs = bufs.length; static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
NativeDispatcher nd)
throws IOException
{
IOVecWrapper vec = IOVecWrapper.get(length);
// Create shadow to ensure DirectByteBuffers are used boolean completed = false;
ByteBuffer[] shadow = new ByteBuffer[numBufs]; int iov_len = 0;
try { try {
for (int i=0; i<numBufs; i++) {
if (!(bufs[i] instanceof DirectBuffer)) {
int pos = bufs[i].position();
int lim = bufs[i].limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
shadow[i] = bb;
// Leave slow buffer position untouched; it will be updated
// after we see how many bytes were really written out
bb.put(bufs[i]);
bufs[i].position(pos);
bb.flip();
} else {
shadow[i] = bufs[i];
}
}
IOVecWrapper vec = null; // Iterate over buffers to populate native iovec array.
long bytesWritten = 0; int count = offset + length;
try { for (int i=offset; i<count; i++) {
// Create a native iovec array ByteBuffer buf = bufs[i];
vec= new IOVecWrapper(numBufs); int pos = buf.position();
int lim = buf.limit();
// Fill in the iovec array with appropriate data assert (pos <= lim);
for (int i=0; i<numBufs; i++) { int rem = (pos <= lim ? lim - pos : 0);
ByteBuffer nextBuffer = shadow[i]; if (rem > 0) {
// put in the buffer addresses vec.setBuffer(iov_len, buf, pos, rem);
long pos = nextBuffer.position();
long len = nextBuffer.limit() - pos; // allocate shadow buffer to ensure I/O is done with direct buffer
vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos); if (!(buf instanceof DirectBuffer)) {
vec.putLen(i, len); ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
} shadow.put(buf);
shadow.flip();
vec.setShadow(iov_len, shadow);
buf.position(pos); // temporarily restore position in user buffer
buf = shadow;
pos = shadow.position();
}
// Invoke native call to fill the buffers vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
bytesWritten = nd.writev(fd, vec.address, numBufs); vec.putLen(iov_len, rem);
} finally { iov_len++;
vec.free(); }
} }
long returnVal = bytesWritten; if (iov_len == 0)
return 0L;
long bytesWritten = nd.writev(fd, vec.address, iov_len);
// Notify the buffers how many bytes were taken // Notify the buffers how many bytes were taken
for (int i=0; i<numBufs; i++) { long left = bytesWritten;
ByteBuffer nextBuffer = bufs[i]; for (int j=0; j<iov_len; j++) {
int pos = nextBuffer.position(); if (left > 0) {
int lim = nextBuffer.limit(); ByteBuffer buf = vec.getBuffer(j);
assert (pos <= lim); int pos = vec.getPosition(j);
int len = (pos <= lim ? lim - pos : lim); int rem = vec.getRemaining(j);
if (bytesWritten >= len) { int n = (left > rem) ? rem : (int)left;
bytesWritten -= len; buf.position(pos + n);
int newPosition = pos + len; left -= n;
nextBuffer.position(newPosition);
} else { // Buffers not completely filled
if (bytesWritten > 0) {
assert(pos + bytesWritten < (long)Integer.MAX_VALUE);
int newPosition = (int)(pos + bytesWritten);
nextBuffer.position(newPosition);
}
break;
} }
// return shadow buffers to buffer pool
ByteBuffer shadow = vec.getShadow(j);
if (shadow != null)
Util.offerLastTemporaryDirectBuffer(shadow);
vec.clearRefs(j);
} }
return returnVal;
completed = true;
return bytesWritten;
} finally { } finally {
// return any substituted buffers to cache // if an error occurred then clear refs to buffers and return any shadow
for (int i=0; i<numBufs; i++) { // buffers to cache
ByteBuffer bb = shadow[i]; if (!completed) {
if (bb != null && bb != bufs[i]) { for (int j=0; j<iov_len; j++) {
Util.releaseTemporaryDirectBuffer(bb); ByteBuffer shadow = vec.getShadow(j);
if (shadow != null)
Util.offerLastTemporaryDirectBuffer(shadow);
vec.clearRefs(j);
} }
} }
} }
...@@ -231,7 +196,7 @@ class IOUtil { ...@@ -231,7 +196,7 @@ class IOUtil {
dst.put(bb); dst.put(bb);
return n; return n;
} finally { } finally {
Util.releaseTemporaryDirectBuffer(bb); Util.offerFirstTemporaryDirectBuffer(bb);
} }
} }
...@@ -262,92 +227,85 @@ class IOUtil { ...@@ -262,92 +227,85 @@ class IOUtil {
static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
throws IOException throws IOException
{ {
int nextWithRemaining = remaining(bufs); return read(fd, bufs, 0, bufs.length, nd);
// if all bufs are empty we should return immediately }
if (nextWithRemaining < 0)
return 0;
// If some bufs are empty we should skip them
if (nextWithRemaining > 0)
bufs = skipBufs(bufs, nextWithRemaining);
int numBufs = bufs.length; static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
NativeDispatcher nd)
throws IOException
{
IOVecWrapper vec = IOVecWrapper.get(length);
// Read into the shadow to ensure DirectByteBuffers are used boolean completed = false;
ByteBuffer[] shadow = new ByteBuffer[numBufs]; int iov_len = 0;
boolean usingSlowBuffers = false;
try { try {
for (int i=0; i<numBufs; i++) {
if (bufs[i].isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (!(bufs[i] instanceof DirectBuffer)) {
shadow[i] = Util.getTemporaryDirectBuffer(bufs[i].remaining());
usingSlowBuffers = true;
} else {
shadow[i] = bufs[i];
}
}
IOVecWrapper vec = null; // Iterate over buffers to populate native iovec array.
long bytesRead = 0; int count = offset + length;
try { for (int i=offset; i<count; i++) {
// Create a native iovec array ByteBuffer buf = bufs[i];
vec = new IOVecWrapper(numBufs); if (buf.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
// Fill in the iovec array with appropriate data int pos = buf.position();
for (int i=0; i<numBufs; i++) { int lim = buf.limit();
ByteBuffer nextBuffer = shadow[i]; assert (pos <= lim);
// put in the buffer addresses int rem = (pos <= lim ? lim - pos : 0);
long pos = nextBuffer.position();
long len = nextBuffer.remaining();
vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
vec.putLen(i, len);
}
// Invoke native call to fill the buffers if (rem > 0) {
bytesRead = nd.readv(fd, vec.address, numBufs); vec.setBuffer(iov_len, buf, pos, rem);
} finally {
vec.free();
}
long returnVal = bytesRead;
// Notify the buffers how many bytes were read // allocate shadow buffer to ensure I/O is done with direct buffer
for (int i=0; i<numBufs; i++) { if (!(buf instanceof DirectBuffer)) {
ByteBuffer nextBuffer = shadow[i]; ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
// Note: should this have been cached from above? vec.setShadow(iov_len, shadow);
int pos = nextBuffer.position(); buf = shadow;
int len = nextBuffer.remaining(); pos = shadow.position();
if (bytesRead >= len) {
bytesRead -= len;
int newPosition = pos + len;
nextBuffer.position(newPosition);
} else { // Buffers not completely filled
if (bytesRead > 0) {
assert(pos + bytesRead < (long)Integer.MAX_VALUE);
int newPosition = (int)(pos + bytesRead);
nextBuffer.position(newPosition);
} }
break;
vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
vec.putLen(iov_len, rem);
iov_len++;
} }
} }
if (iov_len == 0)
return 0L;
// Put results from shadow into the slow buffers long bytesRead = nd.readv(fd, vec.address, iov_len);
if (usingSlowBuffers) {
for (int i=0; i<numBufs; i++) { // Notify the buffers how many bytes were read
if (!(bufs[i] instanceof DirectBuffer)) { long left = bytesRead;
shadow[i].flip(); for (int j=0; j<iov_len; j++) {
bufs[i].put(shadow[i]); ByteBuffer shadow = vec.getShadow(j);
if (left > 0) {
ByteBuffer buf = vec.getBuffer(j);
int rem = vec.getRemaining(j);
int n = (left > rem) ? rem : (int)left;
if (shadow == null) {
int pos = vec.getPosition(j);
buf.position(pos + n);
} else {
shadow.limit(shadow.position() + n);
buf.put(shadow);
} }
left -= n;
} }
if (shadow != null)
Util.offerLastTemporaryDirectBuffer(shadow);
vec.clearRefs(j);
} }
return returnVal;
completed = true;
return bytesRead;
} finally { } finally {
// return any substituted buffers to cache // if an error occurred then clear refs to buffers and return any shadow
if (usingSlowBuffers) { // buffers to cache
for (int i=0; i<numBufs; i++) { if (!completed) {
ByteBuffer bb = shadow[i]; for (int j=0; j<iov_len; j++) {
if (bb != null && bb != bufs[i]) { ByteBuffer shadow = vec.getShadow(j);
Util.releaseTemporaryDirectBuffer(bb); if (shadow != null)
} Util.offerLastTemporaryDirectBuffer(shadow);
vec.clearRefs(j);
} }
} }
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package sun.nio.ch; package sun.nio.ch;
import java.nio.ByteBuffer;
import sun.misc.*; import sun.misc.*;
...@@ -43,23 +44,98 @@ import sun.misc.*; ...@@ -43,23 +44,98 @@ import sun.misc.*;
class IOVecWrapper { class IOVecWrapper {
// Miscellaneous constants // Miscellaneous constants
static int BASE_OFFSET = 0; private static final int BASE_OFFSET = 0;
static int LEN_OFFSET; private static final int LEN_OFFSET;
static int SIZE_IOVEC; private static final int SIZE_IOVEC;
// The iovec array // The iovec array
private AllocatedNativeObject vecArray; private final AllocatedNativeObject vecArray;
// Number of elements in iovec array
private final int size;
// Buffers and position/remaining corresponding to elements in iovec array
private final ByteBuffer[] buf;
private final int[] position;
private final int[] remaining;
// Shadow buffers for cases when original buffer is substituted
private final ByteBuffer[] shadow;
// Base address of this array // Base address of this array
long address; final long address;
// Address size in bytes // Address size in bytes
static int addressSize; static int addressSize;
IOVecWrapper(int newSize) { private static class Deallocator implements Runnable {
newSize = (newSize + 1) * SIZE_IOVEC; private final AllocatedNativeObject obj;
vecArray = new AllocatedNativeObject(newSize, false); Deallocator(AllocatedNativeObject obj) {
address = vecArray.address(); this.obj = obj;
}
public void run() {
obj.free();
}
}
// per thread IOVecWrapper
private static final ThreadLocal<IOVecWrapper> cached =
new ThreadLocal<IOVecWrapper>();
private IOVecWrapper(int size) {
this.size = size;
this.buf = new ByteBuffer[size];
this.position = new int[size];
this.remaining = new int[size];
this.shadow = new ByteBuffer[size];
this.vecArray = new AllocatedNativeObject(size * SIZE_IOVEC, false);
this.address = vecArray.address();
}
static IOVecWrapper get(int size) {
IOVecWrapper wrapper = cached.get();
if (wrapper != null && wrapper.size < size) {
// not big enough; eagerly release memory
wrapper.vecArray.free();
wrapper = null;
}
if (wrapper == null) {
wrapper = new IOVecWrapper(size);
Cleaner.create(wrapper, new Deallocator(wrapper.vecArray));
cached.set(wrapper);
}
return wrapper;
}
void setBuffer(int i, ByteBuffer buf, int pos, int rem) {
this.buf[i] = buf;
this.position[i] = pos;
this.remaining[i] = rem;
}
void setShadow(int i, ByteBuffer buf) {
shadow[i] = buf;
}
ByteBuffer getBuffer(int i) {
return buf[i];
}
int getPosition(int i) {
return position[i];
}
int getRemaining(int i) {
return remaining[i];
}
ByteBuffer getShadow(int i) {
return shadow[i];
}
void clearRefs(int i) {
buf[i] = null;
shadow[i] = null;
} }
void putBase(int i, long base) { void putBase(int i, long base) {
...@@ -78,10 +154,6 @@ class IOVecWrapper { ...@@ -78,10 +154,6 @@ class IOVecWrapper {
vecArray.putLong(offset, len); vecArray.putLong(offset, len);
} }
void free() {
vecArray.free();
}
static { static {
addressSize = Util.unsafe().addressSize(); addressSize = Util.unsafe().addressSize();
LEN_OFFSET = addressSize; LEN_OFFSET = addressSize;
......
...@@ -385,9 +385,11 @@ class SocketChannelImpl ...@@ -385,9 +385,11 @@ class SocketChannelImpl
} }
} }
private long read0(ByteBuffer[] bufs) throws IOException { public long read(ByteBuffer[] dsts, int offset, int length)
if (bufs == null) throws IOException
throw new NullPointerException(); {
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
synchronized (readLock) { synchronized (readLock) {
if (!ensureReadOpen()) if (!ensureReadOpen())
return -1; return -1;
...@@ -401,7 +403,7 @@ class SocketChannelImpl ...@@ -401,7 +403,7 @@ class SocketChannelImpl
} }
for (;;) { for (;;) {
n = IOUtil.read(fd, bufs, nd); n = IOUtil.read(fd, dsts, offset, length, nd);
if ((n == IOStatus.INTERRUPTED) && isOpen()) if ((n == IOStatus.INTERRUPTED) && isOpen())
continue; continue;
return IOStatus.normalize(n); return IOStatus.normalize(n);
...@@ -418,15 +420,6 @@ class SocketChannelImpl ...@@ -418,15 +420,6 @@ class SocketChannelImpl
} }
} }
public long read(ByteBuffer[] dsts, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
// ## Fix IOUtil.write so that we can avoid this array copy
return read0(Util.subsequence(dsts, offset, length));
}
public int write(ByteBuffer buf) throws IOException { public int write(ByteBuffer buf) throws IOException {
if (buf == null) if (buf == null)
throw new NullPointerException(); throw new NullPointerException();
...@@ -458,9 +451,11 @@ class SocketChannelImpl ...@@ -458,9 +451,11 @@ class SocketChannelImpl
} }
} }
public long write0(ByteBuffer[] bufs) throws IOException { public long write(ByteBuffer[] srcs, int offset, int length)
if (bufs == null) throws IOException
throw new NullPointerException(); {
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
synchronized (writeLock) { synchronized (writeLock) {
ensureWriteOpen(); ensureWriteOpen();
long n = 0; long n = 0;
...@@ -472,7 +467,7 @@ class SocketChannelImpl ...@@ -472,7 +467,7 @@ class SocketChannelImpl
writerThread = NativeThread.current(); writerThread = NativeThread.current();
} }
for (;;) { for (;;) {
n = IOUtil.write(fd, bufs, nd); n = IOUtil.write(fd, srcs, offset, length, nd);
if ((n == IOStatus.INTERRUPTED) && isOpen()) if ((n == IOStatus.INTERRUPTED) && isOpen())
continue; continue;
return IOStatus.normalize(n); return IOStatus.normalize(n);
...@@ -489,15 +484,6 @@ class SocketChannelImpl ...@@ -489,15 +484,6 @@ class SocketChannelImpl
} }
} }
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
// ## Fix IOUtil.write so that we can avoid this array copy
return write0(Util.subsequence(srcs, offset, length));
}
// package-private // package-private
int sendOutOfBandData(byte b) throws IOException { int sendOutOfBandData(byte b) throws IOException {
synchronized (writeLock) { synchronized (writeLock) {
......
...@@ -41,67 +41,180 @@ import sun.security.action.GetPropertyAction; ...@@ -41,67 +41,180 @@ import sun.security.action.GetPropertyAction;
class Util { class Util {
// -- Caches -- // -- Caches --
// The number of temp buffers in our pool // The number of temp buffers in our pool
private static final int TEMP_BUF_POOL_SIZE = 3; private static final int TEMP_BUF_POOL_SIZE = 8;
// Per-thread soft cache of the last temporary direct buffer // Per-thread cache of temporary direct buffers
private static ThreadLocal<SoftReference<ByteBuffer>>[] bufferPool; private static ThreadLocal<BufferCache> bufferCache =
new ThreadLocal<BufferCache>()
{
@Override
protected BufferCache initialValue() {
return new BufferCache();
}
};
@SuppressWarnings("unchecked") /**
static ThreadLocal<SoftReference<ByteBuffer>>[] createThreadLocalBufferPool() { * A simple cache of direct buffers.
return new ThreadLocal[TEMP_BUF_POOL_SIZE]; */
} private static class BufferCache {
// the array of buffers
private ByteBuffer[] buffers;
// the number of buffers in the cache
private int count;
// the index of the first valid buffer (undefined if count == 0)
private int start;
private int next(int i) {
return (i + 1) % TEMP_BUF_POOL_SIZE;
}
BufferCache() {
buffers = new ByteBuffer[TEMP_BUF_POOL_SIZE];
}
static { /**
bufferPool = createThreadLocalBufferPool(); * Removes and returns a buffer from the cache of at least the given
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) * size (or null if no suitable buffer is found).
bufferPool[i] = new ThreadLocal<SoftReference<ByteBuffer>>(); */
ByteBuffer get(int size) {
if (count == 0)
return null; // cache is empty
ByteBuffer[] buffers = this.buffers;
// search for suitable buffer (often the first buffer will do)
ByteBuffer buf = buffers[start];
if (buf.capacity() < size) {
buf = null;
int i = start;
while ((i = next(i)) != start) {
ByteBuffer bb = buffers[i];
if (bb == null)
break;
if (bb.capacity() >= size) {
buf = bb;
break;
}
}
if (buf == null)
return null;
// move first element to here to avoid re-packing
buffers[i] = buffers[start];
}
// remove first element
buffers[start] = null;
start = next(start);
count--;
// prepare the buffer and return it
buf.rewind();
buf.limit(size);
return buf;
}
boolean offerFirst(ByteBuffer buf) {
if (count >= TEMP_BUF_POOL_SIZE) {
return false;
} else {
start = (start + TEMP_BUF_POOL_SIZE - 1) % TEMP_BUF_POOL_SIZE;
buffers[start] = buf;
count++;
return true;
}
}
boolean offerLast(ByteBuffer buf) {
if (count >= TEMP_BUF_POOL_SIZE) {
return false;
} else {
int next = (start + count) % TEMP_BUF_POOL_SIZE;
buffers[next] = buf;
count++;
return true;
}
}
boolean isEmpty() {
return count == 0;
}
ByteBuffer removeFirst() {
assert count > 0;
ByteBuffer buf = buffers[start];
buffers[start] = null;
start = next(start);
count--;
return buf;
}
} }
/**
* Returns a temporary buffer of at least the given size
*/
static ByteBuffer getTemporaryDirectBuffer(int size) { static ByteBuffer getTemporaryDirectBuffer(int size) {
ByteBuffer buf = null; BufferCache cache = bufferCache.get();
// Grab a buffer if available ByteBuffer buf = cache.get(size);
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { if (buf != null) {
SoftReference<ByteBuffer> ref = bufferPool[i].get(); return buf;
if ((ref != null) && ((buf = ref.get()) != null) && } else {
(buf.capacity() >= size)) { // No suitable buffer in the cache so we need to allocate a new
buf.rewind(); // one. To avoid the cache growing then we remove the first
buf.limit(size); // buffer from the cache and free it.
bufferPool[i].set(null); if (!cache.isEmpty()) {
return buf; buf = cache.removeFirst();
free(buf);
} }
return ByteBuffer.allocateDirect(size);
} }
// Make a new one
return ByteBuffer.allocateDirect(size);
} }
/**
* Releases a temporary buffer by returning to the cache or freeing it.
*/
static void releaseTemporaryDirectBuffer(ByteBuffer buf) { static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
if (buf == null) offerFirstTemporaryDirectBuffer(buf);
return; }
// Put it in an empty slot if such exists
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { /**
SoftReference<ByteBuffer> ref = bufferPool[i].get(); * Releases a temporary buffer by returning to the cache or freeing it. If
if ((ref == null) || (ref.get() == null)) { * returning to the cache then insert it at the start so that it is
bufferPool[i].set(new SoftReference<ByteBuffer>(buf)); * likely to be returned by a subsequent call to getTemporaryDirectBuffer.
return; */
} static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
assert buf != null;
BufferCache cache = bufferCache.get();
if (!cache.offerFirst(buf)) {
// cache is full
free(buf);
} }
// Otherwise replace a smaller one in the cache if such exists }
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
SoftReference<ByteBuffer> ref = bufferPool[i].get(); /**
ByteBuffer inCacheBuf = ref.get(); * Releases a temporary buffer by returning to the cache or freeing it. If
if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) { * returning to the cache then insert it at the end. This makes it
bufferPool[i].set(new SoftReference<ByteBuffer>(buf)); * suitable for scatter/gather operations where the buffers are returned to
return; * cache in same order that they were obtained.
} */
static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
assert buf != null;
BufferCache cache = bufferCache.get();
if (!cache.offerLast(buf)) {
// cache is full
free(buf);
} }
}
// release memory /**
((DirectBuffer)buf).cleaner().clean(); * Frees the memory for the given direct buffer
*/
private static void free(ByteBuffer buf) {
((DirectBuffer)buf).cleaner().clean();
} }
private static class SelectorWrapper { private static class SelectorWrapper {
......
...@@ -260,3 +260,30 @@ networkaddress.cache.negative.ttl=10 ...@@ -260,3 +260,30 @@ networkaddress.cache.negative.ttl=10
# Example, # Example,
# ocsp.responderCertSerialNumber=2A:FF:00 # ocsp.responderCertSerialNumber=2A:FF:00
#
# Policy for failed Kerberos KDC lookups:
#
# When a KDC is unavailable (network error, service failure, etc), it is
# put inside a blacklist and accessed less often for future requests. The
# value (case-insensitive) for this policy can be:
#
# tryLast
# KDCs in the blacklist are always tried after those not on the list.
#
# tryLess[:max_retries,timeout]
# KDCs in the blacklist are still tried by their order in the configuration,
# but with smaller max_retries and timeout values. max_retries and timeout
# are optional numerical parameters (default 1 and 5000, which means once
# and 5 seconds). Please notes that if any of the values defined here is
# more than what is defined in krb5.conf, it will be ignored.
#
# Whenever a KDC is detected as available, it is removed from the blacklist.
# The blacklist is reset when krb5.conf is reloaded. You can add
# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
# reloaded whenever a JAAS authentication is attempted.
#
# Example,
# krb5.kdc.bad.policy = tryLast
# krb5.kdc.bad.policy = tryLess:2,2000
krb5.kdc.bad.policy = tryLast
...@@ -260,3 +260,30 @@ networkaddress.cache.negative.ttl=10 ...@@ -260,3 +260,30 @@ networkaddress.cache.negative.ttl=10
# Example, # Example,
# ocsp.responderCertSerialNumber=2A:FF:00 # ocsp.responderCertSerialNumber=2A:FF:00
#
# Policy for failed Kerberos KDC lookups:
#
# When a KDC is unavailable (network error, service failure, etc), it is
# put inside a blacklist and accessed less often for future requests. The
# value (case-insensitive) for this policy can be:
#
# tryLast
# KDCs in the blacklist are always tried after those not on the list.
#
# tryLess[:max_retries,timeout]
# KDCs in the blacklist are still tried by their order in the configuration,
# but with smaller max_retries and timeout values. max_retries and timeout
# are optional numerical parameters (default 1 and 5000, which means once
# and 5 seconds). Please notes that if any of the values defined here is
# more than what is defined in krb5.conf, it will be ignored.
#
# Whenever a KDC is detected as available, it is removed from the blacklist.
# The blacklist is reset when krb5.conf is reloaded. You can add
# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
# reloaded whenever a JAAS authentication is attempted.
#
# Example,
# krb5.kdc.bad.policy = tryLast
# krb5.kdc.bad.policy = tryLess:2,2000
krb5.kdc.bad.policy = tryLast
...@@ -2730,7 +2730,10 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta ...@@ -2730,7 +2730,10 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta
operand); operand);
const char *result_signature; const char *result_signature;
check_and_push(context, signature, VM_STRING_UTF); check_and_push(context, signature, VM_STRING_UTF);
result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC) + 1; result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC);
if (result_signature++ == NULL) {
CCerror(context, "Illegal signature %s", signature);
}
if (result_signature[0] == JVM_SIGNATURE_VOID) { if (result_signature[0] == JVM_SIGNATURE_VOID) {
stack_results = ""; stack_results = "";
} else { } else {
...@@ -3654,14 +3657,13 @@ signature_to_fieldtype(context_type *context, ...@@ -3654,14 +3657,13 @@ signature_to_fieldtype(context_type *context,
const char **signature_p, fullinfo_type *full_info_p) const char **signature_p, fullinfo_type *full_info_p)
{ {
const char *p = *signature_p; const char *p = *signature_p;
fullinfo_type full_info = MAKE_FULLINFO(0, 0, 0); fullinfo_type full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
char result; char result;
int array_depth = 0; int array_depth = 0;
for (;;) { for (;;) {
switch(*p++) { switch(*p++) {
default: default:
full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
result = 0; result = 0;
break; break;
...@@ -3714,7 +3716,14 @@ signature_to_fieldtype(context_type *context, ...@@ -3714,7 +3716,14 @@ signature_to_fieldtype(context_type *context,
char buffer_space[256]; char buffer_space[256];
char *buffer = buffer_space; char *buffer = buffer_space;
char *finish = strchr(p, JVM_SIGNATURE_ENDCLASS); char *finish = strchr(p, JVM_SIGNATURE_ENDCLASS);
int length = finish - p; int length;
if (finish == NULL) {
/* Signature must have ';' after the class name.
* If it does not, return 0 and ITEM_Bogus in full_info. */
result = 0;
break;
}
length = finish - p;
if (length + 1 > (int)sizeof(buffer_space)) { if (length + 1 > (int)sizeof(buffer_space)) {
buffer = malloc(length + 1); buffer = malloc(length + 1);
check_and_push(context, buffer, VM_MALLOC_BLK); check_and_push(context, buffer, VM_MALLOC_BLK);
......
...@@ -187,7 +187,6 @@ class UnixFileSystem extends FileSystem { ...@@ -187,7 +187,6 @@ class UnixFileSystem extends FileSystem {
} }
} }
} }
assert canonicalize0(path).equals(res) || path.startsWith(javaHome);
return res; return res;
} }
} }
......
...@@ -1141,6 +1141,13 @@ class UnixPath ...@@ -1141,6 +1141,13 @@ class UnixPath
} }
result = result.resolve(element); result = result.resolve(element);
} }
// check file exists (without following links)
try {
UnixFileAttributes.get(result, false);
} catch (UnixException x) {
x.rethrowAsIOException(result);
}
return result; return result;
} }
......
...@@ -1052,30 +1052,38 @@ JNIEXPORT void JNICALL ...@@ -1052,30 +1052,38 @@ JNIEXPORT void JNICALL
Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
jobject this) { jobject this) {
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
int fd; int fd, t = 1;
#ifdef AF_INET6
int t = 1; int domain = ipv6_available() ? AF_INET6 : AF_INET;
#else
int domain = AF_INET;
#endif
if (IS_NULL(fdObj)) { if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed"); "Socket closed");
return; return;
} else {
#ifdef AF_INET6
if (ipv6_available()) {
fd = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
} else
#endif /* AF_INET6 */
{
fd = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
}
} }
if (fd == JVM_IO_ERR) {
if ((fd = JVM_Socket(domain, SOCK_DGRAM, 0)) == JVM_IO_ERR) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
"Error creating socket"); "Error creating socket");
return; return;
} }
#ifdef AF_INET6
/* Disable IPV6_V6ONLY to ensure dual-socket support */
if (domain == AF_INET6) {
int arg = 0;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
sizeof(int)) < 0) {
NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
close(fd);
return;
}
}
#endif /* AF_INET6 */
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int)); setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int));
#ifdef __linux__ #ifdef __linux__
...@@ -1088,7 +1096,7 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, ...@@ -1088,7 +1096,7 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
* On Linux for IPv6 sockets we must set the hop limit * On Linux for IPv6 sockets we must set the hop limit
* to 1 to be compatible with default ttl of 1 for IPv4 sockets. * to 1 to be compatible with default ttl of 1 for IPv4 sockets.
*/ */
if (ipv6_available()) { if (domain == AF_INET6) {
int ttl = 1; int ttl = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl, setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl,
sizeof(ttl)); sizeof(ttl));
......
...@@ -181,6 +181,12 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this, ...@@ -181,6 +181,12 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
jboolean stream) { jboolean stream) {
jobject fdObj, ssObj; jobject fdObj, ssObj;
int fd; int fd;
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
#ifdef AF_INET6
int domain = ipv6_available() ? AF_INET6 : AF_INET;
#else
int domain = AF_INET;
#endif
if (socketExceptionCls == NULL) { if (socketExceptionCls == NULL) {
jclass c = (*env)->FindClass(env, "java/net/SocketException"); jclass c = (*env)->FindClass(env, "java/net/SocketException");
...@@ -194,25 +200,29 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this, ...@@ -194,25 +200,29 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
(*env)->ThrowNew(env, socketExceptionCls, "null fd object"); (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
return; return;
} }
#ifdef AF_INET6
if (ipv6_available()) { if ((fd = JVM_Socket(domain, type, 0)) == JVM_IO_ERR) {
fd = JVM_Socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
} else
#endif /* AF_INET6 */
{
fd = JVM_Socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
}
if (fd == JVM_IO_ERR) {
/* note: if you run out of fds, you may not be able to load /* note: if you run out of fds, you may not be able to load
* the exception class, and get a NoClassDefFoundError * the exception class, and get a NoClassDefFoundError
* instead. * instead.
*/ */
NET_ThrowNew(env, errno, "can't create socket"); NET_ThrowNew(env, errno, "can't create socket");
return; return;
} else {
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
} }
#ifdef AF_INET6
/* Disable IPV6_V6ONLY to ensure dual-socket support */
if (domain == AF_INET6) {
int arg = 0;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
sizeof(int)) < 0) {
NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
close(fd);
return;
}
}
#endif /* AF_INET6 */
/* /*
* If this is a server socket then enable SO_REUSEADDR * If this is a server socket then enable SO_REUSEADDR
* automatically and set to non blocking. * automatically and set to non blocking.
...@@ -221,9 +231,15 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this, ...@@ -221,9 +231,15 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
if (ssObj != NULL) { if (ssObj != NULL) {
int arg = 1; int arg = 1;
SET_NONBLOCKING(fd); SET_NONBLOCKING(fd);
JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
sizeof(arg)); sizeof(arg)) < 0) {
NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
close(fd);
return;
}
} }
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
} }
/* /*
......
...@@ -170,6 +170,22 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, ...@@ -170,6 +170,22 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
if (fd < 0) { if (fd < 0) {
return handleSocketError(env, errno); return handleSocketError(env, errno);
} }
#ifdef AF_INET6
/* Disable IPV6_V6ONLY to ensure dual-socket support */
if (domain == AF_INET6) {
int arg = 0;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
sizeof(int)) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"sun.nio.ch.Net.setIntOption");
close(fd);
return -1;
}
}
#endif
if (reuse) { if (reuse) {
int arg = 1; int arg = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
......
...@@ -424,7 +424,6 @@ class Win32FileSystem extends FileSystem { ...@@ -424,7 +424,6 @@ class Win32FileSystem extends FileSystem {
} }
} }
} }
assert canonicalize0(path).equalsIgnoreCase(res);
return res; return res;
} }
} }
......
...@@ -55,7 +55,7 @@ case "$OS" in ...@@ -55,7 +55,7 @@ case "$OS" in
Linux ) Linux )
FS="/" FS="/"
;; ;;
Windows* ) Windows* | CYGWIN* )
FS="\\" FS="\\"
;; ;;
esac esac
......
...@@ -1536,6 +1536,7 @@ public class Test { ...@@ -1536,6 +1536,7 @@ public class Test {
serial(); serial();
urls(); urls();
npes(); npes();
bugs();
} }
...@@ -1572,6 +1573,19 @@ public class Test { ...@@ -1572,6 +1573,19 @@ public class Test {
} }
// miscellaneous bugs/rfes that don't fit in with the test framework
static void bugs() {
// 6339649 - include detail message from nested exception
try {
URI uri = URI.create("http://nowhere.net/should not be permitted");
} catch (IllegalArgumentException e) {
if ("".equals(e.getMessage()) || e.getMessage() == null) {
throw new RuntimeException ("No detail message");
}
}
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
switch (args.length) { switch (args.length) {
......
...@@ -260,6 +260,21 @@ public class Misc { ...@@ -260,6 +260,21 @@ public class Misc {
*/ */
assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false))); assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false)));
/**
* Test: toRealPath should fail if file does not exist
*/
Path doesNotExist = dir.resolve("DoesNotExist");
try {
doesNotExist.toRealPath(true);
throw new RuntimeException("IOException expected");
} catch (IOException expected) {
}
try {
doesNotExist.toRealPath(false);
throw new RuntimeException("IOException expected");
} catch (IOException expected) {
}
/** /**
* Test: toRealPath(true) should resolve links * Test: toRealPath(true) should resolve links
*/ */
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
# #
# @test # @test
# @ignore until 6543856 is fixed
# @bug 4990825 # @bug 4990825
# @summary attach to external but local JVM processes # @summary attach to external but local JVM processes
# @library ../../testlibrary # @library ../../testlibrary
......
/*
* 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.
*/
import java.net.URL;
import java.net.URLConnection;
import java.io.IOException;
public class DirPermissionDenied {
public static void main(String[] args) throws Exception {
URL url = new URL("file:" + args[0]);
try {
URLConnection uc = url.openConnection();
uc.connect();
} catch (IOException e) {
// OK
} catch (Exception e) {
throw new RuntimeException("Failed " + e);
}
try {
URLConnection uc = url.openConnection();
uc.getInputStream();
} catch (IOException e) {
// OK
} catch (Exception e) {
throw new RuntimeException("Failed " + e);
}
try {
URLConnection uc = url.openConnection();
uc.getContentLengthLong();
} catch (IOException e) {
// OK
} catch (Exception e) {
throw new RuntimeException("Failed " + e);
}
}
}
#
# 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.
#
#
# @test
# @bug 6977851
# @summary NPE from FileURLConnection.connect
# @build DirPermissionDenied
# @run shell DirPermissionDenied.sh
TESTDIR="${TESTCLASSES}/DirPermissionDeniedDirectory"
echo ${TESTDIR}
rm -rf ${TESTDIR}
mkdir -p ${TESTDIR}
chmod 333 ${TESTDIR}
$TESTJAVA/bin/java -classpath $TESTCLASSES DirPermissionDenied ${TESTDIR}
result=$?
rm -rf ${TESTDIR}
exit $result
/*
* 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.
*/
/*
* @test
* @bug 6976536
* @summary Solaris JREs do not have the krb5.kdc.bad.policy configured by default.
* @run main/othervm BadKdcDefaultValue
*/
import java.security.Security;
public class BadKdcDefaultValue {
public static void main(String[] args) throws Exception {
if (!"tryLast".equalsIgnoreCase(
Security.getProperty("krb5.kdc.bad.policy"))) {
throw new Exception("Default value not correct");
}
}
}
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6226610 * @bug 6226610 6973030
* @run main/othervm B6226610 * @run main/othervm B6226610
* @summary HTTP tunnel connections send user headers to proxy * @summary HTTP tunnel connections send user headers to proxy
*/ */
...@@ -36,45 +36,23 @@ ...@@ -36,45 +36,23 @@
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import javax.net.ssl.*; import sun.net.www.MessageHeader;
import javax.net.ServerSocketFactory;
import sun.net.www.*;
import java.util.Enumeration;
public class B6226610 { public class B6226610 {
static HeaderCheckerProxyTunnelServer proxy; static HeaderCheckerProxyTunnelServer proxy;
// it seems there's no proxy ever if a url points to 'localhost', public static void main(String[] args) throws Exception
// even if proxy related properties are set. so we need to bind
// our simple http proxy and http server to a non-loopback address
static InetAddress firstNonLoAddress = null;
public static void main(String[] args)
{ {
try { proxy = new HeaderCheckerProxyTunnelServer();
proxy = new HeaderCheckerProxyTunnelServer(); proxy.start();
proxy.start();
} catch (Exception e) {
System.out.println("Cannot create proxy: " + e);
}
try {
firstNonLoAddress = getNonLoAddress();
if (firstNonLoAddress == null) {
System.out.println("The test needs at least one non-loopback address to run. Quit now.");
System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
}
System.setProperty( "https.proxyHost", firstNonLoAddress.getHostAddress()); String hostname = InetAddress.getLocalHost().getHostName();
System.setProperty( "https.proxyPort", (new Integer(proxy.getLocalPort())).toString() );
try { try {
URL u = new URL("https://" + firstNonLoAddress.getHostAddress()); URL u = new URL("https://" + hostname + "/");
java.net.URLConnection c = u.openConnection(); System.out.println("Connecting to " + u);
InetSocketAddress proxyAddr = new InetSocketAddress(hostname, proxy.getLocalPort());
java.net.URLConnection c = u.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddr));
/* I want this header to go to the destination server only, protected /* I want this header to go to the destination server only, protected
* by SSL * by SSL
...@@ -89,33 +67,15 @@ public class B6226610 { ...@@ -89,33 +67,15 @@ public class B6226610 {
} }
else else
System.out.println(e); System.out.println(e);
} finally {
if (proxy != null) proxy.shutdown();
} }
if (HeaderCheckerProxyTunnelServer.failed) if (HeaderCheckerProxyTunnelServer.failed)
throw new RuntimeException("Test failed: Proxy should not receive user defined headers for tunneled requests"); throw new RuntimeException("Test failed; see output");
}
public static InetAddress getNonLoAddress() throws Exception {
NetworkInterface loNIC = NetworkInterface.getByInetAddress(InetAddress.getByName("localhost"));
Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
while (nics.hasMoreElements()) {
NetworkInterface nic = nics.nextElement();
if (!nic.getName().equalsIgnoreCase(loNIC.getName())) {
Enumeration<InetAddress> addrs = nic.getInetAddresses();
while (addrs.hasMoreElements()) {
InetAddress addr = addrs.nextElement();
if (!addr.isLoopbackAddress())
return addr;
}
}
}
return null;
} }
} }
class HeaderCheckerProxyTunnelServer extends Thread class HeaderCheckerProxyTunnelServer extends Thread
{ {
public static boolean failed = false; public static boolean failed = false;
...@@ -139,6 +99,10 @@ class HeaderCheckerProxyTunnelServer extends Thread ...@@ -139,6 +99,10 @@ class HeaderCheckerProxyTunnelServer extends Thread
} }
} }
void shutdown() {
try { ss.close(); } catch (IOException e) {}
}
public void run() public void run()
{ {
try { try {
...@@ -178,6 +142,15 @@ class HeaderCheckerProxyTunnelServer extends Thread ...@@ -178,6 +142,15 @@ class HeaderCheckerProxyTunnelServer extends Thread
retrieveConnectInfo(statusLine); retrieveConnectInfo(statusLine);
if (mheader.findValue("X-TestHeader") != null) { if (mheader.findValue("X-TestHeader") != null) {
System.out.println("Proxy should not receive user defined headers for tunneled requests");
failed = true;
}
// 6973030
String value;
if ((value = mheader.findValue("Proxy-Connection")) == null ||
!value.equals("keep-alive")) {
System.out.println("Proxy-Connection:keep-alive not being sent");
failed = true; failed = true;
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/** /**
* @test * @test
* @bug 4225317 * @bug 4225317 6969651
* @summary Check extracted files have date as per those in the .jar file * @summary Check extracted files have date as per those in the .jar file
*/ */
...@@ -68,17 +68,9 @@ public class JarEntryTime { ...@@ -68,17 +68,9 @@ public class JarEntryTime {
} }
public static void realMain(String[] args) throws Throwable { public static void realMain(String[] args) throws Throwable {
final long now = System.currentTimeMillis();
final long earlier = now - (60L * 60L * 6L * 1000L);
final long yesterday = now - (60L * 60L * 24L * 1000L);
// ZipEntry's mod date has 2 seconds precision: give extra time to
// allow for e.g. rounding/truncation and networked/samba drives.
final long PRECISION = 10000L;
File dirOuter = new File("outer"); File dirOuter = new File("outer");
File dirInner = new File(dirOuter, "inner"); File dirInner = new File(dirOuter, "inner");
File jarFile = new File("JarEntryTime.jar"); File jarFile = new File("JarEntryTime.jar");
// Remove any leftovers from prior run // Remove any leftovers from prior run
...@@ -99,6 +91,17 @@ public class JarEntryTime { ...@@ -99,6 +91,17 @@ public class JarEntryTime {
PrintWriter pw = new PrintWriter(fileInner); PrintWriter pw = new PrintWriter(fileInner);
pw.println("hello, world"); pw.println("hello, world");
pw.close(); pw.close();
// Get the "now" from the "last-modified-time" of the last file we
// just created, instead of the "System.currentTimeMillis()", to
// workaround the possible "time difference" due to nfs.
final long now = fileInner.lastModified();
final long earlier = now - (60L * 60L * 6L * 1000L);
final long yesterday = now - (60L * 60L * 24L * 1000L);
// ZipEntry's mod date has 2 seconds precision: give extra time to
// allow for e.g. rounding/truncation and networked/samba drives.
final long PRECISION = 10000L;
dirOuter.setLastModified(now); dirOuter.setLastModified(now);
dirInner.setLastModified(yesterday); dirInner.setLastModified(yesterday);
fileInner.setLastModified(earlier); fileInner.setLastModified(earlier);
......
/*
* Copyright (c) 2007, 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.
*/
/*
* @test CommandLineTests.sh
* @bug 6521334 6965836 6965836
* @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<File> 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<File>();
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();
}
// 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");
ps.println("pack.pass.file.5=com/sun/demo/jvmti/hprof/Tracker.class");
} finally {
Utils.close(ps);
Utils.close(fos);
}
}
static void runPack200(boolean jre) throws IOException {
List<String> cmdsList = new ArrayList<String>();
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.getAbsoluteFile(), bakFile.getAbsoluteFile());
} else { // restore
Utils.copyFile(bakFile.getAbsoluteFile(), f.getAbsoluteFile());
}
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<String> cmdsList = new ArrayList<String>();
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<String> cmdsList = new ArrayList<String>();
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();
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
...@@ -21,113 +21,107 @@ ...@@ -21,113 +21,107 @@
* questions. * questions.
*/ */
/** /*
* @test * @test
* @bug 6575373 * @bug 6575373 6969063
* @summary verify default segment limit * @summary verify default properties of the packer/unpacker and segment limit
* @compile SegmentLimit.java * @compile -XDignore.symbol.file Utils.java Pack200Props.java
* @run main SegmentLimit * @run main Pack200Props
* @author ksrini
*/ */
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.util.ArrayList;
import java.io.IOException; import java.util.HashMap;
import java.io.InputStream; import java.util.List;
import java.io.InputStreamReader; import java.util.Map;
import java.io.PrintStream; import java.util.jar.Pack200;
import java.util.jar.Pack200.Packer;
/* /*
* Run this against a large jar file, by default the packer should generate only * 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. * one segment, parse the output of the packer to verify if this is indeed true.
*/ */
public class SegmentLimit { public class Pack200Props {
private static final File javaHome = new File(System.getProperty("java.home"));
public static void main(String... args) { public static void main(String... args) {
if (!javaHome.getName().endsWith("jre")) { verifyDefaults();
throw new RuntimeException("Error: requires an SDK to run"); File out = new File("test" + Utils.PACK_FILE_EXT);
}
File out = new File("test" + Pack200Test.PACKEXT);
out.delete(); out.delete();
runPack200(out); verifySegmentLimit(out);
} }
static void close(Closeable c) { static void verifySegmentLimit(File outFile) {
if (c == null) { File sdkHome = Utils.JavaSDK;
return;
}
try {
c.close();
} catch (IOException ignore) {}
}
static void runPack200(File outFile) {
File binDir = new File(javaHome, "bin");
File pack200Exe = System.getProperty("os.name").startsWith("Windows")
? new File(binDir, "pack200.exe")
: new File(binDir, "pack200");
File sdkHome = javaHome.getParentFile();
File testJar = new File(new File(sdkHome, "lib"), "tools.jar"); File testJar = new File(new File(sdkHome, "lib"), "tools.jar");
System.out.println("using pack200: " + pack200Exe.getAbsolutePath()); System.out.println("using pack200: " + Utils.getPack200Cmd());
String[] cmds = { pack200Exe.getAbsolutePath(), List<String> cmdsList = new ArrayList<>();
"--effort=1", cmdsList.add(Utils.getPack200Cmd());
"--verbose", cmdsList.add("--effort=1");
"--no-gzip", cmdsList.add("--verbose");
outFile.getName(), cmdsList.add("--no-gzip");
testJar.getAbsolutePath() cmdsList.add(outFile.getName());
}; cmdsList.add(testJar.getAbsolutePath());
InputStream is = null; List<String> outList = Utils.runExec(cmdsList);
BufferedReader br = null;
InputStreamReader ir = null; int count = 0;
for (String line : outList) {
FileOutputStream fos = null; System.out.println(line);
PrintStream ps = null; if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) {
count++;
try { }
ProcessBuilder pb = new ProcessBuilder(cmds); }
pb.redirectErrorStream(true); if (count == 0) {
Process p = pb.start(); throw new RuntimeException("no segments or no output ????");
is = p.getInputStream(); } else if (count > 1) {
ir = new InputStreamReader(is); throw new RuntimeException("multiple segments detected, expected 1");
br = new BufferedReader(ir); }
}
File logFile = new File("pack200.log");
fos = new FileOutputStream(logFile);
ps = new PrintStream(fos);
String line = br.readLine(); private static void verifyDefaults() {
int count = 0; Map<String, String> expectedDefaults = new HashMap<>();
while (line != null) { Packer p = Pack200.newPacker();
line = line.trim(); expectedDefaults.put("com.sun.java.util.jar.pack.default.timezone",
if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) { p.FALSE);
count++; 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<String, String> 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++;
} }
ps.println(line);
line=br.readLine();
}
p.waitFor();
if (p.exitValue() != 0) {
throw new RuntimeException("pack200 failed");
} }
p.destroy(); }
if (count > 1) { if (errors > 0) {
throw new Error("test fails: check for multiple segments(" + throw new RuntimeException(errors +
count + ") in: " + logFile.getAbsolutePath()); " error(s) encountered in default properties verification");
}
} catch (IOException ex) {
throw new RuntimeException(ex.getMessage());
} catch (InterruptedException ignore){
} finally {
close(is);
close(ps);
close(fos);
} }
} }
} }
......
#
# Copyright (c) 2003, 2007, 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 Pack200Simple.sh
# @bug 6521334
# @build Pack200Test
# @run shell/timeout=1200 Pack200Simple.sh
# @summary An ad hoc test to verify class-file format.
# @author Kumar Srinivasan
# The goal of this test is to assist javac or other developers
# who modify class file formats, to quickly test those modifications
# without having to build the install workspace. However it must
# be noted that building the install workspace is the only know
# way to prevent build breakages.
# Pack200 developers could use this as a basic smoke-test, however
# please note, there are other more elaborate and thorough tests for
# this very purpose.
# 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.
# print error and exit with a message
errorOut() {
if [ "x$1" = "x" ]; then
printf "Error: Unknown error\n"
else
printf "Error: %s\n" "$1"
fi
exit 1
}
# Verify directory context variables are set
if [ "${TESTJAVA}" = "" ]; then
errorOut "TESTJAVA not set. Test cannot execute. Failed."
fi
if [ "${TESTSRC}" = "" ]; then
errorOut "TESTSRC not set. Test cannot execute. Failed."
fi
if [ "${TESTCLASSES}" = "" ]; then
errorOut "TESTCLASSES not set. Test cannot execute. Failed."
fi
# The common java utils we need
PACK200=${TESTJAVA}/bin/pack200
UNPACK200=${TESTJAVA}/bin/unpack200
JAR=${TESTJAVA}/bin/jar
# For Windows and Linux needs the heap to be set, for others ergonomics
# will do the rest. It is important to use ea, which can expose class
# format errors much earlier than later.
OS=`uname -s`
case "$OS" in
Windows*|CYGWIN* )
PackOptions="-J-Xmx512m -J-ea"
break
;;
Linux )
PackOptions="-J-Xmx512m -J-ea"
break
;;
* )
PackOptions="-J-ea"
;;
esac
# Creates a packfile of choice expects 1 argument the filename
createConfigFile() {
# optimize for speed
printf "pack.effort=1\n" > $1
# we DO want to know about new attributes
printf "pack.unknown.attribute=error\n" >> $1
# optimize for speed
printf "pack.deflate.hint=false\n" >> $1
# keep the ordering for easy compare
printf "pack.keep.class.order=true\n" >> $1
}
# Tests a given jar, expects 1 argument the fully qualified
# name to a test jar, it writes all output to the current
# directory which is a scratch area.
testAJar() {
PackConf="pack.conf"
createConfigFile $PackConf
# Try some command line options
CLIPackOptions="$PackOptions -v --no-gzip --segment-limit=10000 --config-file=$PackConf"
jfName=`basename $1`
${PACK200} $CLIPackOptions ${jfName}.pack $1 > ${jfName}.pack.log 2>&1
if [ $? != 0 ]; then
errorOut "$jfName packing failed"
fi
# We want to test unpack200, therefore we dont use -r with pack
${UNPACK200} -v ${jfName}.pack $jfName > ${jfName}.unpack.log 2>&1
if [ $? != 0 ]; then
errorOut "$jfName unpacking failed"
fi
# A quick crc compare test to ensure a well formed zip
# archive, this is a critical unpack200 behaviour.
unzip -t $jfName > ${jfName}.unzip.log 2>&1
if [ $? != 0 ]; then
errorOut "$jfName unzip -t test failed"
fi
# The PACK200 signature should be at the top of the log
# this tag is critical for deployment related tools.
head -5 ${jfName}.unzip.log | grep PACK200 > /dev/null 2>&1
if [ $? != 0 ]; then
errorOut "$jfName PACK200 signature missing"
fi
# we know the size fields don't match, strip 'em out, its
# extremely important to ensure that the date stamps match up.
# Don't EVER sort the output we are checking for correct ordering.
${JAR} -tvf $1 | sed -e 's/^ *[0-9]* //g'> ${jfName}.ref.txt
${JAR} -tvf $jfName | sed -e 's/^ *[0-9]* //g'> ${jfName}.cmp.txt
diff ${jfName}.ref.txt ${jfName}.cmp.txt > ${jfName}.diff.log 2>&1
if [ $? != 0 ]; then
errorOut "$jfName files missing"
fi
}
# These JARs are the largest and also the most likely specimens to
# expose class format issues and stress the packer as well.
JLIST="${TESTJAVA}/lib/tools.jar ${TESTJAVA}/jre/lib/rt.jar"
# Test the Command Line Interfaces (CLI).
mkdir cliTestDir
_pwd=`pwd`
cd cliTestDir
for jarfile in $JLIST ; do
if [ -f $jarfile ]; then
testAJar $jarfile
else
errorOut "Error: '$jarFile' does not exist\nTest requires a j2sdk-image\n"
fi
done
cd $_pwd
# Test the Java APIs.
mkdir apiTestDir
_pwd=`pwd`
cd apiTestDir
# Strip out the -J prefixes.
JavaPackOptions=`printf %s "$PackOptions" | sed -e 's/-J//g'`
# Test the Java APIs now.
$TESTJAVA/bin/java $JavaPackOptions -cp $TESTCLASSES Pack200Test $JLIST || exit 1
cd $_pwd
exit 0
...@@ -24,111 +24,97 @@ ...@@ -24,111 +24,97 @@
import java.util.*; import java.util.*;
import java.io.*; import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.util.jar.*; import java.util.jar.*;
import java.util.zip.*;
/* /*
* Pack200Test.java * @test
* * @bug 6521334 6712743
* @author ksrini * @summary check for memory leaks, test general packer/unpacker functionality\
*/ * using native and java unpackers
* @compile -XDignore.symbol.file Utils.java Pack200Test.java
* @run main/othervm/timeout=1200 -Xmx512m Pack200Test
* @author ksrini
*/
/** /**
* These tests are very rudimentary smoke tests to ensure that the packing * Tests the packing/unpacking via the APIs.
* unpacking process works on a select set of JARs.
*/ */
public class Pack200Test { public class Pack200Test {
private static ArrayList <File> jarList = new ArrayList<File>(); private static ArrayList <File> jarList = new ArrayList<File>();
static final String PACKEXT = ".pack"; static final MemoryMXBean mmxbean = ManagementFactory.getMemoryMXBean();
static final long m0 = getUsedMemory();
static final int LEAK_TOLERANCE = 20000; // OS and GC related variations.
/** Creates a new instance of Pack200Test */ /** Creates a new instance of Pack200Test */
private Pack200Test() {} private Pack200Test() {}
static long getUsedMemory() {
mmxbean.gc();
mmxbean.gc();
mmxbean.gc();
return mmxbean.getHeapMemoryUsage().getUsed()/1024;
}
private static void leakCheck() throws Exception {
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() { private static void doPackUnpack() {
for (File in : jarList) { for (File in : jarList) {
Pack200.Packer packer = Pack200.newPacker(); JarOutputStream javaUnpackerStream = null;
Map<String, String> p = packer.properties(); JarOutputStream nativeUnpackerStream = null;
// Take the time optimization vs. space JarFile jarFile = null;
p.put(packer.EFFORT, "1"); // CAUTION: do not use 0.
// Make the memory consumption as effective as possible
p.put(packer.SEGMENT_LIMIT,"10000");
// throw an error if an attribute is unrecognized
p.put(packer.UNKNOWN_ATTRIBUTE, packer.ERROR);
// 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);
try { try {
JarFile jarFile = new JarFile(in); jarFile = new JarFile(in);
// Write out to a jtreg scratch area // Write out to a jtreg scratch area
FileOutputStream fos = new FileOutputStream(in.getName() + PACKEXT); File packFile = new File(in.getName() + Utils.PACK_FILE_EXT);
System.out.print("Packing [" + in.toString() + "]..."); System.out.println("Packing [" + in.toString() + "]");
// Call the packer // Call the packer
packer.pack(jarFile, fos); Utils.pack(jarFile, packFile);
jarFile.close(); jarFile.close();
fos.close(); leakCheck();
System.out.print("Unpacking...");
File f = new File(in.getName() + PACKEXT);
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 // Write out to current directory, jtreg will setup a scratch area
JarOutputStream jostream = new JarOutputStream(new FileOutputStream(in.getName())); javaUnpackerStream = new JarOutputStream(
new FileOutputStream(javaUnpackedJar));
// Unpack the files Utils.unpackj(packFile, javaUnpackerStream);
Pack200.Unpacker unpacker = Pack200.newUnpacker(); javaUnpackerStream.close();
// Call the unpacker System.out.println(" Testing...java unpacker");
unpacker.unpack(f, jostream); leakCheck();
// Must explicitly close the output.
jostream.close();
System.out.print("Testing...");
// Ok we have unpacked the file, lets test it. // Ok we have unpacked the file, lets test it.
doTest(in); 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."); System.out.println("Done.");
} catch (Exception e) { } catch (Exception e) {
System.out.println("ERROR: " + e.getMessage()); throw new RuntimeException(e);
System.exit(1); } finally {
} Utils.close(nativeUnpackerStream);
} Utils.close(javaUnpackerStream);
} Utils.close((Closeable) jarFile);
private static ArrayList <String> getZipFileEntryNames(ZipFile z) {
ArrayList <String> out = new ArrayList<String>();
for (ZipEntry ze : Collections.list(z.entries())) {
out.add(ze.getName());
}
return out;
}
private static void doTest(File in) throws Exception {
// make sure all the files in the original jar exists in the other
ArrayList <String> refList = getZipFileEntryNames(new ZipFile(in));
ArrayList <String> cmpList = getZipFileEntryNames(new ZipFile(in.getName()));
System.out.print(refList.size() + "/" + cmpList.size() + " entries...");
if (refList.size() != cmpList.size()) {
throw new Exception("Missing: files ?, entries don't match");
}
for (String ename: refList) {
if (!cmpList.contains(ename)) {
throw new Exception("Does not contain : " + ename);
}
}
}
private static void doSanity(String[] args) {
for (String s: args) {
File f = new File(s);
if (f.exists()) {
jarList.add(f);
} else {
System.out.println("Warning: The JAR file " + f.toString() + " does not exist,");
System.out.println(" this test requires a JDK image, this file will be skipped.");
} }
} }
} }
...@@ -137,11 +123,12 @@ public class Pack200Test { ...@@ -137,11 +123,12 @@ public class Pack200Test {
* @param args the command line arguments * @param args the command line arguments
*/ */
public static void main(String[] args) { public static void main(String[] args) {
if (args.length < 1) { // select the jars carefully, adding more jars will increase the
System.out.println("Usage: jar1 jar2 jar3 ....."); // testing time, especially for jprt.
System.exit(1); jarList.add(Utils.locateJar("tools.jar"));
} jarList.add(Utils.locateJar("rt.jar"));
doSanity(args); jarList.add(Utils.locateJar("golden.jar"));
System.out.println(jarList);
doPackUnpack(); doPackUnpack();
} }
} }
...@@ -22,13 +22,14 @@ ...@@ -22,13 +22,14 @@
* questions. * questions.
*/ */
/** /*
* @test * @test
* @bug 6712743 * @bug 6712743
* @summary verify package versioning * @summary verify package versions
* @compile -XDignore.symbol.file PackageVersionTest.java * @compile -XDignore.symbol.file Utils.java PackageVersionTest.java
* @run main PackageVersionTest * @run main PackageVersionTest
*/ * @author ksrini
*/
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.Closeable; import java.io.Closeable;
...@@ -74,14 +75,6 @@ public class PackageVersionTest { ...@@ -74,14 +75,6 @@ public class PackageVersionTest {
JAVA5_PACKAGE_MINOR_VERSION); JAVA5_PACKAGE_MINOR_VERSION);
} }
static void close(Closeable c) {
if (c == null) {
return;
}
try {
c.close();
} catch (IOException ignore) {}
}
static void createClassFile(String name) { static void createClassFile(String name) {
createJavaFile(name); createJavaFile(name);
...@@ -93,7 +86,7 @@ public class PackageVersionTest { ...@@ -93,7 +86,7 @@ public class PackageVersionTest {
name.substring(name.length() - 1), name.substring(name.length() - 1),
name + ".java" name + ".java"
}; };
compileJava(javacCmds); Utils.compiler(javacCmds);
} }
static void createJavaFile(String name) { static void createJavaFile(String name) {
...@@ -108,22 +101,8 @@ public class PackageVersionTest { ...@@ -108,22 +101,8 @@ public class PackageVersionTest {
} catch (IOException ioe) { } catch (IOException ioe) {
throw new RuntimeException("creation of test file failed"); throw new RuntimeException("creation of test file failed");
} finally { } finally {
close(ps); Utils.close(ps);
close(fos); Utils.close(fos);
}
}
static void compileJava(String... javacCmds) {
if (com.sun.tools.javac.Main.compile(javacCmds) != 0) {
throw new RuntimeException("compilation failed");
}
}
static void makeJar(String... jargs) {
sun.tools.jar.Main jarTool =
new sun.tools.jar.Main(System.out, System.err, "jartool");
if (!jarTool.run(jargs)) {
throw new RuntimeException("jar command failed");
} }
} }
...@@ -136,7 +115,7 @@ public class PackageVersionTest { ...@@ -136,7 +115,7 @@ public class PackageVersionTest {
jarFileName.getName(), jarFileName.getName(),
filename filename
}; };
makeJar(jargs); Utils.jar(jargs);
JarFile jfin = null; JarFile jfin = null;
try { try {
...@@ -163,7 +142,7 @@ public class PackageVersionTest { ...@@ -163,7 +142,7 @@ public class PackageVersionTest {
} catch (IOException ioe) { } catch (IOException ioe) {
throw new RuntimeException(ioe.getMessage()); throw new RuntimeException(ioe.getMessage());
} finally { } finally {
close(jfin); Utils.close((Closeable) jfin);
} }
} }
} }
/*
* 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.
*/
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.locateJar("golden.jar");
File goldenFile = new File("golden.jar");
Utils.copyFile(srcFile, goldenFile.getAbsoluteFile());
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();
}
static void unpackNative(File packFile, File outFile) {
String name = outFile.getName();
String tzname = name.substring(name.lastIndexOf(".") + 1);
HashMap<String, String> 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<String> 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");
}
}
}
/*
* 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.
*/
/*
* @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);
}
}
}
}
此差异已折叠。
The files contained in the golden.jar have been harvested from many
different sources, some are hand-crafted invalid class files (odds directory),
or from random JDK builds.
Generally these files serve to ensure the integrity of the packer and unpacker
by,
1. maximizing the test coverage.
2. exercising all the Bands in the pack200 specification.
2. testing the behavior of the packer with invalid classes.
3. testing the archive integrity, ordering and description (date, sizes,
CRC etc.)
Build:
To rebuild this JAR follow these steps:
1. unzip the golden.jar to some directory lets call it "example"
2. now we can add any directories with files into example.
2. run the script BUILDME.sh as
% sh BUILDME.sh example
Note: the BUILDME.sh is known to work on all Unix platforms as well as Windows
using Cygwin.
The above will create two JAR files in the current directory,
example.jar and example-cls.jar, now the example.jar can be used as the
golden.jar.
To ensure the JAR has been built correctly use jar -tvf and compare the
results of the old jar and the newly built one, note that the compressed sizes
may differ, however the timestamps etc. should be consistent.
Test:
Basic:
% pack200 --repack test.jar golden.jar
Advanced:
Create a pack.conf as follows:
% cat pack.conf
com.sun.java.util.jar.pack.dump.bands=true
% pack200 --no-gzip --config-file=pack.conf \
--verbose golden.jar.pack golden.jar
This command will dump the Bands in a unique directory BD_XXXXXX,
one can inspect the directory to ensure all of the bands are being
generated. Familiarity of the Pack200 specification is suggested.
\ No newline at end of file
<project name="PackageVerify" default="dist" basedir="..">
<!-- Requires ant 1.6.1+ and JDK 1.6+-->
<!-- set global properties for this build -->
<property name="src" value="${basedir}/src"/>
<property name="build" value="${basedir}/build"/>
<property name="dist" value="${basedir}/dist"/>
<property name="make" value="${basedir}/make"/>
<property name="classes" value="${build}/classes"/>
<property name="api" value="${build}/api"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
<mkdir dir="${dist}"/>
<mkdir dir="${classes}"/>
<mkdir dir="${api}"/>
</target>
<target name="compile" depends="init">
<!-- Compile the java code from ${src} into ${build} -->
<javac
source="1.6"
srcdir="${src}"
destdir="${build}/classes"
verbose="no"
debug="on"
/>
</target>
<target name="doc" depends="init, compile">
<javadoc
source="1.6"
sourcepath="${src}"
destdir="${api}"
/>
</target>
<target name="dist" depends="compile, doc">
<!-- Put everything in jar file -->
<jar destfile="${dist}/pack200-verifier.jar">
<manifest>
<attribute name="Main-Class" value="sun.tools.pack.verify.Main"/>
</manifest>
<fileset dir="${classes}"/>
</jar>
<zip destfile="dist/pack200-verifier-doc.zip">
<fileset dir="${api}"/>
</zip>
</target>
<target name="clean">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>
/*
* 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<K> extends java.util.TreeSet {
VerifyTreeSet() {
super();
}
public VerifyTreeSet(Comparator c) {
super(c);
}
public TreeSet<K> diff(TreeSet in) {
TreeSet<K> delta = (TreeSet<K>) this.clone();
delta.removeAll(in);
return delta;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册