Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
JDK 11 java.base.jmod - Base Module
JDK 11 java.base.jmod is the JMOD file for JDK 11 Base module.
JDK 11 Base module compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\java.base.jmod.
JDK 11 Base module compiled class files are also linked and stored in the \fyicenter\jdk-11.0.1\lib\modules JImage file.
JDK 11 Base module source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\java.base.
You can click and view the content of each source code file in the list below.
✍: FYIcenter
⏎ com/sun/java/util/jar/pack/Attribute.java
/* * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.java.util.jar.pack; import com.sun.java.util.jar.pack.ConstantPool.Entry; import com.sun.java.util.jar.pack.ConstantPool.Index; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.sun.java.util.jar.pack.Constants.*; /** * Represents an attribute in a class-file. * Takes care to remember where constant pool indexes occur. * Implements the "little language" of Pack200 for describing * attribute layouts. * @author John Rose */ class Attribute implements Comparable<Attribute> { // Attribute instance fields. Layout def; // the name and format of this attr byte[] bytes; // the actual bytes Object fixups; // reference relocations, if any are required public String name() { return def.name(); } public Layout layout() { return def; } public byte[] bytes() { return bytes; } public int size() { return bytes.length; } public Entry getNameRef() { return def.getNameRef(); } private Attribute(Attribute old) { this.def = old.def; this.bytes = old.bytes; this.fixups = old.fixups; } public Attribute(Layout def, byte[] bytes, Object fixups) { this.def = def; this.bytes = bytes; this.fixups = fixups; Fixups.setBytes(fixups, bytes); } public Attribute(Layout def, byte[] bytes) { this(def, bytes, null); } public Attribute addContent(byte[] bytes, Object fixups) { assert(isCanonical()); if (bytes.length == 0 && fixups == null) return this; Attribute res = new Attribute(this); res.bytes = bytes; res.fixups = fixups; Fixups.setBytes(fixups, bytes); return res; } public Attribute addContent(byte[] bytes) { return addContent(bytes, null); } public void finishRefs(Index ix) { if (fixups != null) { Fixups.finishRefs(fixups, bytes, ix); fixups = null; } } public boolean isCanonical() { return this == def.canon; } @Override public int compareTo(Attribute that) { return this.def.compareTo(that.def); } private static final Map<List<Attribute>, List<Attribute>> canonLists = new HashMap<>(); private static final Map<Layout, Attribute> attributes = new HashMap<>(); private static final Map<Layout, Attribute> standardDefs = new HashMap<>(); // Canonicalized lists of trivial attrs (Deprecated, etc.) // are used by trimToSize, in order to reduce footprint // of some common cases. (Note that Code attributes are // always zero size.) public static List<Attribute> getCanonList(List<Attribute> al) { synchronized (canonLists) { List<Attribute> cl = canonLists.get(al); if (cl == null) { cl = new ArrayList<>(al.size()); cl.addAll(al); cl = Collections.unmodifiableList(cl); canonLists.put(al, cl); } return cl; } } // Find the canonical empty attribute with the given ctype, name, layout. public static Attribute find(int ctype, String name, String layout) { Layout key = Layout.makeKey(ctype, name, layout); synchronized (attributes) { Attribute a = attributes.get(key); if (a == null) { a = new Layout(ctype, name, layout).canonicalInstance(); attributes.put(key, a); } return a; } } public static Layout keyForLookup(int ctype, String name) { return Layout.makeKey(ctype, name); } // Find canonical empty attribute with given ctype and name, // and with the standard layout. public static Attribute lookup(Map<Layout, Attribute> defs, int ctype, String name) { if (defs == null) { defs = standardDefs; } return defs.get(Layout.makeKey(ctype, name)); } public static Attribute define(Map<Layout, Attribute> defs, int ctype, String name, String layout) { Attribute a = find(ctype, name, layout); defs.put(Layout.makeKey(ctype, name), a); return a; } static { Map<Layout, Attribute> sd = standardDefs; define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH"); define(sd, ATTR_CONTEXT_CLASS, "Synthetic", ""); define(sd, ATTR_CONTEXT_CLASS, "Deprecated", ""); define(sd, ATTR_CONTEXT_CLASS, "SourceFile", "RUH"); define(sd, ATTR_CONTEXT_CLASS, "EnclosingMethod", "RCHRDNH"); define(sd, ATTR_CONTEXT_CLASS, "InnerClasses", "NH[RCHRCNHRUNHFH]"); define(sd, ATTR_CONTEXT_CLASS, "BootstrapMethods", "NH[RMHNH[KLH]]"); define(sd, ATTR_CONTEXT_FIELD, "Signature", "RSH"); define(sd, ATTR_CONTEXT_FIELD, "Synthetic", ""); define(sd, ATTR_CONTEXT_FIELD, "Deprecated", ""); define(sd, ATTR_CONTEXT_FIELD, "ConstantValue", "KQH"); define(sd, ATTR_CONTEXT_METHOD, "Signature", "RSH"); define(sd, ATTR_CONTEXT_METHOD, "Synthetic", ""); define(sd, ATTR_CONTEXT_METHOD, "Deprecated", ""); define(sd, ATTR_CONTEXT_METHOD, "Exceptions", "NH[RCH]"); define(sd, ATTR_CONTEXT_METHOD, "MethodParameters", "NB[RUNHFH]"); //define(sd, ATTR_CONTEXT_METHOD, "Code", "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]"); define(sd, ATTR_CONTEXT_CODE, "StackMapTable", ("[NH[(1)]]" + "[TB" + "(64-127)[(2)]" + "(247)[(1)(2)]" + "(248-251)[(1)]" + "(252)[(1)(2)]" + "(253)[(1)(2)(2)]" + "(254)[(1)(2)(2)(2)]" + "(255)[(1)NH[(2)]NH[(2)]]" + "()[]" + "]" + "[H]" + "[TB(7)[RCH](8)[PH]()[]]")); define(sd, ATTR_CONTEXT_CODE, "LineNumberTable", "NH[PHH]"); define(sd, ATTR_CONTEXT_CODE, "LocalVariableTable", "NH[PHOHRUHRSHH]"); define(sd, ATTR_CONTEXT_CODE, "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); //define(sd, ATTR_CONTEXT_CODE, "CharacterRangeTable", "NH[PHPOHIIH]"); //define(sd, ATTR_CONTEXT_CODE, "CoverageTable", "NH[PHHII]"); // Note: Code and InnerClasses are special-cased elsewhere. // Their layout specs. are given here for completeness. // The Code spec is incomplete, in that it does not distinguish // bytecode bytes or locate CP references. // The BootstrapMethods attribute is also special-cased // elsewhere as an appendix to the local constant pool. } // Metadata. // // We define metadata using similar layouts // for all five kinds of metadata attributes and 2 type metadata attributes // // Regular annotations are a counted list of [RSHNH[RUH(1)]][...] // pack.method.attribute.RuntimeVisibleAnnotations=[NH[(1)]][RSHNH[RUH(1)]][TB...] // // Parameter annotations are a counted list of regular annotations. // pack.method.attribute.RuntimeVisibleParameterAnnotations=[NB[(1)]][NH[(1)]][RSHNH[RUH(1)]][TB...] // // RuntimeInvisible annotations are defined similarly... // Non-method annotations are defined similarly... // // Annotation are a simple tagged value [TB...] // pack.attribute.method.AnnotationDefault=[TB...] static { String mdLayouts[] = { Attribute.normalizeLayoutString ("" +"\n # parameter_annotations :=" +"\n [ NB[(1)] ] # forward call to annotations" ), Attribute.normalizeLayoutString ("" +"\n # annotations :=" +"\n [ NH[(1)] ] # forward call to annotation" +"\n " ), Attribute.normalizeLayoutString ("" +"\n # annotation :=" +"\n [RSH" +"\n NH[RUH (1)] # forward call to value" +"\n ]" ), Attribute.normalizeLayoutString ("" +"\n # value :=" +"\n [TB # Callable 2 encodes one tagged value." +"\n (\\B,\\C,\\I,\\S,\\Z)[KIH]" +"\n (\\D)[KDH]" +"\n (\\F)[KFH]" +"\n (\\J)[KJH]" +"\n (\\c)[RSH]" +"\n (\\e)[RSH RUH]" +"\n (\\s)[RUH]" +"\n (\\[)[NH[(0)]] # backward self-call to value" +"\n (\\@)[RSH NH[RUH (0)]] # backward self-call to value" +"\n ()[] ]" ) }; /* * RuntimeVisibleTypeAnnotation and RuntimeInvisibleTypeAnnotatation are * similar to RuntimeVisibleAnnotation and RuntimeInvisibleAnnotation, * a type-annotation union and a type-path structure precedes the * annotation structure */ String typeLayouts[] = { Attribute.normalizeLayoutString ("" +"\n # type-annotations :=" +"\n [ NH[(1)(2)(3)] ] # forward call to type-annotations" ), Attribute.normalizeLayoutString ( "" +"\n # type-annotation :=" +"\n [TB" +"\n (0-1) [B] # {CLASS, METHOD}_TYPE_PARAMETER" +"\n (16) [FH] # CLASS_EXTENDS" +"\n (17-18) [BB] # {CLASS, METHOD}_TYPE_PARAMETER_BOUND" +"\n (19-21) [] # FIELD, METHOD_RETURN, METHOD_RECEIVER" +"\n (22) [B] # METHOD_FORMAL_PARAMETER" +"\n (23) [H] # THROWS" +"\n (64-65) [NH[PHOHH]] # LOCAL_VARIABLE, RESOURCE_VARIABLE" +"\n (66) [H] # EXCEPTION_PARAMETER" +"\n (67-70) [PH] # INSTANCEOF, NEW, {CONSTRUCTOR, METHOD}_REFERENCE_RECEIVER" +"\n (71-75) [PHB] # CAST, {CONSTRUCTOR,METHOD}_INVOCATION_TYPE_ARGUMENT, {CONSTRUCTOR, METHOD}_REFERENCE_TYPE_ARGUMENT" +"\n ()[] ]" ), Attribute.normalizeLayoutString ("" +"\n # type-path" +"\n [ NB[BB] ]" ) }; Map<Layout, Attribute> sd = standardDefs; String defaultLayout = mdLayouts[3]; String annotationsLayout = mdLayouts[1] + mdLayouts[2] + mdLayouts[3]; String paramsLayout = mdLayouts[0] + annotationsLayout; String typesLayout = typeLayouts[0] + typeLayouts[1] + typeLayouts[2] + mdLayouts[2] + mdLayouts[3]; for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { if (ctype != ATTR_CONTEXT_CODE) { define(sd, ctype, "RuntimeVisibleAnnotations", annotationsLayout); define(sd, ctype, "RuntimeInvisibleAnnotations", annotationsLayout); if (ctype == ATTR_CONTEXT_METHOD) { define(sd, ctype, "RuntimeVisibleParameterAnnotations", paramsLayout); define(sd, ctype, "RuntimeInvisibleParameterAnnotations", paramsLayout); define(sd, ctype, "AnnotationDefault", defaultLayout); } } define(sd, ctype, "RuntimeVisibleTypeAnnotations", typesLayout); define(sd, ctype, "RuntimeInvisibleTypeAnnotations", typesLayout); } } public static String contextName(int ctype) { switch (ctype) { case ATTR_CONTEXT_CLASS: return "class"; case ATTR_CONTEXT_FIELD: return "field"; case ATTR_CONTEXT_METHOD: return "method"; case ATTR_CONTEXT_CODE: return "code"; } return null; } /** Base class for any attributed object (Class, Field, Method, Code). * Flags are included because they are used to help transmit the * presence of attributes. That is, flags are a mix of modifier * bits and attribute indicators. */ public abstract static class Holder { // We need this abstract method to interpret embedded CP refs. protected abstract Entry[] getCPMap(); protected int flags; // defined here for convenience protected List<Attribute> attributes; public int attributeSize() { return (attributes == null) ? 0 : attributes.size(); } public void trimToSize() { if (attributes == null) { return; } if (attributes.isEmpty()) { attributes = null; return; } if (attributes instanceof ArrayList) { ArrayList<Attribute> al = (ArrayList<Attribute>)attributes; al.trimToSize(); boolean allCanon = true; for (Attribute a : al) { if (!a.isCanonical()) { allCanon = false; } if (a.fixups != null) { assert(!a.isCanonical()); a.fixups = Fixups.trimToSize(a.fixups); } } if (allCanon) { // Replace private writable attribute list // with only trivial entries by public unique // immutable attribute list with the same entries. attributes = getCanonList(al); } } } public void addAttribute(Attribute a) { if (attributes == null) attributes = new ArrayList<>(3); else if (!(attributes instanceof ArrayList)) attributes = new ArrayList<>(attributes); // unfreeze it attributes.add(a); } public Attribute removeAttribute(Attribute a) { if (attributes == null) return null; if (!attributes.contains(a)) return null; if (!(attributes instanceof ArrayList)) attributes = new ArrayList<>(attributes); // unfreeze it attributes.remove(a); return a; } public Attribute getAttribute(int n) { return attributes.get(n); } protected void visitRefs(int mode, Collection<Entry> refs) { if (attributes == null) return; for (Attribute a : attributes) { a.visitRefs(this, mode, refs); } } static final List<Attribute> noAttributes = Arrays.asList(new Attribute[0]); public List<Attribute> getAttributes() { if (attributes == null) return noAttributes; return attributes; } public void setAttributes(List<Attribute> attrList) { if (attrList.isEmpty()) attributes = null; else attributes = attrList; } public Attribute getAttribute(String attrName) { if (attributes == null) return null; for (Attribute a : attributes) { if (a.name().equals(attrName)) return a; } return null; } public Attribute getAttribute(Layout attrDef) { if (attributes == null) return null; for (Attribute a : attributes) { if (a.layout() == attrDef) return a; } return null; } public Attribute removeAttribute(String attrName) { return removeAttribute(getAttribute(attrName)); } public Attribute removeAttribute(Layout attrDef) { return removeAttribute(getAttribute(attrDef)); } public void strip(String attrName) { removeAttribute(getAttribute(attrName)); } } // Lightweight interface to hide details of band structure. // Also used for testing. public abstract static class ValueStream { public int getInt(int bandIndex) { throw undef(); } public void putInt(int bandIndex, int value) { throw undef(); } public Entry getRef(int bandIndex) { throw undef(); } public void putRef(int bandIndex, Entry ref) { throw undef(); } // Note: decodeBCI goes w/ getInt/Ref; encodeBCI goes w/ putInt/Ref public int decodeBCI(int bciCode) { throw undef(); } public int encodeBCI(int bci) { throw undef(); } public void noteBackCall(int whichCallable) { /* ignore by default */ } private RuntimeException undef() { return new UnsupportedOperationException("ValueStream method"); } } // Element kinds: static final byte EK_INT = 1; // B H I SH etc. static final byte EK_BCI = 2; // PH POH etc. static final byte EK_BCO = 3; // OH etc. static final byte EK_FLAG = 4; // FH etc. static final byte EK_REPL = 5; // NH[...] etc. static final byte EK_REF = 6; // RUH, RUNH, KQH, etc. static final byte EK_UN = 7; // TB(...)[...] etc. static final byte EK_CASE = 8; // (...)[...] etc. static final byte EK_CALL = 9; // (0), (1), etc. static final byte EK_CBLE = 10; // [...][...] etc. static final byte EF_SIGN = 1<<0; // INT is signed static final byte EF_DELTA = 1<<1; // BCI/BCI value is diff'ed w/ previous static final byte EF_NULL = 1<<2; // null REF is expected/allowed static final byte EF_BACK = 1<<3; // call, callable, case is backward static final int NO_BAND_INDEX = -1; /** A "class" of attributes, characterized by a context-type, name * and format. The formats are specified in a "little language". */ public static class Layout implements Comparable<Layout> { int ctype; // attribute context type, e.g., ATTR_CONTEXT_CODE String name; // name of attribute boolean hasRefs; // this kind of attr contains CP refs? String layout; // layout specification int bandCount; // total number of elems Element[] elems; // tokenization of layout Attribute canon; // canonical instance of this layout public int ctype() { return ctype; } public String name() { return name; } public String layout() { return layout; } public Attribute canonicalInstance() { return canon; } public Entry getNameRef() { return ConstantPool.getUtf8Entry(name()); } public boolean isEmpty() { return layout.isEmpty(); } public Layout(int ctype, String name, String layout) { this.ctype = ctype; this.name = name.intern(); this.layout = layout.intern(); assert(ctype < ATTR_CONTEXT_LIMIT); boolean hasCallables = layout.startsWith("["); try { if (!hasCallables) { this.elems = tokenizeLayout(this, -1, layout); } else { String[] bodies = splitBodies(layout); // Make the callables now, so they can be linked immediately. Element[] lelems = new Element[bodies.length]; this.elems = lelems; for (int i = 0; i < lelems.length; i++) { Element ce = this.new Element(); ce.kind = EK_CBLE; ce.removeBand(); ce.bandIndex = NO_BAND_INDEX; ce.layout = bodies[i]; lelems[i] = ce; } // Next fill them in. for (int i = 0; i < lelems.length; i++) { Element ce = lelems[i]; ce.body = tokenizeLayout(this, i, bodies[i]); } //System.out.println(Arrays.asList(elems)); } } catch (StringIndexOutOfBoundsException ee) { // simplest way to catch syntax errors... throw new RuntimeException("Bad attribute layout: "+layout, ee); } // Some uses do not make a fresh one for each occurrence. // For example, if layout == "", we only need one attr to share. canon = new Attribute(this, noBytes); } private Layout() {} static Layout makeKey(int ctype, String name, String layout) { Layout def = new Layout(); def.ctype = ctype; def.name = name.intern(); def.layout = layout.intern(); assert(ctype < ATTR_CONTEXT_LIMIT); return def; } static Layout makeKey(int ctype, String name) { return makeKey(ctype, name, ""); } public Attribute addContent(byte[] bytes, Object fixups) { return canon.addContent(bytes, fixups); } public Attribute addContent(byte[] bytes) { return canon.addContent(bytes, null); } @Override public boolean equals(Object x) { return ( x != null) && ( x.getClass() == Layout.class ) && equals((Layout)x); } public boolean equals(Layout that) { return this.name.equals(that.name) && this.layout.equals(that.layout) && this.ctype == that.ctype; } @Override public int hashCode() { return (((17 + name.hashCode()) * 37 + layout.hashCode()) * 37 + ctype); } @Override public int compareTo(Layout that) { int r; r = this.name.compareTo(that.name); if (r != 0) return r; r = this.layout.compareTo(that.layout); if (r != 0) return r; return this.ctype - that.ctype; } @Override public String toString() { String str = contextName(ctype)+"."+name+"["+layout+"]"; // If -ea, print out more informative strings! assert((str = stringForDebug()) != null); return str; } private String stringForDebug() { return contextName(ctype)+"."+name+Arrays.asList(elems); } public class Element { String layout; // spelling in the little language byte flags; // EF_SIGN, etc. byte kind; // EK_UINT, etc. byte len; // scalar length of element byte refKind; // CONSTANT_String, etc. int bandIndex; // which band does this element govern? int value; // extra parameter Element[] body; // extra data (for replications, unions, calls) boolean flagTest(byte mask) { return (flags & mask) != 0; } Element() { bandIndex = bandCount++; } void removeBand() { --bandCount; assert(bandIndex == bandCount); bandIndex = NO_BAND_INDEX; } public boolean hasBand() { return bandIndex >= 0; } public String toString() { String str = layout; // If -ea, print out more informative strings! assert((str = stringForDebug()) != null); return str; } private String stringForDebug() { Element[] lbody = this.body; switch (kind) { case EK_CALL: lbody = null; break; case EK_CASE: if (flagTest(EF_BACK)) lbody = null; break; } return layout + (!hasBand()?"":"#"+bandIndex) + "<"+ (flags==0?"":""+flags)+kind+len + (refKind==0?"":""+refKind) + ">" + (value==0?"":"("+value+")") + (lbody==null?"": ""+Arrays.asList(lbody)); } } public boolean hasCallables() { return (elems.length > 0 && elems[0].kind == EK_CBLE); } private static final Element[] noElems = {}; public Element[] getCallables() { if (hasCallables()) { Element[] nelems = Arrays.copyOf(elems, elems.length); return nelems; } else return noElems; // no callables at all } public Element[] getEntryPoint() { if (hasCallables()) return elems[0].body; // body of first callable else { Element[] nelems = Arrays.copyOf(elems, elems.length); return nelems; // no callables; whole body } } /** Return a sequence of tokens from the given attribute bytes. * Sequence elements will be 1-1 correspondent with my layout tokens. */ public void parse(Holder holder, byte[] bytes, int pos, int len, ValueStream out) { int end = parseUsing(getEntryPoint(), holder, bytes, pos, len, out); if (end != pos + len) throw new InternalError("layout parsed "+(end-pos)+" out of "+len+" bytes"); } /** Given a sequence of tokens, return the attribute bytes. * Sequence elements must be 1-1 correspondent with my layout tokens. * The returned object is a cookie for Fixups.finishRefs, which * must be used to harden any references into integer indexes. */ public Object unparse(ValueStream in, ByteArrayOutputStream out) { Object[] fixups = { null }; unparseUsing(getEntryPoint(), fixups, in, out); return fixups[0]; // return ref-bearing cookie, if any } public String layoutForClassVersion(Package.Version vers) { if (vers.lessThan(JAVA6_MAX_CLASS_VERSION)) { // Disallow layout syntax in the oldest protocol version. return expandCaseDashNotation(layout); } return layout; } } public static class FormatException extends IOException { private static final long serialVersionUID = -2542243830788066513L; private int ctype; private String name; String layout; public FormatException(String message, int ctype, String name, String layout) { super(ATTR_CONTEXT_NAME[ctype]+ " attribute \"" + name + "\"" + (message == null? "" : (": " + message))); this.ctype = ctype; this.name = name; this.layout = layout; } public FormatException(String message, int ctype, String name) { this(message, ctype, name, null); } } void visitRefs(Holder holder, int mode, final Collection<Entry> refs) { if (mode == VRM_CLASSIC) { refs.add(getNameRef()); } // else the name is owned by the layout, and is processed elsewhere if (bytes.length == 0) return; // quick exit if (!def.hasRefs) return; // quick exit if (fixups != null) { Fixups.visitRefs(fixups, refs); return; } // References (to a local cpMap) are embedded in the bytes. def.parse(holder, bytes, 0, bytes.length, new ValueStream() { @Override public void putInt(int bandIndex, int value) { } @Override public void putRef(int bandIndex, Entry ref) { refs.add(ref); } @Override public int encodeBCI(int bci) { return bci; } }); } public void parse(Holder holder, byte[] bytes, int pos, int len, ValueStream out) { def.parse(holder, bytes, pos, len, out); } public Object unparse(ValueStream in, ByteArrayOutputStream out) { return def.unparse(in, out); } @Override public String toString() { return def +"{"+(bytes == null ? -1 : size())+"}" +(fixups == null? "": fixups.toString()); } /** Remove any informal "pretty printing" from the layout string. * Removes blanks and control chars. * Removes '#' comments (to end of line). * Replaces '\c' by the decimal code of the character c. * Replaces '0xNNN' by the decimal code of the hex number NNN. */ public static String normalizeLayoutString(String layout) { StringBuilder buf = new StringBuilder(); for (int i = 0, len = layout.length(); i < len; ) { char ch = layout.charAt(i++); if (ch <= ' ') { // Skip whitespace and control chars continue; } else if (ch == '#') { // Skip to end of line. int end1 = layout.indexOf('\n', i); int end2 = layout.indexOf('\r', i); if (end1 < 0) end1 = len; if (end2 < 0) end2 = len; i = Math.min(end1, end2); } else if (ch == '\\') { // Map a character reference to its decimal code. buf.append((int) layout.charAt(i++)); } else if (ch == '0' && layout.startsWith("0x", i-1)) { // Map a hex numeral to its decimal code. int start = i-1; int end = start+2; while (end < len) { int dig = layout.charAt(end); if ((dig >= '0' && dig <= '9') || (dig >= 'a' && dig <= 'f')) ++end; else break; } if (end > start) { String num = layout.substring(start, end); buf.append(Integer.decode(num)); i = end; } else { buf.append(ch); } } else { buf.append(ch); } } String result = buf.toString(); if (false && !result.equals(layout)) { Utils.log.info("Normalizing layout string"); Utils.log.info(" From: "+layout); Utils.log.info(" To: "+result); } return result; } /// Subroutines for parsing and unparsing: /** Parse the attribute layout language. <pre> attribute_layout: ( layout_element )* | ( callable )+ layout_element: ( integral | replication | union | call | reference ) callable: '[' body ']' body: ( layout_element )+ integral: ( unsigned_int | signed_int | bc_index | bc_offset | flag ) unsigned_int: uint_type signed_int: 'S' uint_type any_int: ( unsigned_int | signed_int ) bc_index: ( 'P' uint_type | 'PO' uint_type ) bc_offset: 'O' any_int flag: 'F' uint_type uint_type: ( 'B' | 'H' | 'I' | 'V' ) replication: 'N' uint_type '[' body ']' union: 'T' any_int (union_case)* '(' ')' '[' (body)? ']' union_case: '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']' union_case_tag: ( numeral | numeral '-' numeral ) call: '(' numeral ')' reference: reference_type ( 'N' )? uint_type reference_type: ( constant_ref | schema_ref | utf8_ref | untyped_ref ) constant_ref: ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' ) schema_ref: ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' ) utf8_ref: 'RU' untyped_ref: 'RQ' numeral: '(' ('-')? (digit)+ ')' digit: ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) </pre> */ static //private Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) { List<Layout.Element> col = new ArrayList<>(layout.length()); tokenizeLayout(self, curCble, layout, col); Layout.Element[] res = new Layout.Element[col.size()]; col.toArray(res); return res; } static //private void tokenizeLayout(Layout self, int curCble, String layout, List<Layout.Element> col) { boolean prevBCI = false; for (int len = layout.length(), i = 0; i < len; ) { int start = i; int body; Layout.Element e = self.new Element(); byte kind; //System.out.println("at "+i+": ..."+layout.substring(i)); // strip a prefix switch (layout.charAt(i++)) { /// layout_element: integral case 'B': case 'H': case 'I': case 'V': // unsigned_int kind = EK_INT; --i; // reparse i = tokenizeUInt(e, layout, i); break; case 'S': // signed_int kind = EK_INT; --i; // reparse i = tokenizeSInt(e, layout, i); break; case 'P': // bc_index kind = EK_BCI; if (layout.charAt(i++) == 'O') { // bc_index: 'PO' tokenizeUInt e.flags |= EF_DELTA; // must follow P or PO: if (!prevBCI) { i = -i; continue; } // fail i++; // move forward } --i; // reparse i = tokenizeUInt(e, layout, i); break; case 'O': // bc_offset kind = EK_BCO; e.flags |= EF_DELTA; // must follow P or PO: if (!prevBCI) { i = -i; continue; } // fail i = tokenizeSInt(e, layout, i); break; case 'F': // flag kind = EK_FLAG; i = tokenizeUInt(e, layout, i); break; case 'N': // replication: 'N' uint '[' elem ... ']' kind = EK_REPL; i = tokenizeUInt(e, layout, i); if (layout.charAt(i++) != '[') { i = -i; continue; } // fail i = skipBody(layout, body = i); e.body = tokenizeLayout(self, curCble, layout.substring(body, i++)); break; case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']' kind = EK_UN; i = tokenizeSInt(e, layout, i); List<Layout.Element> cases = new ArrayList<>(); for (;;) { // Keep parsing cases until we hit the default case. if (layout.charAt(i++) != '(') { i = -i; break; } // fail int beg = i; i = layout.indexOf(')', i); String cstr = layout.substring(beg, i++); int cstrlen = cstr.length(); if (layout.charAt(i++) != '[') { i = -i; break; } // fail // Check for duplication. if (layout.charAt(i) == ']') body = i; // missing body, which is legal here else i = skipBody(layout, body = i); Layout.Element[] cbody = tokenizeLayout(self, curCble, layout.substring(body, i++)); if (cstrlen == 0) { Layout.Element ce = self.new Element(); ce.body = cbody; ce.kind = EK_CASE; ce.removeBand(); cases.add(ce); break; // done with the whole union } else { // Parse a case string. boolean firstCaseNum = true; for (int cp = 0, endp;; cp = endp+1) { // Look for multiple case tags: endp = cstr.indexOf(',', cp); if (endp < 0) endp = cstrlen; String cstr1 = cstr.substring(cp, endp); if (cstr1.length() == 0) cstr1 = "empty"; // will fail parse int value0, value1; // Check for a case range (new in 1.6). int dash = findCaseDash(cstr1, 0); if (dash >= 0) { value0 = parseIntBefore(cstr1, dash); value1 = parseIntAfter(cstr1, dash); if (value0 >= value1) { i = -i; break; } // fail } else { value0 = value1 = Integer.parseInt(cstr1); } // Add a case for each value in value0..value1 for (;; value0++) { Layout.Element ce = self.new Element(); ce.body = cbody; // all cases share one body ce.kind = EK_CASE; ce.removeBand(); if (!firstCaseNum) // "backward case" repeats a body ce.flags |= EF_BACK; firstCaseNum = false; ce.value = value0; cases.add(ce); if (value0 == value1) break; } if (endp == cstrlen) { break; // done with this case } } } } e.body = new Layout.Element[cases.size()]; cases.toArray(e.body); e.kind = kind; for (int j = 0; j < e.body.length-1; j++) { Layout.Element ce = e.body[j]; if (matchCase(e, ce.value) != ce) { // Duplicate tag. { i = -i; break; } // fail } } break; case '(': // call: '(' '-'? digit+ ')' kind = EK_CALL; e.removeBand(); i = layout.indexOf(')', i); String cstr = layout.substring(start+1, i++); int offset = Integer.parseInt(cstr); int target = curCble + offset; if (!(offset+"").equals(cstr) || self.elems == null || target < 0 || target >= self.elems.length) { i = -i; continue; } // fail Layout.Element ce = self.elems[target]; assert(ce.kind == EK_CBLE); e.value = target; e.body = new Layout.Element[]{ ce }; // Is it a (recursive) backward call? if (offset <= 0) { // Yes. Mark both caller and callee backward. e.flags |= EF_BACK; ce.flags |= EF_BACK; } break; case 'K': // reference_type: constant_ref kind = EK_REF; switch (layout.charAt(i++)) { case 'I': e.refKind = CONSTANT_Integer; break; case 'J': e.refKind = CONSTANT_Long; break; case 'F': e.refKind = CONSTANT_Float; break; case 'D': e.refKind = CONSTANT_Double; break; case 'S': e.refKind = CONSTANT_String; break; case 'Q': e.refKind = CONSTANT_FieldSpecific; break; // new in 1.7: case 'M': e.refKind = CONSTANT_MethodHandle; break; case 'T': e.refKind = CONSTANT_MethodType; break; case 'L': e.refKind = CONSTANT_LoadableValue; break; default: { i = -i; continue; } // fail } break; case 'R': // schema_ref kind = EK_REF; switch (layout.charAt(i++)) { case 'C': e.refKind = CONSTANT_Class; break; case 'S': e.refKind = CONSTANT_Signature; break; case 'D': e.refKind = CONSTANT_NameandType; break; case 'F': e.refKind = CONSTANT_Fieldref; break; case 'M': e.refKind = CONSTANT_Methodref; break; case 'I': e.refKind = CONSTANT_InterfaceMethodref; break; case 'U': e.refKind = CONSTANT_Utf8; break; //utf8_ref case 'Q': e.refKind = CONSTANT_All; break; //untyped_ref // new in 1.7: case 'Y': e.refKind = CONSTANT_InvokeDynamic; break; case 'B': e.refKind = CONSTANT_BootstrapMethod; break; case 'N': e.refKind = CONSTANT_AnyMember; break; default: { i = -i; continue; } // fail } break; default: { i = -i; continue; } // fail } // further parsing of refs if (kind == EK_REF) { // reference: reference_type -><- ( 'N' )? tokenizeUInt if (layout.charAt(i++) == 'N') { e.flags |= EF_NULL; i++; // move forward } --i; // reparse i = tokenizeUInt(e, layout, i); self.hasRefs = true; } prevBCI = (kind == EK_BCI); // store the new element e.kind = kind; e.layout = layout.substring(start, i); col.add(e); } } static //private String[] splitBodies(String layout) { List<String> bodies = new ArrayList<>(); // Parse several independent layout bodies: "[foo][bar]...[baz]" for (int i = 0; i < layout.length(); i++) { if (layout.charAt(i++) != '[') layout.charAt(-i); // throw error int body; i = skipBody(layout, body = i); bodies.add(layout.substring(body, i)); } String[] res = new String[bodies.size()]; bodies.toArray(res); return res; } private static int skipBody(String layout, int i) { assert(layout.charAt(i-1) == '['); if (layout.charAt(i) == ']') // No empty bodies, please. return -i; // skip balanced [...[...]...] for (int depth = 1; depth > 0; ) { switch (layout.charAt(i++)) { case '[': depth++; break; case ']': depth--; break; } } --i; // get before bracket assert(layout.charAt(i) == ']'); return i; // return closing bracket } private static int tokenizeUInt(Layout.Element e, String layout, int i) { switch (layout.charAt(i++)) { case 'V': e.len = 0; break; case 'B': e.len = 1; break; case 'H': e.len = 2; break; case 'I': e.len = 4; break; default: return -i; } return i; } private static int tokenizeSInt(Layout.Element e, String layout, int i) { if (layout.charAt(i) == 'S') { e.flags |= EF_SIGN; ++i; } return tokenizeUInt(e, layout, i); } private static boolean isDigit(char c) { return c >= '0' && c <= '9'; } /** Find an occurrence of hyphen '-' between two numerals. */ static //private int findCaseDash(String layout, int fromIndex) { if (fromIndex <= 0) fromIndex = 1; // minimum dash pos int lastDash = layout.length() - 2; // maximum dash pos for (;;) { int dash = layout.indexOf('-', fromIndex); if (dash < 0 || dash > lastDash) return -1; if (isDigit(layout.charAt(dash-1))) { char afterDash = layout.charAt(dash+1); if (afterDash == '-' && dash+2 < layout.length()) afterDash = layout.charAt(dash+2); if (isDigit(afterDash)) { // matched /[0-9]--?[0-9]/; return position of dash return dash; } } fromIndex = dash+1; } } static int parseIntBefore(String layout, int dash) { int end = dash; int beg = end; while (beg > 0 && isDigit(layout.charAt(beg-1))) { --beg; } if (beg == end) return Integer.parseInt("empty"); // skip backward over a sign if (beg >= 1 && layout.charAt(beg-1) == '-') --beg; assert(beg == 0 || !isDigit(layout.charAt(beg-1))); return Integer.parseInt(layout.substring(beg, end)); } static int parseIntAfter(String layout, int dash) { int beg = dash+1; int end = beg; int limit = layout.length(); if (end < limit && layout.charAt(end) == '-') ++end; while (end < limit && isDigit(layout.charAt(end))) { ++end; } if (beg == end) return Integer.parseInt("empty"); return Integer.parseInt(layout.substring(beg, end)); } /** For compatibility with 1.5 pack, expand 1-5 into 1,2,3,4,5. */ static String expandCaseDashNotation(String layout) { int dash = findCaseDash(layout, 0); if (dash < 0) return layout; // no dashes (the common case) StringBuilder result = new StringBuilder(layout.length() * 3); int sofar = 0; // how far have we processed the layout? for (;;) { // for each dash, collect everything up to the dash result.append(layout, sofar, dash); sofar = dash+1; // skip the dash // then collect intermediate values int value0 = parseIntBefore(layout, dash); int value1 = parseIntAfter(layout, dash); assert(value0 < value1); result.append(","); // close off value0 numeral for (int i = value0+1; i < value1; i++) { result.append(i); result.append(","); // close off i numeral } dash = findCaseDash(layout, sofar); if (dash < 0) break; } result.append(layout, sofar, layout.length()); // collect the rest return result.toString(); } static { assert(expandCaseDashNotation("1-5").equals("1,2,3,4,5")); assert(expandCaseDashNotation("-2--1").equals("-2,-1")); assert(expandCaseDashNotation("-2-1").equals("-2,-1,0,1")); assert(expandCaseDashNotation("-1-0").equals("-1,0")); } // Parse attribute bytes, putting values into bands. Returns new pos. // Used when reading a class file (local refs resolved with local cpMap). // Also used for ad hoc scanning. static int parseUsing(Layout.Element[] elems, Holder holder, byte[] bytes, int pos, int len, ValueStream out) { int prevBCI = 0; int prevRBCI = 0; int end = pos + len; int[] buf = { 0 }; // for calls to parseInt, holds 2nd result for (int i = 0; i < elems.length; i++) { Layout.Element e = elems[i]; int bandIndex = e.bandIndex; int value; int BCI, RBCI; switch (e.kind) { case EK_INT: pos = parseInt(e, bytes, pos, buf); value = buf[0]; out.putInt(bandIndex, value); break; case EK_BCI: // PH, POH pos = parseInt(e, bytes, pos, buf); BCI = buf[0]; RBCI = out.encodeBCI(BCI); if (!e.flagTest(EF_DELTA)) { // PH: transmit R(bci), store bci value = RBCI; } else { // POH: transmit D(R(bci)), store bci value = RBCI - prevRBCI; } prevBCI = BCI; prevRBCI = RBCI; out.putInt(bandIndex, value); break; case EK_BCO: // OH assert(e.flagTest(EF_DELTA)); // OH: transmit D(R(bci)), store D(bci) pos = parseInt(e, bytes, pos, buf); BCI = prevBCI + buf[0]; RBCI = out.encodeBCI(BCI); value = RBCI - prevRBCI; prevBCI = BCI; prevRBCI = RBCI; out.putInt(bandIndex, value); break; case EK_FLAG: pos = parseInt(e, bytes, pos, buf); value = buf[0]; out.putInt(bandIndex, value); break; case EK_REPL: pos = parseInt(e, bytes, pos, buf); value = buf[0]; out.putInt(bandIndex, value); for (int j = 0; j < value; j++) { pos = parseUsing(e.body, holder, bytes, pos, end-pos, out); } break; // already transmitted the scalar value case EK_UN: pos = parseInt(e, bytes, pos, buf); value = buf[0]; out.putInt(bandIndex, value); Layout.Element ce = matchCase(e, value); pos = parseUsing(ce.body, holder, bytes, pos, end-pos, out); break; // already transmitted the scalar value case EK_CALL: // Adjust band offset if it is a backward call. assert(e.body.length == 1); assert(e.body[0].kind == EK_CBLE); if (e.flagTest(EF_BACK)) out.noteBackCall(e.value); pos = parseUsing(e.body[0].body, holder, bytes, pos, end-pos, out); break; // no additional scalar value to transmit case EK_REF: pos = parseInt(e, bytes, pos, buf); int localRef = buf[0]; Entry globalRef; if (localRef == 0) { globalRef = null; // N.B. global null reference is -1 } else { Entry[] cpMap = holder.getCPMap(); globalRef = (localRef >= 0 && localRef < cpMap.length ? cpMap[localRef] : null); byte tag = e.refKind; if (globalRef != null && tag == CONSTANT_Signature && globalRef.getTag() == CONSTANT_Utf8) { // Cf. ClassReader.readSignatureRef. String typeName = globalRef.stringValue(); globalRef = ConstantPool.getSignatureEntry(typeName); } String got = (globalRef == null ? "invalid CP index" : "type=" + ConstantPool.tagName(globalRef.tag)); if (globalRef == null || !globalRef.tagMatches(tag)) { throw new IllegalArgumentException( "Bad constant, expected type=" + ConstantPool.tagName(tag) + " got " + got); } } out.putRef(bandIndex, globalRef); break; default: assert(false); } } return pos; } static Layout.Element matchCase(Layout.Element e, int value) { assert(e.kind == EK_UN); int lastj = e.body.length-1; for (int j = 0; j < lastj; j++) { Layout.Element ce = e.body[j]; assert(ce.kind == EK_CASE); if (value == ce.value) return ce; } return e.body[lastj]; } private static int parseInt(Layout.Element e, byte[] bytes, int pos, int[] buf) { int value = 0; int loBits = e.len * 8; // Read in big-endian order: for (int bitPos = loBits; (bitPos -= 8) >= 0; ) { value += (bytes[pos++] & 0xFF) << bitPos; } if (loBits < 32 && e.flagTest(EF_SIGN)) { // sign-extend subword value int hiBits = 32 - loBits; value = (value << hiBits) >> hiBits; } buf[0] = value; return pos; } // Format attribute bytes, drawing values from bands. // Used when emptying attribute bands into a package model. // (At that point CP refs. are not yet assigned indexes.) static void unparseUsing(Layout.Element[] elems, Object[] fixups, ValueStream in, ByteArrayOutputStream out) { int prevBCI = 0; int prevRBCI = 0; for (int i = 0; i < elems.length; i++) { Layout.Element e = elems[i]; int bandIndex = e.bandIndex; int value; int BCI, RBCI; // "RBCI" is R(BCI), BCI's coded representation switch (e.kind) { case EK_INT: value = in.getInt(bandIndex); unparseInt(e, value, out); break; case EK_BCI: // PH, POH value = in.getInt(bandIndex); if (!e.flagTest(EF_DELTA)) { // PH: transmit R(bci), store bci RBCI = value; } else { // POH: transmit D(R(bci)), store bci RBCI = prevRBCI + value; } assert(prevBCI == in.decodeBCI(prevRBCI)); BCI = in.decodeBCI(RBCI); unparseInt(e, BCI, out); prevBCI = BCI; prevRBCI = RBCI; break; case EK_BCO: // OH value = in.getInt(bandIndex); assert(e.flagTest(EF_DELTA)); // OH: transmit D(R(bci)), store D(bci) assert(prevBCI == in.decodeBCI(prevRBCI)); RBCI = prevRBCI + value; BCI = in.decodeBCI(RBCI); unparseInt(e, BCI - prevBCI, out); prevBCI = BCI; prevRBCI = RBCI; break; case EK_FLAG: value = in.getInt(bandIndex); unparseInt(e, value, out); break; case EK_REPL: value = in.getInt(bandIndex); unparseInt(e, value, out); for (int j = 0; j < value; j++) { unparseUsing(e.body, fixups, in, out); } break; case EK_UN: value = in.getInt(bandIndex); unparseInt(e, value, out); Layout.Element ce = matchCase(e, value); unparseUsing(ce.body, fixups, in, out); break; case EK_CALL: assert(e.body.length == 1); assert(e.body[0].kind == EK_CBLE); unparseUsing(e.body[0].body, fixups, in, out); break; case EK_REF: Entry globalRef = in.getRef(bandIndex); int localRef; if (globalRef != null) { // It's a one-element array, really an lvalue. fixups[0] = Fixups.addRefWithLoc(fixups[0], out.size(), globalRef); localRef = 0; // placeholder for fixups } else { localRef = 0; // fixed null value } unparseInt(e, localRef, out); break; default: assert(false); continue; } } } private static void unparseInt(Layout.Element e, int value, ByteArrayOutputStream out) { int loBits = e.len * 8; if (loBits == 0) { // It is not stored at all ('V' layout). return; } if (loBits < 32) { int hiBits = 32 - loBits; int codedValue; if (e.flagTest(EF_SIGN)) codedValue = (value << hiBits) >> hiBits; else codedValue = (value << hiBits) >>> hiBits; if (codedValue != value) throw new InternalError("cannot code in "+e.len+" bytes: "+value); } // Write in big-endian order: for (int bitPos = loBits; (bitPos -= 8) >= 0; ) { out.write((byte)(value >>> bitPos)); } } /* /// Testing. public static void main(String av[]) { int maxVal = 12; int iters = 0; boolean verbose; int ap = 0; while (ap < av.length) { if (!av[ap].startsWith("-")) break; if (av[ap].startsWith("-m")) maxVal = Integer.parseInt(av[ap].substring(2)); else if (av[ap].startsWith("-i")) iters = Integer.parseInt(av[ap].substring(2)); else throw new RuntimeException("Bad option: "+av[ap]); ap++; } verbose = (iters == 0); if (iters <= 0) iters = 1; if (ap == av.length) { av = new String[] { "HH", // ClassFile.version "RUH", // SourceFile "RCHRDNH", // EnclosingMethod "KQH", // ConstantValue "NH[RCH]", // Exceptions "NH[PHH]", // LineNumberTable "NH[PHOHRUHRSHH]", // LocalVariableTable "NH[PHPOHIIH]", // CharacterRangeTable "NH[PHHII]", // CoverageTable "NH[RCHRCNHRUNHFH]", // InnerClasses "NH[RMHNH[KLH]]", // BootstrapMethods "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]", // Code "=AnnotationDefault", // Like metadata, but with a compact tag set: "[NH[(1)]]" +"[NH[(1)]]" +"[RSHNH[RUH(1)]]" +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(-1)](6)[NH[(0)]]()[]]", "" }; ap = 0; } Utils.currentInstance.set(new PackerImpl()); final int[][] counts = new int[2][3]; // int bci ref final Entry[] cpMap = new Entry[maxVal+1]; for (int i = 0; i < cpMap.length; i++) { if (i == 0) continue; // 0 => null cpMap[i] = ConstantPool.getLiteralEntry(new Integer(i)); } Package.Class cls = new Package().new Class(""); cls.cpMap = cpMap; class TestValueStream extends ValueStream { java.util.Random rand = new java.util.Random(0); ArrayList history = new ArrayList(); int ckidx = 0; int maxVal; boolean verbose; void reset() { history.clear(); ckidx = 0; } public int getInt(int bandIndex) { counts[0][0]++; int value = rand.nextInt(maxVal+1); history.add(new Integer(bandIndex)); history.add(new Integer(value)); return value; } public void putInt(int bandIndex, int token) { counts[1][0]++; if (verbose) System.out.print(" "+bandIndex+":"+token); // Make sure this put parallels a previous get: int check0 = ((Integer)history.get(ckidx+0)).intValue(); int check1 = ((Integer)history.get(ckidx+1)).intValue(); if (check0 != bandIndex || check1 != token) { if (!verbose) System.out.println(history.subList(0, ckidx)); System.out.println(" *** Should be "+check0+":"+check1); throw new RuntimeException("Failed test!"); } ckidx += 2; } public Entry getRef(int bandIndex) { counts[0][2]++; int value = getInt(bandIndex); if (value < 0 || value > maxVal) { System.out.println(" *** Unexpected ref code "+value); return ConstantPool.getLiteralEntry(new Integer(value)); } return cpMap[value]; } public void putRef(int bandIndex, Entry ref) { counts[1][2]++; if (ref == null) { putInt(bandIndex, 0); return; } Number refValue = null; if (ref instanceof ConstantPool.NumberEntry) refValue = ((ConstantPool.NumberEntry)ref).numberValue(); int value; if (!(refValue instanceof Integer)) { System.out.println(" *** Unexpected ref "+ref); value = -1; } else { value = ((Integer)refValue).intValue(); } putInt(bandIndex, value); } public int encodeBCI(int bci) { counts[1][1]++; // move LSB to MSB of low byte int code = (bci >> 8) << 8; // keep high bits code += (bci & 0xFE) >> 1; code += (bci & 0x01) << 7; return code ^ (8<<8); // mark it clearly as coded } public int decodeBCI(int bciCode) { counts[0][1]++; bciCode ^= (8<<8); // remove extra mark int bci = (bciCode >> 8) << 8; // keep high bits bci += (bciCode & 0x7F) << 1; bci += (bciCode & 0x80) >> 7; return bci; } } TestValueStream tts = new TestValueStream(); tts.maxVal = maxVal; tts.verbose = verbose; ByteArrayOutputStream buf = new ByteArrayOutputStream(); for (int i = 0; i < (1 << 30); i = (i + 1) * 5) { int ei = tts.encodeBCI(i); int di = tts.decodeBCI(ei); if (di != i) System.out.println("i="+Integer.toHexString(i)+ " ei="+Integer.toHexString(ei)+ " di="+Integer.toHexString(di)); } while (iters-- > 0) { for (int i = ap; i < av.length; i++) { String layout = av[i]; if (layout.startsWith("=")) { String name = layout.substring(1); for (Attribute a : standardDefs.values()) { if (a.name().equals(name)) { layout = a.layout().layout(); break; } } if (layout.startsWith("=")) { System.out.println("Could not find "+name+" in "+standardDefs.values()); } } Layout self = new Layout(0, "Foo", layout); if (verbose) { System.out.print("/"+layout+"/ => "); System.out.println(Arrays.asList(self.elems)); } buf.reset(); tts.reset(); Object fixups = self.unparse(tts, buf); byte[] bytes = buf.toByteArray(); // Attach the references to the byte array. Fixups.setBytes(fixups, bytes); // Patch the references to their frozen values. Fixups.finishRefs(fixups, bytes, new Index("test", cpMap)); if (verbose) { System.out.print(" bytes: {"); for (int j = 0; j < bytes.length; j++) { System.out.print(" "+bytes[j]); } System.out.println("}"); } if (verbose) { System.out.print(" parse: {"); } self.parse(cls, bytes, 0, bytes.length, tts); if (verbose) { System.out.println("}"); } } } for (int j = 0; j <= 1; j++) { System.out.print("values "+(j==0?"read":"written")+": {"); for (int k = 0; k < counts[j].length; k++) { System.out.print(" "+counts[j][k]); } System.out.println(" }"); } } //*/ }
⏎ com/sun/java/util/jar/pack/Attribute.java
Or download all of them as a single archive file:
File name: java.base-11.0.1-src.zip File size: 8740354 bytes Release date: 2018-11-04 Download
2020-05-29, 242861👍, 0💬
Popular Posts:
Jetty provides an HTTP server, HTTP client, and javax.servlet container. These components are open s...
What Is HttpComponents httpcore-4.4.6.jar? HttpComponents httpcore-4.4.6.jar is the JAR file for Apa...
JDK 11 jdk.jdi.jmod is the JMOD file for JDK 11 JDI (Java Debug Interface) tool. JDK 11 JDI tool com...
How to download and install Apache ZooKeeper Source Package? Apache ZooKeeper is an open-source serv...
What Is fop.jar? I got it from the fop-2.7-bin.zip. fop.jar in fop-2.7-bin.zip is the JAR file for F...