auto import from //depot/cupcake/@132589
diff --git a/docs/dalvik-bytecode.html b/docs/dalvik-bytecode.html
index 4945d60..2bbffe6 100644
--- a/docs/dalvik-bytecode.html
+++ b/docs/dalvik-bytecode.html
@@ -1170,7 +1170,7 @@
   <td>float a;<br/>
     int64 result = (int64) a;
   </td>
-  <td>Conversion of <code>float</code> to <code>int64</code>, using
+  <td>Conversion of <code>float</code> to <code>int32</code>, using
     round-toward-zero. The same special case rules as for
     <code>float-to-int</code> apply here, except that out-of-range values
     get converted to either <code>0x7fffffffffffffff</code> or
diff --git a/docs/debugger.html b/docs/debugger.html
deleted file mode 100644
index 6e23f0d..0000000
--- a/docs/debugger.html
+++ /dev/null
@@ -1,211 +0,0 @@
-<html>
-<head>
-<title>Dalvik Debugger Support</title>
-</head>
-
-<body>
-<h1>Dalvik Debugger Support</h1>
-
-<p>
-The Dalvik virtual machine supports source-level debugging with many popular
-development environments.  Any tool that allows remote debugging over JDWP
-(the
-<a href="http://java.sun.com/javase/6/docs/technotes/guides/jpda/jdwp-spec.html">
-Java Debug Wire Protocol</a>) is expected work.  Supported debuggers
-include jdb, Eclipse, IntelliJ, and JSwat.
-</p><p>
-The VM does not support tools based on JVMTI (Java Virtual
-Machine Tool Interface).  This is a relatively intrusive approach that
-relies on bytecode insertion, something the Dalvik VM does not currently
-support.
-</p><p>
-Dalvik's implementation of JDWP also includes hooks for supporting
-DDM (Dalvik Debug Monitor) features, notably as implemented by DDMS
-(Dalvik Debug Monitor Server) and the Eclipse ADT plugin.  The protocol
-and VM interaction is described in some detail
-<a href="debugmon.html">here</a>.
-</p><p>
-All of the debugger support in the VM lives in the <code>dalvik/vm/jdwp</code>
-directory, and is almost entirely isolated from the rest of the VM sources.
-<code>dalvik/vm/Debugger.c</code> bridges the gap.  The goal in doing so
-was to make it easier to re-use the JDWP code in other projects.
-</p><p>
-
-
-<h2>Implementation</h2>
-
-<p>
-Every VM that has debugging enabled starts a "JDWP" thread.  The thread
-typically sits idle until DDMS or a debugger connects.  The thread is
-only responsible for handling requests from the debugger; VM-initated
-communication, such as notifying the debugger when the VM has stopped at
-a breakpoint, are sent from the affected thread.
-</p><p>
-When the VM is embedded in the Android framework,
-debugging is enabled in the VM unless the system property
-<code>ro.secure</code> is set to </code>1</code>.  On these
-"secure" devices, debugging is only enabled in app processes whose
-manifest contains <code>android:debuggable="true"</code> in the
-<code>&lt;application&gt;</code> element.
-
-</p><p>
-The VM recognizes the difference between a connection from DDMS and a
-connection from a debugger (either directly or in concert with DDMS).
-A connection from DDMS alone doesn't result in a change in VM behavior,
-but when the VM sees debugger packets it allocates additional data
-structures and may switch to a different implementation of the interpreter.
-</p><p>
-Because Dalvik maps bytecode into memory read-only, some common
-techniques are difficult to implement without allocating additional memory.
-For example, suppose the debugger sets a breakpoint in a method.  The
-quick way to handle this is to insert a breakpoint instruction directly
-into the code.  When the instruction is reached, the breakpoint handler
-engages.  Without this, it's necessary to perform an "is there a breakpoint
-here" scan.  Even with some optimizations, the debug-enabled interpreter
-is much slower than the regular interpreter (perhaps 5x).
-</p><p>
-The JDWP protocol is stateless, so the VM handles individual debugger
-requests as they arrive, and posts events to the debugger as they happen.
-</p><p>
-
-
-<h2>Debug Data</h2>
-<p> Source code debug data, which includes mappings of source code to
-bytecode and lists describing which registers are used to hold method
-arguments and local variables, are optionally emitted by the Java compiler.
-When <code>dx</code> converts Java bytecode to Dalvik bytecode, it must
-also convert this debug data.
-</p><p>
-<code>dx</code> must also ensure that it doesn't perform operations
-that confuse the debugger.  For example, re-using registers that hold
-method arguments and the "<code>this</code>" pointer is allowed in
-Dalvik bytecode if the values are never used or no longer needed.
-This can be very confusing for the debugger (and the programmer)
-since the values have method scope and aren't expected to disappear.  For
-this reason, <code>dx</code> generates sub-optimal code in some situations
-when debugging support is enabled.
-</p><p>
-Some of the debug data is used for other purposes; in particular, having
-filename and line number data is necessary for generating useful exception
-stack traces.  This data can be omitted by <code>dx</code> to make the DEX
-file smaller.
-</p><p>
-
-
-<h2>Usage</h2>
-
-<p>
-The Dalvik VM supports many of the same command-line flags that other popular
-desktop VMs do.  To start a VM with debugging enabled, you add a command-line
-flag with some basic options.  The basic incantation looks something
-like this:
-
-<pre>-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y</pre>
-or
-<pre>-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y</pre>
-
-</p><p>
-After the initial prefix, options are provided as name=value pairs.  The
-options currently supported by the Dalvik VM are:
-<dl>
-    <dt>transport (no default)</dt>
-    <dd>Communication transport mechanism to use.  Dalvik supports
-    TCP/IP sockets (<code>dt_socket</code>) and connection over USB
-    through ADB (<code>dt_android_adb</code>).
-    </dd>
-
-    <dt>server (default='n')</dt>
-    <dd>Determines whether the VM acts as a client or a server.  When
-    acting as a server, the VM waits for a debugger to connect to it.
-    When acting as a client, the VM attempts to connect to a waiting
-    debugger.
-    </dd>
-
-    <dt>suspend (default='n')</dt>
-    <dd>If set to 'y', the VM will wait for a debugger connection
-    before executing application code.  When the debugger connects (or
-    when the VM finishes connecting to the debugger), the VM tells the
-    debugger that it has suspended, and will not proceed until told
-    to resume.  If set to 'n', the VM just plows ahead.
-    </dd>
-
-    <dt>address (default="")</dt>
-    <dd>This must be <code>hostname:port</code> when <code>server=n</code>,
-    but can be just <code>port</code> when <code>server=y</code>.  This
-    specifies the IP address and port number to connect or listen to.
-    <br>
-    Listening on port 0 has a special meaning: try to
-    listen on port 8000; if that fails, try 8001, 8002, and so on.  (This
-    behavior is non-standard and may be removed from a future release.)
-    <br>This option has no meaning for <code>transport=dt_android_adb</code>.
-    </dd>
-
-    <dt>help (no arguments)</dt>
-    <dd>If this is the only option, a brief usage message is displayed.
-    </dd>
-
-    <dt>launch, onthrow, oncaught, timeout</dt>
-    <dd>These options are accepted but ignored.
-    </dd>
-</dl>
-
-</p><p>
-To debug a program on an Android device using DDMS over USB, you could
-use a command like this:
-<pre>% dalvikvm -agentlib:jdwp=transport=dt_android_adb,suspend=y,server=y -cp /data/foo.jar Foo</pre>
-
-This tells the Dalvik VM to run the program with debugging enabled, listening
-for a connection from DDMS, and waiting for a debugger.  The program will show
-up with an app name of "?" in the process list, because it wasn't started
-from the Android application framework.  From here you would connect your
-debugger to the appropriate DDMS listen port (e.g.
-<code>jdb -attach localhost:8700</code> after selecting it in the app list).
-
-</p><p>
-To debug a program on an Android device using TCP/IP bridged across ADB,
-you would first need to set up forwarding:
-<pre>% adb forward tcp:8000 tcp:8000
-% adb shell dalvikvm -agentlib:jdwp=transport=dt_socket,address=8000,suspend=y,server=y -cp /data/foo.jar Foo</pre>
-and then <code>jdb -attach localhost:8000</code>.
-</p><p>
-(In the above examples, the VM will be suspended when you attach.  In jdb,
-type <code>cont</code> to continue.)
-</p><p>
-The DDMS integration makes the <code>dt_android_adb</code> transport much
-more convenient when debugging on an Android device, but when working with
-Dalvik on the desktop it makes sense to use the TCP/IP transport.
-</p><p>
-
-
-<h2>Known Issues and Limitations</h2>
-
-</p><p>
-Most of the optional features JDWP allows are not implemented.  These
-include field access watchpoints and better tracking of monitors.
-</p><p>
-Not all JDWP requests are implemented.  In particular, anything that
-never gets emitted by the debuggers we've used is not supported and will
-result in error messages being logged.  Support will be added when a
-use case is uncovered.
-</p><p>
-&nbsp;
-</p><p>
-The debugger and garbage collector are somewhat loosely
-integrated at present.  The VM currently guarantees that any object the
-debugger is aware of will not be garbage collected until after the
-debugger disconnects.  This can result in a build-up over time while the
-debugger is connected.
-</p><p>
-The situation is exacerbated by a flaw in the exception processing code,
-which results in nearly all exceptions being added to the "do not discard"
-list, even if the debugger never sees them.  Having a debugger attached
-to a program that throws lots of exceptions can result in out-of-memory
-errors.  This will be fixed in a future release.
-</p><p>
-
-
-<address>Copyright &copy; 2009 The Android Open Source Project</address>
-</p>
-
-</body>
-</html>
diff --git a/docs/instruction-formats.html b/docs/instruction-formats.html
index d7bf690..941689e 100644
--- a/docs/instruction-formats.html
+++ b/docs/instruction-formats.html
@@ -366,15 +366,15 @@
 <tr>
   <td>B|A|<i>op</i> DDCC H|G|F|E</td>
   <td>35fs</td>
-  <td><i>[<code>B=5</code>] <code>op</code></i> {vE, vF, vG, vH, vA},
+  <td><i>[<code>B=5</code>] <code>op</code></i> vB, {vE, vF, vG, vH, vA},
     vtaboff@CC, iface@DD<br/>
-    <i>[<code>B=4</code>] <code>op</code></i> {vE, vF, vG, vH},
+    <i>[<code>B=4</code>] <code>op</code></i> vB, {vE, vF, vG, vH},
     vtaboff@CC, iface@DD<br/>
-    <i>[<code>B=3</code>] <code>op</code></i> {vE, vF, vG},
+    <i>[<code>B=3</code>] <code>op</code></i> vB, {vE, vF, vG},
     vtaboff@CC, iface@DD<br/>
-    <i>[<code>B=2</code>] <code>op</code></i> {vE, vF},
+    <i>[<code>B=2</code>] <code>op</code></i> vB, {vE, vF},
     vtaboff@CC, iface@DD<br/>
-    <i>[<code>B=1</code>] <code>op</code></i> {vE},
+    <i>[<code>B=1</code>] <code>op</code></i> vB, {vE},
     vtaboff@CC, iface@DD<br/>
   </td>
   <td><i>(suggested format for statically linked <code>invoke-interface</code>
diff --git a/docs/libraries.html b/docs/libraries.html
index e1c3035..9fd199c 100644
--- a/docs/libraries.html
+++ b/docs/libraries.html
@@ -34,7 +34,7 @@
 
 <ul>
     <li><a href="#vm-specific">Dalvik VM-specific libraries</a></li>
-    <li><a href="#interop">Java programming language interoperability
+    <li><a href="#interop">Jave programming language interoperability
         libraries</a></li>
 </ul>
 
diff --git a/dx/src/com/android/dx/dex/code/LocalEnd.java b/dx/src/com/android/dx/dex/code/LocalEnd.java
index c19a8dc..87934db 100644
--- a/dx/src/com/android/dx/dex/code/LocalEnd.java
+++ b/dx/src/com/android/dx/dex/code/LocalEnd.java
@@ -29,10 +29,9 @@
 public final class LocalEnd extends ZeroSizeInsn {
     /**
      * non-null; register spec representing the local variable ended
-     * by this instance. <b>Note:</b> Technically, only the register
-     * number needs to be recorded here as the rest of the information
-     * is implicit in the ambient local variable state, but other code
-     * will check the other info for consistency.
+     * by this instance. <b>Note:</b> The only salient part of the spec
+     * is the register number; the rest of the info may be useful for
+     * debugging but shouldn't affect any actual processing
      */
     private final RegisterSpec local;
 
diff --git a/dx/src/com/android/dx/dex/code/LocalList.java b/dx/src/com/android/dx/dex/code/LocalList.java
index 4614fc4..d963fca 100644
--- a/dx/src/com/android/dx/dex/code/LocalList.java
+++ b/dx/src/com/android/dx/dex/code/LocalList.java
@@ -23,9 +23,7 @@
 import com.android.dx.rop.type.Type;
 import com.android.dx.util.FixedSizeList;
 
-import java.io.PrintStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 
 /**
  * List of local variables. Each local variable entry indicates a
@@ -36,9 +34,174 @@
     /** non-null; empty instance */
     public static final LocalList EMPTY = new LocalList(0);
 
-    /** whether to run the self-check code */
-    private static final boolean DEBUG = false;
-    
+    /**
+     * Constructs an instance for the given method, based on the given
+     * block order and intermediate local information.
+     * 
+     * @param insns non-null; instructions to convert
+     * @return non-null; the constructed list 
+     */
+    public static LocalList make(DalvInsnList insns) {
+        ArrayList<Entry> result = new ArrayList<Entry>(100);
+        int codeSize = insns.codeSize();
+        int sz = insns.size();
+        RegisterSpecSet state = null;
+        int stateMax = 0;
+
+        for (int i = 0; i < sz; i++) {
+            DalvInsn insn = insns.get(i);
+
+            if (insn instanceof LocalSnapshot) {
+                RegisterSpecSet newState = ((LocalSnapshot) insn).getLocals();
+                boolean first = (state == null);
+
+                if (first) {
+                    stateMax = newState.getMaxSize();
+                }
+
+                for (int j = 0; j < stateMax; j++) {
+                    RegisterSpec oldSpec = first ? null : state.get(j);
+                    RegisterSpec newSpec = newState.get(j);
+                    boolean oldEnds = false;
+                    boolean newStarts = false;
+
+                    if (oldSpec == null) {
+                        if (newSpec != null) {
+                            /*
+                             * This is a newly-introduced local, not
+                             * replacing an existing local.
+                             */
+                            newStarts = true;
+                        }
+                    } else if (newSpec == null) {
+                        /*
+                         * This is a local going out of scope, with no
+                         * replacement.
+                         */
+                        oldEnds = true;
+                    } else if (!oldSpec.equals(newSpec)) {
+                        /*
+                         * This is a local going out of scope, immediately
+                         * replaced by a different local.
+                         */
+                        oldEnds = true;
+                        newStarts = true;
+                    }
+
+                    if (oldEnds) {
+                        endScope(result, oldSpec, insn.getAddress());
+                    }
+
+                    if (newStarts) {
+                        startScope(result, newSpec, insn.getAddress(),
+                                   codeSize);
+                    }
+                }
+
+                state = newState;
+            } else if (insn instanceof LocalStart) {
+                RegisterSpec newSpec = ((LocalStart) insn).getLocal();
+                RegisterSpec oldSpec = state.get(newSpec);
+
+                boolean oldEnds = false;
+                boolean newStarts = false;
+
+                if (oldSpec == null) {
+                    /*
+                     * This is a newly-introduced local, not replacing an
+                     * existing local.
+                     */
+                    newStarts = true;
+                } else if (!oldSpec.equals(newSpec)) {
+                    /*
+                     * This is a local going out of scope, immediately
+                     * replaced by a different local.
+                     */
+                    oldEnds = true;
+                    newStarts = true;
+                }
+
+                if (newStarts) {
+                    int address = insn.getAddress();
+
+                    if (oldEnds) {
+                        endScope(result, oldSpec, address);
+                    }
+
+                    startScope(result, newSpec, address, codeSize);
+
+                    if (state.isImmutable()) {
+                        state = state.mutableCopy();
+                    }
+
+                    state.put(newSpec);
+                }
+            }
+        }
+
+        int resultSz = result.size();
+
+        if (resultSz == 0) {
+            return EMPTY;
+        }
+
+        LocalList resultList = new LocalList(resultSz);
+
+        for (int i = 0; i < resultSz; i++) {
+            resultList.set(i, result.get(i));
+        }
+
+        resultList.setImmutable();
+        return resultList;
+    }
+
+    /**
+     * Helper for {@link #make}, to indicate that the given variable has
+     * been introduced.
+     * 
+     * @param result non-null; result in-progress
+     * @param spec non-null; register spec for the variable in question
+     * @param startAddress &gt;= 0; address at which the scope starts
+     * (inclusive)
+     * @param endAddress &gt; startAddress; initial scope end address
+     * (exclusive)
+     */
+    private static void startScope(ArrayList<Entry> result, RegisterSpec spec,
+                                   int startAddress, int endAddress) {
+        result.add(new Entry(startAddress, endAddress, spec));
+    }
+
+    /**
+     * Helper for {@link #make}, to indicate that the given variable's
+     * scope has closed.
+     * 
+     * @param result non-null; result in-progress
+     * @param spec non-null; register spec for the variable in question
+     * @param endAddress &gt;= 0; address at which the scope ends (exclusive)
+     */
+    private static void endScope(ArrayList<Entry> result, RegisterSpec spec,
+                                 int endAddress) {
+        int sz = result.size();
+
+        for (int i = sz - 1; i >= 0; i--) {
+            Entry e = result.get(i);
+            if (e.matches(spec)) {
+                if (e.getStart() == endAddress) {
+                    /*
+                     * It turns out that the indicated entry doesn't actually
+                     * cover any code.
+                     */
+                    result.remove(i);
+                } else {
+                    result.set(i, e.withEnd(endAddress));
+                }
+                return;
+            }
+        }
+
+        throw new RuntimeException("unmatched variable: " + spec);
+    }
+
     /**
      * Constructs an instance. All indices initially contain <code>null</code>.
      * 
@@ -64,6 +227,18 @@
      * Sets the entry at the given index.
      * 
      * @param n &gt;= 0, &lt; size(); which index
+     * @param start &gt;= 0; start address 
+     * @param end &gt; start; end address (exclusive)
+     * @param spec non-null; register spec representing the variable
+     */
+    public void set(int n, int start, int end, RegisterSpec spec) {
+        set0(n, new Entry(start, end, spec));
+    }
+
+    /**
+     * Sets the entry at the given index.
+     * 
+     * @param n &gt;= 0, &lt; size(); which index
      * @param entry non-null; the entry to set at <code>n</code>
      */
     public void set(int n, Entry entry) {
@@ -71,79 +246,35 @@
     }
 
     /**
-     * Does a human-friendly dump of this instance.
-     * 
-     * @param out non-null; where to dump
-     * @param prefix non-null; prefix to attach to each line of output
-     */
-    public void debugPrint(PrintStream out, String prefix) {
-        int sz = size();
-
-        for (int i = 0; i < sz; i++) {
-            out.print(prefix);
-            out.println(get(i));
-        }
-    }
-
-    /**
-     * Disposition of a local entry.
-     */
-    public static enum Disposition {
-        /** local started (introduced) */
-        START, 
-
-        /** local ended without being replaced */
-        END_SIMPLY,
-
-        /** local ended because it was directly replaced */
-        END_REPLACED,
-
-        /** local ended because it was moved to a different register */
-        END_MOVED,
-
-        /**
-         * local ended because the previous local clobbered this one
-         * (because it is category-2)
-         */
-        END_CLOBBERED_BY_PREV,
-
-        /**
-         * local ended because the next local clobbered this one
-         * (because this one is a category-2)
-         */
-        END_CLOBBERED_BY_NEXT;
-    }
-
-    /**
      * Entry in a local list.
      */
-    public static class Entry implements Comparable<Entry> {
-        /** &gt;= 0; address */
-        private final int address;
+    public static class Entry {
+        /** &gt;= 0; start address */
+        private final int start;
 
-        /** non-null; disposition of the local */
-        private final Disposition disposition;
+        /** &gt; start; end address (exclusive) */
+        private final int end;
 
         /** non-null; register spec representing the variable */
         private final RegisterSpec spec;
 
-        /** non-null; variable type (derived from {@code spec}) */
+        /** non-null; variable type */
         private final CstType type;
-        
+
         /**
          * Constructs an instance.
          * 
-         * @param address &gt;= 0; address 
-         * @param disposition non-null; disposition of the local
+         * @param start &gt;= 0; start address 
+         * @param end &gt; start; end address (exclusive)
          * @param spec non-null; register spec representing the variable
          */
-        public Entry(int address, Disposition disposition, RegisterSpec spec) {
-            if (address < 0) {
-                throw new IllegalArgumentException("address < 0");
+        public Entry(int start, int end, RegisterSpec spec) {
+            if (start < 0) {
+                throw new IllegalArgumentException("start < 0");
             }
 
-            if (disposition == null) {
-                throw new NullPointerException("disposition == null");
+            if (end <= start) {
+                throw new IllegalArgumentException("end <= start");
             }
 
             try {
@@ -156,78 +287,37 @@
                 throw new NullPointerException("spec == null");
             }
 
-            this.address = address;
-            this.disposition = disposition;
+            this.start = start;
+            this.end = end;
             this.spec = spec;
-            this.type = CstType.intern(spec.getType());
-        }
 
-        /** {@inheritDoc} */
-        public String toString() {
-            return Integer.toHexString(address) + " " + disposition + " " +
-                spec;
-        }
-
-        /** {@inheritDoc} */
-        public boolean equals(Object other) {
-            if (!(other instanceof Entry)) {
-                return false;
+            if (spec.getType() == Type.KNOWN_NULL) {
+                /*
+                 * KNOWN_NULL's descriptor is '<null>', which we do
+                 * not want to emit. Everything else is as expected.
+                 */
+                this.type = CstType.OBJECT;
+            } else {
+                this.type = CstType.intern(spec.getType());
             }
-
-            return (compareTo((Entry) other) == 0);
         }
 
         /**
-         * Compares by (in priority order) address, end then start
-         * disposition (variants of end are all consistered
-         * equivalent), and spec.
+         * Gets the start address.
          * 
-         * @param other non-null; entry to compare to
-         * @return {@code -1..1}; standard result of comparison
+         * @return &gt;= 0; the start address
          */
-        public int compareTo(Entry other) {
-            if (address < other.address) {
-                return -1;
-            } else if (address > other.address) {
-                return 1;
-            }
-
-            boolean thisIsStart = isStart();
-            boolean otherIsStart = other.isStart();
-            
-            if (thisIsStart != otherIsStart) {
-                return thisIsStart ? 1 : -1;
-            }
-
-            return spec.compareTo(other.spec);
+        public int getStart() {
+            return start;
         }
 
         /**
-         * Gets the address.
+         * Gets the end address (exclusive).
          * 
-         * @return &gt;= 0; the address
+         * @return &gt; start; the end address (exclusive)
          */
-        public int getAddress() {
-            return address;
-        }
-
-        /**
-         * Gets the disposition.
-         * 
-         * @return non-null; the disposition
-         */
-        public Disposition getDisposition() {
-            return disposition;
-        }
-
-        /**
-         * Gets whether this is a local start. This is just shorthand for
-         * {@code getDisposition() == Disposition.START}.
-         * 
-         * @return {@code true} iff this is a start
-         */
-        public boolean isStart() {
-            return disposition == Disposition.START;
+        public int getEnd() {
+            return end;
         }
 
         /**
@@ -282,8 +372,8 @@
          * @return <code>true</code> iff this instance matches
          * <code>spec</code>
          */
-        public boolean matches(RegisterSpec otherSpec) {
-            return spec.equalsUsingSimpleType(otherSpec);
+        public boolean matches(RegisterSpec spec) {
+            return spec.equals(this.spec);
         }
 
         /**
@@ -295,619 +385,18 @@
          * <code>other</code>
          */
         public boolean matches(Entry other) {
-            return matches(other.spec);
+            return other.spec.equals(this.spec);
         }
 
         /**
-         * Returns an instance just like this one but with the disposition
-         * set as given
+         * Returns an instance just like this one, except with the end
+         * address altered to be the one given.
          * 
-         * @param disposition non-null; the new disposition
+         * @param newEnd &gt; getStart(); the end address of the new instance
          * @return non-null; an appropriately-constructed instance
          */
-        public Entry withDisposition(Disposition disposition) {
-            if (disposition == this.disposition) {
-                return this;
-            }
-            
-            return new Entry(address, disposition, spec);
+        public Entry withEnd(int newEnd) {
+            return new Entry(start, newEnd, spec);
         }
     }
-    
-    /**
-     * Constructs an instance for the given method, based on the given
-     * block order and intermediate local information.
-     * 
-     * @param insns non-null; instructions to convert
-     * @return non-null; the constructed list 
-     */
-    public static LocalList make(DalvInsnList insns) {
-        int sz = insns.size();
-
-        /*
-         * Go through the insn list, looking for all the local
-         * variable pseudoinstructions, splitting out LocalSnapshots
-         * into separate per-variable starts, adding explicit ends
-         * wherever a variable is replaced or moved, and collecting
-         * these and all the other local variable "activity"
-         * together into an output list (without the other insns). 
-         * 
-         * Note: As of this writing, this method won't be handed any
-         * insn lists that contain local ends, but I (danfuzz) expect
-         * that to change at some point, when we start feeding that
-         * info explicitly into the rop layer rather than only trying
-         * to infer it. So, given that expectation, this code is
-         * written to deal with them.
-         */
-
-        MakeState state = new MakeState(sz);
-
-        for (int i = 0; i < sz; i++) {
-            DalvInsn insn = insns.get(i);
-
-            if (insn instanceof LocalSnapshot) {
-                RegisterSpecSet snapshot =
-                    ((LocalSnapshot) insn).getLocals();
-                state.snapshot(insn.getAddress(), snapshot);
-            } else if (insn instanceof LocalStart) {
-                RegisterSpec local = ((LocalStart) insn).getLocal();
-                state.startLocal(insn.getAddress(), local);
-            } else if (insn instanceof LocalEnd) {
-                RegisterSpec local = ((LocalEnd) insn).getLocal();
-                state.endLocal(insn.getAddress(), local);
-            }
-        }
-
-        LocalList result = state.finish();
-
-        if (DEBUG) {
-            debugVerify(result);
-        }
-
-        return result;
-    }
-
-    /**
-     * Debugging helper that verifies the constraint that a list doesn't
-     * contain any redundant local starts and that local ends that are
-     * due to replacements are properly annotated.
-     */
-    private static void debugVerify(LocalList locals) {
-        try {
-            debugVerify0(locals);
-        } catch (RuntimeException ex) {
-            int sz = locals.size();
-            for (int i = 0; i < sz; i++) {
-                System.err.println(locals.get(i));
-            }
-            throw ex;
-        }
-            
-    }
-    
-    /**
-     * Helper for {@link #debugVerify} which does most of the work.
-     */
-    private static void debugVerify0(LocalList locals) {
-        int sz = locals.size();
-        Entry[] active = new Entry[65536];
-
-        for (int i = 0; i < sz; i++) {
-            Entry e = locals.get(i);
-            int reg = e.getRegister();
-
-            if (e.isStart()) {
-                Entry already = active[reg];
-
-                if ((already != null) && e.matches(already)) {
-                    throw new RuntimeException("redundant start at " +
-                            Integer.toHexString(e.getAddress()) + ": got " +
-                            e + "; had " + already);
-                }
-
-                active[reg] = e;
-            } else {
-                if (active[reg] == null) {
-                    throw new RuntimeException("redundant end at " +
-                            Integer.toHexString(e.getAddress()));
-                }
-                
-                int addr = e.getAddress();
-                boolean foundStart = false;
-
-                for (int j = i + 1; j < sz; j++) {
-                    Entry test = locals.get(j);
-                    if (test.getAddress() != addr) {
-                        break;
-                    }
-                    if (test.getRegisterSpec().getReg() == reg) {
-                        if (test.isStart()) {
-                            if (e.getDisposition()
-                                    != Disposition.END_REPLACED) {
-                                throw new RuntimeException(
-                                        "improperly marked end at " +
-                                        Integer.toHexString(addr));
-                            }
-                            foundStart = true;
-                        } else {
-                            throw new RuntimeException(
-                                    "redundant end at " +
-                                    Integer.toHexString(addr));
-                        }                            
-                    }
-                }
-
-                if (!foundStart &&
-                        (e.getDisposition() == Disposition.END_REPLACED)) {
-                    throw new RuntimeException(
-                            "improper end replacement claim at " +
-                            Integer.toHexString(addr));
-                }
-                    
-                active[reg] = null;
-            }
-        }
-    }
-
-    /**
-     * Intermediate state when constructing a local list.
-     */
-    public static class MakeState {
-        /** non-null; result being collected */
-        private final ArrayList<Entry> result;
-
-        /**
-         * &gt;= 0; running count of nulled result entries, to help with
-         * sizing the final list
-         */
-        private int nullResultCount;
-
-        /** null-ok; current register mappings */
-        private RegisterSpecSet regs;
-
-        /** null-ok; result indices where local ends are stored */
-        private int[] endIndices;
-
-        /** &gt;= 0; last address seen */
-        private int lastAddress;
-
-        /**
-         * &gt;= 0; result index where the first element for the most
-         * recent address is stored
-         */
-        private int startIndexForAddress;
-
-        /**
-         * Constructs an instance.
-         */
-        public MakeState(int initialSize) {
-            result = new ArrayList<Entry>(initialSize);
-            nullResultCount = 0;
-            regs = null;
-            endIndices = null;
-            lastAddress = 0;
-            startIndexForAddress = 0;
-        }
-
-        /**
-         * Checks the address and other vitals as a prerequisite to
-         * further processing.
-         *
-         * @param address &gt;= 0; address about to be processed
-         * @param reg &gt;= 0; register number about to be processed
-         */
-        private void aboutToProcess(int address, int reg) {
-            boolean first = (endIndices == null);
-            
-            if ((address == lastAddress) && !first) {
-                return;
-            }
-
-            if (address < lastAddress) {
-                throw new RuntimeException("shouldn't happen");
-            }
-
-            if (first || (reg >= endIndices.length)) {
-                /*
-                 * This is the first allocation of the state set and
-                 * index array, or we need to grow. (The latter doesn't
-                 * happen much; in fact, we have only ever observed
-                 * it happening in test cases, never in "real" code.)
-                 */
-                int newSz = reg + 1;
-                RegisterSpecSet newRegs = new RegisterSpecSet(newSz);
-                int[] newEnds = new int[newSz];
-                Arrays.fill(newEnds, -1);
-
-                if (!first) {
-                    newRegs.putAll(regs);
-                    System.arraycopy(endIndices, 0, newEnds, 0,
-                            endIndices.length);
-                }
-
-                regs = newRegs;
-                endIndices = newEnds;
-            }
-        }
-
-        /**
-         * Sets the local state at the given address to the given snapshot.
-         * The first call on this instance must be to this method, so that
-         * the register state can be properly sized.
-         * 
-         * @param address &gt;= 0; the address
-         * @param specs non-null; spec set representing the locals
-         */
-        public void snapshot(int address, RegisterSpecSet specs) {
-            int sz = specs.getMaxSize();
-            aboutToProcess(address, sz - 1);
-
-            for (int i = 0; i < sz; i++) {
-                RegisterSpec oldSpec = regs.get(i);
-                RegisterSpec newSpec = filterSpec(specs.get(i));
-
-                if (oldSpec == null) {
-                    if (newSpec != null) {
-                        startLocal(address, newSpec);
-                    }
-                } else if (newSpec == null) {
-                    endLocal(address, oldSpec);
-                } else if (! newSpec.equalsUsingSimpleType(oldSpec)) {
-                    endLocal(address, oldSpec);
-                    startLocal(address, newSpec);
-                }
-            }
-        }
-        
-        /**
-         * Starts a local at the given address.
-         * 
-         * @param address &gt;= 0; the address
-         * @param startedLocal non-null; spec representing the started local
-         */
-        public void startLocal(int address, RegisterSpec startedLocal) {
-            int regNum = startedLocal.getReg();
-
-            startedLocal = filterSpec(startedLocal);
-            aboutToProcess(address, regNum);
-
-            RegisterSpec existingLocal = regs.get(regNum);
-
-            if (startedLocal.equalsUsingSimpleType(existingLocal)) {
-                // Silently ignore a redundant start.
-                return;
-            }
-
-            RegisterSpec movedLocal = regs.findMatchingLocal(startedLocal);
-            if (movedLocal != null) {
-                /*
-                 * The same variable was moved from one register to another.
-                 * So add an end for its old location.
-                 */
-                addOrUpdateEnd(address, Disposition.END_MOVED, movedLocal);
-            }
-
-            int endAt = endIndices[regNum];
-            
-            if (existingLocal != null) {
-                /*
-                 * There is an existing (but non-matching) local.
-                 * Add an explicit end for it.
-                 */
-                add(address, Disposition.END_REPLACED, existingLocal);
-            } else if (endAt >= 0) {
-                /*
-                 * Look for an end local for the same register at the
-                 * same address. If found, then update it or delete
-                 * it, depending on whether or not it represents the
-                 * same variable as the one being started.
-                 */
-                Entry endEntry = result.get(endAt);
-                if (endEntry.getAddress() == address) {
-                    if (endEntry.matches(startedLocal)) {
-                        /*
-                         * There was already an end local for the same
-                         * variable at the same address. This turns
-                         * out to be superfluous, as we are starting
-                         * up the exact same local. This situation can
-                         * happen when a single local variable got
-                         * somehow "split up" during intermediate
-                         * processing. In any case, rather than represent
-                         * the end-then-start, just remove the old end.
-                         */
-                        result.set(endAt, null);
-                        nullResultCount++;
-                        regs.put(startedLocal);
-                        endIndices[regNum] = -1;
-                        return;
-                    } else {
-                        /*
-                         * There was a different variable ended at the
-                         * same address. Update it to indicate that
-                         * it was ended due to a replacement (rather than
-                         * ending for no particular reason).
-                         */
-                        endEntry = endEntry.withDisposition(
-                                Disposition.END_REPLACED);
-                        result.set(endAt, endEntry);
-                    }
-                }
-            }
-                                
-            /* 
-             * The code above didn't find and remove an unnecessary
-             * local end, so we now have to add one or more entries to
-             * the output to capture the transition.
-             */
-
-            /*
-             * If the local just below (in the register set at reg-1)
-             * is of category-2, then it is ended by this new start.
-             */
-            if (regNum > 0) {
-                RegisterSpec justBelow = regs.get(regNum - 1);
-                if ((justBelow != null) && justBelow.isCategory2()) {
-                    addOrUpdateEnd(address,
-                            Disposition.END_CLOBBERED_BY_NEXT,
-                            justBelow);
-                }
-            }
-
-            /*
-             * Similarly, if this local is category-2, then the local
-             * just above (if any) is ended by the start now being
-             * emitted.
-             */
-            if (startedLocal.isCategory2()) {
-                RegisterSpec justAbove = regs.get(regNum + 1);
-                if (justAbove != null) {
-                    addOrUpdateEnd(address,
-                            Disposition.END_CLOBBERED_BY_PREV,
-                            justAbove);
-                }
-            }
-
-            /*
-             * TODO: Add an end for the same local in a different reg,
-             * if any (that is, if the local migrates from vX to vY,
-             * we should note that as a local end in vX).
-             */
-            
-            add(address, Disposition.START, startedLocal);
-        }
-
-        /**
-         * Ends a local at the given address.
-         *
-         * @param address &gt;= 0; the address
-         * @param endedLocal non-null; spec representing the local being ended
-         */
-        public void endLocal(int address, RegisterSpec endedLocal) {
-            int regNum = endedLocal.getReg();
-
-            endedLocal = filterSpec(endedLocal);
-            aboutToProcess(address, regNum);
-
-            int endAt = endIndices[regNum];
-
-            if (endAt >= 0) {
-                /*
-                 * The local in the given register is already ended.
-                 * Silently return without adding anything to the result.
-                 */
-                return;
-            }
-
-            // Check for start and end at the same address.
-            if (checkForEmptyRange(address, endedLocal)) {
-                return;
-            }
-
-            add(address, Disposition.END_SIMPLY, endedLocal);
-        }
-
-        /**
-         * Helper for {@link #endLocal}, which handles the cases where
-         * and end local is issued at the same address as a start local
-         * for the same register. If this case is found, then this
-         * method will remove the start (as the local was never actually
-         * active), update the {@link #endIndices} to be accurate, and
-         * if needed update the newly-active end to reflect an altered
-         * disposition.
-         * 
-         * @param address &gt;= 0; the address
-         * @param endedLocal non-null; spec representing the local being ended
-         * @return {@code true} iff this method found the case in question
-         * and adjusted things accordingly
-         */
-        private boolean checkForEmptyRange(int address,
-                RegisterSpec endedLocal) {
-            int at = result.size() - 1;
-            Entry entry;
-
-            // Look for a previous entry at the same address.
-            for (/*at*/; at >= 0; at--) {
-                entry = result.get(at);
-
-                if (entry == null) {
-                    continue;
-                }
-
-                if (entry.getAddress() != address) {
-                    // We didn't find any match at the same address.
-                    return false;
-                }
-
-                if (entry.matches(endedLocal)) {
-                    break;
-                }
-            }
-
-            /*
-             * In fact, we found that the endedLocal had started at the
-             * same address, so do all the requisite cleanup.
-             */
-            
-            regs.remove(endedLocal);
-            result.set(at, null);
-            nullResultCount++;
-
-            int regNum = endedLocal.getReg();
-            boolean found = false;
-            entry = null;
-
-            // Now look back further to update where the register ended.
-            for (at--; at >= 0; at--) {
-                entry = result.get(at);
-
-                if (entry == null) {
-                    continue;
-                }
-
-                if (entry.getRegisterSpec().getReg() == regNum) {
-                    found = true;
-                    break;
-                }
-            }
-
-            if (found) {
-                // We found an end for the same register.
-                endIndices[regNum] = at;
-                   
-                if (entry.getAddress() == address) {
-                    /*
-                     * It's still the same address, so update the
-                     * disposition.
-                     */
-                    result.set(at,
-                            entry.withDisposition(Disposition.END_SIMPLY));
-                }
-            }
-
-            return true;
-        }
-
-        /**
-         * Converts a given spec into the form acceptable for use in a
-         * local list. This, in particular, transforms the "known
-         * null" type into simply {@code Object}. This method needs to
-         * be called for any spec that is on its way into a locals
-         * list.
-         * 
-         * <p>This isn't necessarily the cleanest way to achieve the
-         * goal of not representing known nulls in a locals list, but
-         * it gets the job done.</p>
-         * 
-         * @param orig null-ok; the original spec
-         * @return null-ok; an appropriately modified spec, or the
-         * original if nothing needs to be done
-         */
-        private static RegisterSpec filterSpec(RegisterSpec orig) {
-            if ((orig != null) && (orig.getType() == Type.KNOWN_NULL)) {
-                return orig.withType(Type.OBJECT);
-            }
-
-            return orig;
-        }
-
-        /**
-         * Adds an entry to the result, updating the adjunct tables
-         * accordingly.
-         *
-         * @param address &gt;= 0; the address
-         * @param disposition non-null; the disposition
-         * @param spec non-null; spec representing the local
-         */
-        private void add(int address, Disposition disposition,
-                RegisterSpec spec) {
-            int regNum = spec.getReg();
-
-            result.add(new Entry(address, disposition, spec));
-
-            if (disposition == Disposition.START) {
-                regs.put(spec);
-                endIndices[regNum] = -1;
-            } else {
-                regs.remove(spec);
-                endIndices[regNum] = result.size() - 1;
-            }
-        }
-
-        /**
-         * Adds or updates an end local (changing its disposition).
-         * 
-         * @param address &gt;= 0; the address
-         * @param disposition non-null; the disposition
-         * @param spec non-null; spec representing the local
-         */
-        private void addOrUpdateEnd(int address, Disposition disposition,
-                RegisterSpec spec) {
-            if (disposition == Disposition.START) {
-                throw new RuntimeException("shouldn't happen");
-            }
-
-            int regNum = spec.getReg();
-            int endAt = endIndices[regNum];
-
-            if (endAt >= 0) {
-                Entry endEntry = result.get(endAt);
-                if ((endEntry.getAddress() == address) &&
-                        endEntry.getRegisterSpec().equals(spec)) {
-                    result.set(endAt, endEntry.withDisposition(disposition));
-                    regs.remove(spec);
-                    return;
-                }
-            }
-                
-            add(address, disposition, spec);
-        }
-
-        /**
-         * Finishes processing altogether and gets the result.
-         * 
-         * @return non-null; the result list
-         */
-        public LocalList finish() {
-            aboutToProcess(Integer.MAX_VALUE, 0);
-
-            int resultSz = result.size();
-            int finalSz = resultSz - nullResultCount;
-            
-            if (finalSz == 0) {
-                return EMPTY;
-            }
-
-            /*
-             * Collect an array of only the non-null entries, and then
-             * sort it to get a consistent order for everything: Local
-             * ends and starts for a given address could come in any
-             * order, but we want ends before starts as well as
-             * registers in order (within ends or starts).
-             */
-
-            Entry[] resultArr = new Entry[finalSz];
-
-            if (resultSz == finalSz) {
-                result.toArray(resultArr);
-            } else {
-                int at = 0;
-                for (Entry e : result) {
-                    if (e != null) {
-                        resultArr[at++] = e;
-                    }
-                }
-            }
-
-            Arrays.sort(resultArr);
-
-            LocalList resultList = new LocalList(finalSz);
-
-            for (int i = 0; i < finalSz; i++) {
-                resultList.set(i, resultArr[i]);
-            }
-
-            resultList.setImmutable();
-            return resultList;
-        }
-    }    
 }
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
index 3ffd276..519452b 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
@@ -16,8 +16,6 @@
 
 package com.android.dx.dex.file;
 
-import com.android.dx.dex.code.DalvCode;
-import com.android.dx.dex.code.DalvInsnList;
 import com.android.dx.dex.code.LocalList;
 import com.android.dx.dex.code.PositionList;
 import com.android.dx.rop.cst.CstMethodRef;
@@ -43,28 +41,20 @@
 public class DebugInfoDecoder {
     /** encoded debug info */
     private final byte[] encoded;
-
     /** positions decoded */
     private final ArrayList<PositionEntry> positions;
-
     /** locals decoded */
     private final ArrayList<LocalEntry> locals;
-
     /** size of code block in code units */
     private final int codesize;
-
     /** indexed by register, the last local variable live in a reg */
     private final LocalEntry[] lastEntryForReg;
-
     /** method descriptor of method this debug info is for */
     private final Prototype desc;
-
     /** true if method is static */
     private final boolean isStatic;
-
     /** dex file this debug info will be stored in */
     private final DexFile file;
-
     /**
      * register size, in register units, of the register space
      * used by this method
@@ -91,11 +81,8 @@
      * @param ref method descriptor of method this debug info is for
      * @param file dex file this debug info will be stored in
      */
-    DebugInfoDecoder(byte[] encoded, int codesize, int regSize,
+    DebugInfoDecoder (byte[] encoded, int codesize, int regSize,
             boolean isStatic, CstMethodRef ref, DexFile file) {
-        if (encoded == null) {
-            throw new NullPointerException("encoded == null");
-        }
 
         this.encoded = encoded;
         this.isStatic = isStatic;
@@ -103,37 +90,24 @@
         this.file = file;
         this.regSize = regSize;
         
-        positions = new ArrayList<PositionEntry>();
-        locals = new ArrayList<LocalEntry>();
+        positions = new ArrayList();
+        locals = new ArrayList();
         this.codesize = codesize;
         lastEntryForReg = new LocalEntry[regSize];
 
-        int idx = -1;
-
-        try {
-            idx = file.getStringIds().indexOf(new CstUtf8("this"));
-        } catch (IllegalArgumentException ex) {
-            /*
-             * Silently tolerate not finding "this". It just means that
-             * no method has local variable info that looks like
-             * a standard instance method.
-             */
-        }
-
-        thisStringIdx = idx;
+        thisStringIdx = file.getStringIds().indexOf(new CstUtf8("this"));
     }
 
     /**
      * An entry in the resulting postions table
      */
-    static private class PositionEntry {
+    static class PositionEntry {
         /** bytecode address */
-        public int address;
-
+        int address;
         /** line number */
-        public int line;
+        int line;
 
-        public PositionEntry(int address, int line) {
+        PositionEntry(int address, int line) {
             this.address = address;
             this.line = line;
         }
@@ -142,40 +116,37 @@
     /**
      * An entry in the resulting locals table
      */
-    static private class LocalEntry {
-        /** address of event */
-        public int address;
-
-        /** {@code true} iff it's a local start */
-        public boolean isStart;
-
-        /** register number */
-        public int reg;
-
-        /** index of name in strings table */
-        public int nameIndex;
-
-        /** index of type in types table */
-        public int typeIndex;
-
-        /** index of type signature in strings table */
-        public int signatureIndex;
-
-        public LocalEntry(int address, boolean isStart, int reg, int nameIndex,
-                int typeIndex, int signatureIndex) {
-            this.address        = address;
-            this.isStart        = isStart;
+    static class LocalEntry {
+        LocalEntry(int start, int reg, int nameIndex, int typeIndex,
+                int signatureIndex) {
+            this.start          = start;
             this.reg            = reg;
             this.nameIndex      = nameIndex;
             this.typeIndex      = typeIndex;
             this.signatureIndex = signatureIndex;
         }
 
-        public String toString() {
-            return String.format("[%x %s v%d %04x %04x %04x]",
-                    address, isStart ? "start" : "end", reg,
-                    nameIndex, typeIndex, signatureIndex);
-        }
+        /** start of address range */
+        int start;
+
+        /**
+         * End of address range. Initialized to MAX_VALUE here but will
+         * be set to no more than 1 + max bytecode address of method.
+         */
+        int end = Integer.MAX_VALUE;
+
+        /** register number */
+        int reg;
+
+        /** index of name in strings table */
+        int nameIndex;
+
+        /** index of type in types table */
+        int typeIndex;
+
+        /** index of type signature in strings table */
+        int signatureIndex;
+
     }
 
     /**
@@ -195,6 +166,13 @@
      * @return locals list in ascending address order.
      */
     public List<LocalEntry> getLocals() {
+        // TODO move this loop:
+        // Any variable that didnt end ends now
+        for (LocalEntry local: locals) {
+            if (local.end == Integer.MAX_VALUE) {
+                local.end = codesize;
+            }
+        }
         return locals;
     }
 
@@ -251,8 +229,8 @@
         
         if (!isStatic) {
             // Start off with implicit 'this' entry
-            LocalEntry thisEntry =
-                new LocalEntry(0, true, curReg, thisStringIdx, 0, 0);
+            LocalEntry thisEntry
+                    = new LocalEntry(0, curReg, thisStringIdx, 0, 0);
             locals.add(thisEntry);
             lastEntryForReg[curReg] = thisEntry;
             curReg++;
@@ -264,19 +242,15 @@
 
             int nameIdx = readStringIndex(bs);
 
-            if (nameIdx == -1) {
-                /*
-                 * Unnamed parameter; often but not always filled in by an
-                 * extended start op after the prologue
-                 */
-                le = new LocalEntry(0, true, curReg, -1, 0, 0);
+            if(nameIdx == -1) {
+                // unnamed parameter
             } else {
-                // TODO: Final 0 should be idx of paramType.getDescriptor().
-                le = new LocalEntry(0, true, curReg, nameIdx, 0, 0);
+                // final '0' should be idx of paramType.getDescriptor()
+                le = new LocalEntry(0, curReg, nameIdx, 0, 0);
+                locals.add(le);
+                lastEntryForReg[curReg] = le;
             }
 
-            locals.add(le);
-            lastEntryForReg[curReg] = le;
             curReg += paramType.getCategory();
         }
 
@@ -295,7 +269,15 @@
                     int nameIdx = readStringIndex(bs);
                     int typeIdx = readStringIndex(bs);
                     LocalEntry le = new LocalEntry(
-                            address, true, reg, nameIdx, typeIdx, 0);
+                            address, reg, nameIdx, typeIdx, 0);
+
+                    // a "start" is implicitly the "end" of whatever was
+                    // previously defined in the register
+                    if (lastEntryForReg[reg] != null
+                            && lastEntryForReg[reg].end == Integer.MAX_VALUE) {
+
+                        lastEntryForReg[reg].end = address;
+                    }
 
                     locals.add(le);
                     lastEntryForReg[reg] = le;
@@ -308,7 +290,21 @@
                     int typeIdx = readStringIndex(bs);
                     int sigIdx = readStringIndex(bs);
                     LocalEntry le = new LocalEntry(
-                            address, true, reg, nameIdx, typeIdx, sigIdx);
+                            address, reg, nameIdx, typeIdx, sigIdx);
+
+                    // a "start" is implicitly the "end" of whatever was
+                    // previously defined in the register
+                    if (lastEntryForReg[reg] != null
+                            && lastEntryForReg[reg].end == Integer.MAX_VALUE) {
+
+                        lastEntryForReg[reg].end = address;
+
+                        // A 0-length entry. Almost certainly a "this"
+                        // with a signature.
+                        if (lastEntryForReg[reg].start == address) {
+                            locals.remove(lastEntryForReg[reg]);
+                        }
+                    }
 
                     locals.add(le);
                     lastEntryForReg[reg] = le;
@@ -323,17 +319,16 @@
                     try {
                         prevle = lastEntryForReg[reg];
 
-                        if (prevle.isStart) {
-                            throw new RuntimeException("nonsensical "
-                                    + "RESTART_LOCAL on live register v"
-                                    + reg);
+                        if (lastEntryForReg[reg].end == Integer.MAX_VALUE) {
+                            throw new RuntimeException ("nonsensical "
+                                    + "RESTART_LOCAL on live register v"+reg);
                         }
-
-                        le = new LocalEntry(address, true, reg,
+                        le = new LocalEntry(address, reg,
                                 prevle.nameIndex, prevle.typeIndex, 0);
+
                     } catch (NullPointerException ex) {
-                        throw new RuntimeException(
-                                "Encountered RESTART_LOCAL on new v" + reg);
+                        throw new RuntimeException
+                                ("Encountered RESTART_LOCAL on new v" +reg);
                     }
 
                     locals.add(le);
@@ -343,27 +338,20 @@
 
                 case DBG_END_LOCAL: {
                     int reg = readUnsignedLeb128(bs);
-                    LocalEntry prevle;
-                    LocalEntry le;
-
-                    try {
-                        prevle = lastEntryForReg[reg];
-
-                        if (!prevle.isStart) {
-                            throw new RuntimeException("nonsensical "
-                                    + "END_LOCAL on dead register v" + reg);
+                    boolean found = false;
+                    for (int i = locals.size() - 1; i >= 0; i--) {
+                        if (locals.get(i).reg == reg) {
+                            locals.get(i).end = address;
+                            found = true;
+                            break;
                         }
-                        
-                        le = new LocalEntry(address, false, reg,
-                                prevle.nameIndex, prevle.typeIndex,
-                                prevle.signatureIndex);
-                    } catch (NullPointerException ex) {
-                        throw new RuntimeException(
-                                "Encountered END_LOCAL on new v" + reg);
                     }
 
-                    locals.add(le);
-                    lastEntryForReg[reg] = le;
+                    if (!found) {
+                        throw new RuntimeException(
+                                "Encountered LOCAL_END without local start: v"
+                                        + reg);
+                    }
                 }
                 break;
 
@@ -415,48 +403,40 @@
      * throwing an exception if they do not match. Used to validate the
      * encoder.
      *
-     * @param info encoded debug info
-     * @param file non-null; file to refer to during decoding
-     * @param ref non-null; method whose info is being decoded
-     * @param code non-null; original code object that was encoded
-     * @param isStatic whether the method is static
+     * @param linecodes encoded debug info
+     * @param codeSize size of insn block in code units
+     * @param countRegisters size of used register block in register units
+     * @param pl position list to verify against
+     * @param ll locals list to verify against.
      */
-    public static void validateEncode(byte[] info, DexFile file,
-            CstMethodRef ref, DalvCode code, boolean isStatic) {
-        PositionList pl = code.getPositions();
-        LocalList ll = code.getLocals();
-        DalvInsnList insns = code.getInsns();
-        int codeSize = insns.codeSize();
-        int countRegisters = insns.getRegistersSize();
-        
+    public static void validateEncode(byte[] linecodes, int codeSize,
+            int countRegisters, PositionList pl, LocalList ll,
+            boolean isStatic, CstMethodRef ref, DexFile file) {
+
         try {
-            validateEncode0(info, codeSize, countRegisters,
+            validateEncode0(linecodes, codeSize, countRegisters,
                     isStatic, ref, file, pl, ll);
         } catch (RuntimeException ex) {
-            System.err.println("instructions:");
-            insns.debugPrint(System.err, "  ", true);
-            System.err.println("local list:");
-            ll.debugPrint(System.err, "  ");
+//            System.err.println(ex.toString()
+//                    + " while processing " + ref.toHuman());
             throw ExceptionWithContext.withContext(ex,
                     "while processing " + ref.toHuman());
         }
     }
+
     
-    private static void validateEncode0(byte[] info, int codeSize,
+    private static void validateEncode0(byte[] linecodes, int codeSize,
             int countRegisters, boolean isStatic, CstMethodRef ref,
             DexFile file, PositionList pl, LocalList ll) {
         DebugInfoDecoder decoder
-                = new DebugInfoDecoder(info, codeSize, countRegisters,
+                = new DebugInfoDecoder(linecodes, codeSize, countRegisters,
                     isStatic, ref, file);
 
         decoder.decode();
 
-        /*
-         * Go through the decoded position entries, matching up
-         * with original entries.
-         */
+        List<PositionEntry> decodedEntries;
 
-        List<PositionEntry> decodedEntries = decoder.getPositionList();
+        decodedEntries = decoder.getPositionList();
 
         if (decodedEntries.size() != pl.size()) {
             throw new RuntimeException(
@@ -464,7 +444,7 @@
                     + decodedEntries.size() + " expected " + pl.size());
         }
 
-        for (PositionEntry entry : decodedEntries) {
+        for (PositionEntry entry: decodedEntries) {
             boolean found = false;
             for (int i = pl.size() - 1; i >= 0; i--) {
                 PositionList.Entry ple = pl.get(i);
@@ -482,111 +462,41 @@
             }
         }
 
-        /*
-         * Go through the original local list, in order, matching up
-         * with decoded entries.
-         */
+        List<LocalEntry> decodedLocals;
 
-        List<LocalEntry> decodedLocals = decoder.getLocals();
-        int thisStringIdx = decoder.thisStringIdx;
-        int decodedSz = decodedLocals.size();
+        decodedLocals = decoder.getLocals();
+
         int paramBase = decoder.getParamBase();
 
-        /*
-         * Preflight to fill in any parameters that were skipped in
-         * the prologue (including an implied "this") but then
-         * identified by full signature.
-         */
-        for (int i = 0; i < decodedSz; i++) {
-            LocalEntry entry = decodedLocals.get(i);
-            int idx = entry.nameIndex;
+        int matchedLocalsEntries = 0;
 
-            if ((idx < 0) || (idx == thisStringIdx)) {
-                for (int j = i + 1; j < decodedSz; j++) {
-                    LocalEntry e2 = decodedLocals.get(j);
-                    if (e2.address != 0) {
-                        break;
-                    }
-                    if ((entry.reg == e2.reg) && e2.isStart) {
-                        decodedLocals.set(i, e2);
-                        decodedLocals.remove(j);
-                        decodedSz--;
-                        break;
-                    }
-                }
-            }
-        }
-        
-        int origSz = ll.size();
-        int decodeAt = 0;
-        boolean problem = false;
+        for (LocalEntry entry: decodedLocals) {
+            boolean found = false;
+            for (int i = ll.size() - 1; i >= 0; i--) {
+                LocalList.Entry le = ll.get(i);
 
-        for (int i = 0; i < origSz; i++) {
-            LocalList.Entry origEntry = ll.get(i);
-
-            if (origEntry.getDisposition()
-                    == LocalList.Disposition.END_REPLACED) {
                 /*
-                 * The encoded list doesn't represent replacements, so
-                 * ignore them for the sake of comparison.
+                 * If an entry is a method parameter, then the original
+                 * entry may not be marked as starting at 0. However, the
+                 * end address should still match.
                  */
-                continue;
-            }
-
-            LocalEntry decodedEntry;
-
-            do {
-                decodedEntry = decodedLocals.get(decodeAt);
-                if (decodedEntry.nameIndex >= 0) {
+                if ((entry.start == le.getStart()
+                        || (entry.start == 0 && entry.reg >= paramBase))
+                        && entry.end == le.getEnd()
+                        && entry.reg == le.getRegister()) {
+                    found = true;
+                    matchedLocalsEntries++;
                     break;
                 }
-                /*
-                 * A negative name index means this is an anonymous
-                 * parameter, and we shouldn't expect to see it in the
-                 * original list. So, skip it.
-                 */
-                decodeAt++;
-            } while (decodeAt < decodedSz);
-
-            int decodedAddress = decodedEntry.address;
-
-            if (decodedEntry.reg != origEntry.getRegister()) {
-                System.err.println("local register mismatch at orig " + i +
-                        " / decoded " + decodeAt);
-                problem = true;
-                break;
-            }
-            
-            if (decodedEntry.isStart != origEntry.isStart()) {
-                System.err.println("local start/end mismatch at orig " + i +
-                        " / decoded " + decodeAt);
-                problem = true;
-                break;
             }
 
-            /*
-             * The secondary check here accounts for the fact that a
-             * parameter might not be marked as starting at 0 in the
-             * original list.
-             */
-            if ((decodedAddress != origEntry.getAddress()) 
-                    && !((decodedAddress == 0)
-                            && (decodedEntry.reg >= paramBase))) {
-                System.err.println("local address mismatch at orig " + i +
-                        " / decoded " + decodeAt);
-                problem = true;
-                break;
+            if (!found) {
+                throw new RuntimeException("Could not match local entry");
             }
-
-            decodeAt++;
         }
 
-        if (problem) {
-            System.err.println("decoded locals:");
-            for (LocalEntry e : decodedLocals) {
-                System.err.println("  " + e);
-            }
-            throw new RuntimeException("local table problem");
+        if (matchedLocalsEntries != ll.size()) {
+            throw new RuntimeException("Locals tables did not match");
         }
     }
 
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
index 780e18d..49781bd 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
@@ -56,10 +56,10 @@
     private static final boolean DEBUG = false;
 
     /** null-ok; positions (line numbers) to encode */
-    private final PositionList positions;
+    private final PositionList positionlist;
 
     /** null-ok; local variables to encode */
-    private final LocalList locals;
+    private final LocalList locallist;
 
     private final ByteArrayAnnotatedOutput output;
     private final DexFile file;
@@ -108,8 +108,8 @@
     public DebugInfoEncoder(PositionList pl, LocalList ll,
             DexFile file, int codeSize, int regSize,
             boolean isStatic, CstMethodRef ref) {
-        this.positions = pl;
-        this.locals = ll;
+        this.positionlist = pl;
+        this.locallist = ll;
         this.file = file;
         output = new ByteArrayAnnotatedOutput();
         this.desc = ref.getPrototype();
@@ -193,11 +193,18 @@
     
     private byte[] convert0() throws IOException {
         ArrayList<PositionList.Entry> sortedPositions = buildSortedPositions();
-        ArrayList<LocalList.Entry> methodArgs = extractMethodArguments();
+        ArrayList<LocalList.Entry> sortedLocalsStart = buildLocalsStart();
+
+        // Parameter locals are removed from sortedLocalsStart here.
+        ArrayList<LocalList.Entry> methodArgs
+                = extractMethodArguments(sortedLocalsStart);
+
+        ArrayList<LocalList.Entry> sortedLocalsEnd
+                = buildLocalsEnd(sortedLocalsStart);
 
         emitHeader(sortedPositions, methodArgs);
 
-        // TODO: Make this mark be the actual prologue end.
+        // TODO: Make this mark the actual prologue end.
         output.writeByte(DBG_SET_PROLOGUE_END);
 
         if (annotateTo != null || debugPrint != null) {
@@ -205,37 +212,56 @@
         }
 
         int szp = sortedPositions.size();
-        int szl = locals.size();
+        int szl = sortedLocalsStart.size();
 
         // Current index in sortedPositions
         int curp = 0;
-        // Current index in locals
-        int curl = 0;
+        // Current index in sortedLocalsStart
+        int curls = 0;
+        // Current index in sortedLocalsEnd
+        int curle = 0;
 
         for (;;) {
             /*
              * Emit any information for the current address.
              */
 
-            curl = emitLocalsAtAddress(curl);
+            curle = emitLocalEndsAtAddress(curle, sortedLocalsEnd, curls,
+                    sortedLocalsStart);
+
+            /*
+             * Our locals-sorted-by-range-end has reached the end
+             * of the code block. Ignore everything else.
+             */
+            if (address == codeSize) {
+                curle = szl;
+            }
+
+            curls = emitLocalStartsAtAddress(curls, sortedLocalsStart);
+
             curp = emitPositionsAtAddress(curp, sortedPositions);
 
             /*
              * Figure out what the next important address is.
              */
 
-            int nextAddrL = Integer.MAX_VALUE; // local variable
-            int nextAddrP = Integer.MAX_VALUE; // position (line number)
+            int nextAddrLS = Integer.MAX_VALUE; // local start
+            int nextAddrLE = Integer.MAX_VALUE; // local end
+            int nextAddrP = Integer.MAX_VALUE;  // position (line number)
 
-            if (curl < szl) {
-                nextAddrL = locals.get(curl).getAddress();
+            if (curls < szl) {
+                nextAddrLS = sortedLocalsStart.get(curls).getStart();
+            }
+
+            if (curle < szl) {
+                nextAddrLE = sortedLocalsEnd.get(curle).getEnd();
             }
 
             if (curp < szp) {
                 nextAddrP = sortedPositions.get(curp).getAddress();
             }
 
-            int next = Math.min(nextAddrP, nextAddrL);
+            int next = Math.min(nextAddrP, Math.min(nextAddrLS, nextAddrLE));
 
             // No next important address == done.
             if (next == Integer.MAX_VALUE) {
@@ -247,7 +273,7 @@
              * block, stop here. Those are implied anyway.
              */
             if (next == codeSize
-                    && nextAddrL == Integer.MAX_VALUE
+                    && nextAddrLS == Integer.MAX_VALUE
                     && nextAddrP == Integer.MAX_VALUE) {
                 break;                
             }
@@ -266,24 +292,76 @@
     }
 
     /**
-     * Emits all local variable activity that occurs at the current
-     * {@link #address} starting at the given index into {@code
-     * locals} and including all subsequent activity at the same
-     * address.
+     * Emits all local ends that occur at the current <code>address</code>
      *
-     * @param curl Current index in locals
-     * @return new value for <code>curl</code>
+     * @param curle Current index in sortedLocalsEnd
+     * @param sortedLocalsEnd Locals, sorted by ascending end address
+     * @param curls Current index in sortedLocalsStart
+     * @param sortedLocalsStart Locals, sorted by ascending start address
+     * @return new value for <code>curle</code>
      * @throws IOException
      */
-    private int emitLocalsAtAddress(int curl)
+    private int emitLocalEndsAtAddress(int curle,
+            ArrayList<LocalList.Entry> sortedLocalsEnd, int curls,
+            ArrayList<LocalList.Entry> sortedLocalsStart)
             throws IOException {
-        int sz = locals.size();
 
-        // TODO: Don't emit ends implied by starts.
+        int szl = sortedLocalsEnd.size();
 
-        while ((curl < sz)
-                && (locals.get(curl).getAddress() == address)) {
-            LocalList.Entry lle = locals.get(curl++);
+        // Ignore "local ends" at end of code.
+        while (curle < szl
+                && sortedLocalsEnd.get(curle).getEnd() == address
+                && address != codeSize) {
+
+            boolean skipLocalEnd = false;
+
+            /*
+             * Check to see if there's a range-start that appears at
+             * the same address for the same register. If so, the
+             * end-range is implicit so skip it.
+             */
+            for (int j = curls; j < szl
+                    && sortedLocalsStart.get(j).getStart() == address
+                    ; j++) {
+
+                if (sortedLocalsStart.get(j).getRegister()
+                        == sortedLocalsEnd.get(curle).getRegister()) {
+                    skipLocalEnd = true;
+
+                    if (DEBUG) {
+                        System.err.printf("skip local end v%d\n",
+                                sortedLocalsEnd.get(curle).getRegister());
+                    }
+                    break;
+                }
+            }
+
+            if (!skipLocalEnd) {
+                emitLocalEnd(sortedLocalsEnd.get(curle));
+            }
+
+            curle++;
+        }
+        return curle;
+    }
+
+    /**
+     * Emits all local starts that occur at the current <code>address</code>
+     *
+     * @param curls Current index in sortedLocalsStart
+     * @param sortedLocalsStart Locals, sorted by ascending start address
+     * @return new value for <code>curls</code>
+     * @throws IOException
+     */
+    private int emitLocalStartsAtAddress(int curls,
+            ArrayList<LocalList.Entry> sortedLocalsStart)
+            throws IOException {
+
+        int szl = sortedLocalsStart.size();
+
+        while (curls < szl
+                && sortedLocalsStart.get(curls).getStart() == address) {
+            LocalList.Entry lle = sortedLocalsStart.get(curls++);
             int reg = lle.getRegister();
             LocalList.Entry prevlle = lastEntryForReg[reg];
 
@@ -296,45 +374,26 @@
                 continue;
             } 
 
-            // At this point we have a new entry one way or another.
+            // At this point we have a new live entry one way or another.
             lastEntryForReg[reg] = lle;
 
-            if (lle.isStart()) {
-                if ((prevlle != null) && lle.matches(prevlle)) {
+            if ((prevlle != null) && lle.matches(prevlle)) {
+                if (prevlle.getEnd() == lle.getStart()) {
                     /*
-                     * The previous local in this register has the same
-                     * name and type as the one being introduced now, so
-                     * use the more efficient "restart" form.
+                     * There is nothing more to do in this case: It's
+                     * an adjacent range with the same register. The
+                     * previous emitLocalEndsAtAddress() call skipped
+                     * this local end, so we'll skip this local start
+                     * as well.
                      */
-                    if (prevlle.isStart()) {
-                        /*
-                         * We should never be handed a start when a
-                         * a matching local is already active.
-                         */
-                        throw new RuntimeException("shouldn't happen");
-                    }
-                    emitLocalRestart(lle);
                 } else {
-                    emitLocalStart(lle);
+                    emitLocalRestart(lle);
                 }
             } else {
-                /*
-                 * Only emit a local end if it is *not* due to a direct
-                 * replacement. Direct replacements imply an end of the
-                 * previous local in the same register.
-                 * 
-                 * TODO: Make sure the runtime can deal with implied
-                 * local ends from category-2 interactions, and when so,
-                 * also stop emitting local ends for those cases.
-                 */
-                if (lle.getDisposition()
-                        != LocalList.Disposition.END_REPLACED) {
-                    emitLocalEnd(lle);
-                }
+                emitLocalStart(lle);
             }
         }
-
-        return curl;
+        return curls;
     }
 
     /**
@@ -465,7 +524,7 @@
          * a LOCAL_RESTART_EXTENDED
          */
 
-        for (LocalList.Entry arg : lastEntryForReg) {
+        for (LocalList.Entry arg: lastEntryForReg) {
             if (arg == null) {
                 continue;
             }
@@ -484,11 +543,11 @@
      * @return A sorted positions list
      */
     private ArrayList<PositionList.Entry> buildSortedPositions() {
-        int sz = (positions == null) ? 0 : positions.size();
+        int sz = (positionlist == null) ? 0 : positionlist.size();
         ArrayList<PositionList.Entry> result = new ArrayList(sz);
 
         for (int i = 0; i < sz; i++) {
-            result.add(positions.get(i));
+            result.add(positionlist.get(i));
         }
 
         // Sort ascending by address.
@@ -505,6 +564,58 @@
     }
 
     /**
+     * Builds a list of locals entries sorted by ascending start address.
+     *
+     * @return A sorted locals list list
+     */
+    private ArrayList<LocalList.Entry> buildLocalsStart() {
+        int sz = (locallist == null) ? 0 : locallist.size();
+        ArrayList<LocalList.Entry> result = new ArrayList(sz);
+
+        // Add all the entries
+        for (int i = 0; i < sz; i++) {
+            LocalList.Entry e = locallist.get(i);
+            result.add(locallist.get(i));
+        }
+
+        // Sort ascending by start address.
+        Collections.sort (result, new Comparator<LocalList.Entry>() {
+            public int compare (LocalList.Entry a, LocalList.Entry b) {
+                return a.getStart() - b.getStart();
+            }
+
+            public boolean equals (Object obj) {
+               return obj == this;
+            }
+        });
+        return result;
+    }
+
+    /**
+     * Builds a list of locals entries sorted by ascending end address.
+     * 
+     * @param list locals list in any order
+     * @return a sorted locals list
+     */
+    private ArrayList<LocalList.Entry> buildLocalsEnd(
+            ArrayList<LocalList.Entry> list) {
+
+        ArrayList<LocalList.Entry> sortedLocalsEnd  = new ArrayList(list);
+
+        // Sort ascending by end address.
+        Collections.sort (sortedLocalsEnd, new Comparator<LocalList.Entry>() {
+            public int compare (LocalList.Entry a, LocalList.Entry b) {
+                return a.getEnd() - b.getEnd();
+            }
+
+            public boolean equals (Object obj) {
+               return obj == this;
+            }
+        });
+        return sortedLocalsEnd;
+    }
+
+    /**
      * Gets the register that begins the method's parameter range (including
      * the 'this' parameter for non-static methods). The range continues until
      * <code>regSize</code>
@@ -521,18 +632,24 @@
      * from the input list and sorted by ascending register in the
      * returned list.
      *
+     * @param sortedLocals locals list, sorted by ascending start address,
+     * to process; left unmodified
      * @return list of non-<code>this</code> method argument locals,
      * sorted by ascending register
      */
-    private ArrayList<LocalList.Entry> extractMethodArguments() {
+    private ArrayList<LocalList.Entry> extractMethodArguments (
+            ArrayList<LocalList.Entry> sortedLocals) {
+
         ArrayList<LocalList.Entry> result
                 = new ArrayList(desc.getParameterTypes().size());
-        int argBase = getParamBase();
-        BitSet seen = new BitSet(regSize - argBase);
-        int sz = locals.size();
 
+        int argBase = getParamBase();
+
+        BitSet seen = new BitSet(regSize - argBase);
+
+        int sz = sortedLocals.size();
         for (int i = 0; i < sz; i++) {
-            LocalList.Entry e = locals.get(i);
+            LocalList.Entry e = sortedLocals.get(i);
             int reg = e.getRegister();
 
             if (reg < argBase) {
@@ -549,12 +666,12 @@
         }
 
         // Sort by ascending register.
-        Collections.sort(result, new Comparator<LocalList.Entry>() {
-            public int compare(LocalList.Entry a, LocalList.Entry b) {
+        Collections.sort (result, new Comparator<LocalList.Entry>() {
+            public int compare (LocalList.Entry a, LocalList.Entry b) {
                 return a.getRegister() - b.getRegister();
             }
 
-            public boolean equals(Object obj) {
+            public boolean equals (Object obj) {
                return obj == this;
             }
         });
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoItem.java b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
index 0e4329b..b074593 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoItem.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
@@ -141,37 +141,6 @@
      */
     private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
             AnnotatedOutput out, boolean consume) {
-        byte[] result = encode0(file, prefix, debugPrint, out, consume);
-
-        if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
-            try {
-                DebugInfoDecoder.validateEncode(result, file, ref, code,
-                        isStatic);
-            } catch (RuntimeException ex) {
-                // Reconvert, annotating to System.err.
-                encode0(file, "", new PrintWriter(System.err, true), null,
-                        false);
-                throw ex;
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Helper for {@link #encode} to do most of the work.
-     *
-     * @param file null-ok; file to refer to during encoding
-     * @param prefix null-ok; prefix to attach to each line of output
-     * @param debugPrint null-ok; if specified, an alternate output for
-     * annotations
-     * @param out null-ok; if specified, where annotations should go
-     * @param consume whether to claim to have consumed output for
-     * <code>out</code>
-     * @return non-null; the encoded array
-     */
-    private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint,
-            AnnotatedOutput out, boolean consume) {
         PositionList positions = code.getPositions();
         LocalList locals = code.getLocals();
         DalvInsnList insns = code.getInsns();
@@ -187,8 +156,13 @@
         if ((debugPrint == null) && (out == null)) {
             result = encoder.convert();
         } else {
-            result = encoder.convertAndAnnotate(prefix, debugPrint, out,
-                    consume);
+            result = encoder.convertAndAnnotate(
+                    prefix, debugPrint, out, consume);
+        }
+
+        if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
+            DebugInfoDecoder.validateEncode(encoded, codeSize,
+                    regSize, positions, locals, isStatic, ref, file);
         }
 
         return result;
diff --git a/dx/src/com/android/dx/rop/code/LocalItem.java b/dx/src/com/android/dx/rop/code/LocalItem.java
index bac6ce2..b1e1a4b 100644
--- a/dx/src/com/android/dx/rop/code/LocalItem.java
+++ b/dx/src/com/android/dx/rop/code/LocalItem.java
@@ -22,6 +22,7 @@
  * A local variable item: either a name or a signature or both.
  */
 public class LocalItem implements Comparable<LocalItem> {
+
     /** null-ok; local variable name */
     private final CstUtf8 name;
 
@@ -37,7 +38,7 @@
      * @param signature null-ok; local variable signature
      * @return non-null; appropriate instance.
      */
-    public static LocalItem make(CstUtf8 name, CstUtf8 signature) {
+    public static LocalItem make (CstUtf8 name, CstUtf8 signature) {
         if (name == null && signature == null) {
             return null;
         }
@@ -51,14 +52,14 @@
      * @param name null-ok; local variable name
      * @param signature null-ok; local variable signature
      */
-    private LocalItem(CstUtf8 name, CstUtf8 signature) {
+    private LocalItem (CstUtf8 name, CstUtf8 signature) {
         this.name = name;
         this.signature = signature;
     }
 
     /** {@inheritDoc} */
     @Override
-    public boolean equals(Object other) {
+    public boolean equals (Object other) {
         if (!(other instanceof LocalItem)) {
             return false;
         }
@@ -88,7 +89,7 @@
     }
 
     /** {@inheritDoc} */
-    public int compareTo(LocalItem local) {
+    public int compareTo (LocalItem local) {
         int ret;
 
         ret = compareHandlesNulls(name, local.name);
@@ -105,7 +106,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public int hashCode() {
+    public int hashCode () {
         return (name == null ? 0 : name.hashCode()) * 31
                 + (signature == null ? 0 : signature.hashCode());
     }
@@ -120,7 +121,7 @@
         }
 
         return "[" + (name == null ? "" : name.toQuoted())
-                + "|" + (signature == null ? "" : signature.toQuoted());
+                + "|" + (signature == null ? "" : signature.toQuoted());        
     }
 
     /**
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpec.java b/dx/src/com/android/dx/rop/code/RegisterSpec.java
index 73af91f..09f7f18 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpec.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpec.java
@@ -29,7 +29,7 @@
  * destinations of register-based operations.
  */
 public final class RegisterSpec
-        implements TypeBearer, ToHuman, Comparable<RegisterSpec> {
+        implements TypeBearer, ToHuman {
     /** non-null; string to prefix register numbers with */
     public static final String PREFIX = "v";
 
@@ -97,8 +97,7 @@
      * @param local non-null; the associated local variable
      * @return non-null; an appropriately-constructed instance
      */
-    public static RegisterSpec make(int reg, TypeBearer type,
-            LocalItem local) {
+    public static RegisterSpec make(int reg, TypeBearer type, LocalItem local) {
         if (local == null) {
             throw new NullPointerException("local  == null");
         }
@@ -173,43 +172,6 @@
     }
 
     /**
-     * Like {@code equals}, but only consider the simple types of the
-     * registers. That is, this compares {@code getType()} on the types
-     * to ignore whatever arbitrary extra stuff might be carried around
-     * by an outer {@link TypeBearer}.
-     * 
-     * @param other null-ok; spec to compare to
-     * @return {@code true} iff {@code this} and {@code other} are equal
-     * in the stated way
-     */
-    public boolean equalsUsingSimpleType(RegisterSpec other) {
-        if (!matchesVariable(other)) {
-            return false;
-        }
-
-        return (reg == other.reg);
-    }
-
-    /**
-     * Like {@link #equalsUsingSimpleType} but ignoring the register number.
-     * This is useful to determine if two instances refer to the "same"
-     * local variable.
-     * 
-     * @param other null-ok; spec to compare to
-     * @return {@code true} iff {@code this} and {@code other} are equal
-     * in the stated way
-     */
-    public boolean matchesVariable(RegisterSpec other) {
-        if (other == null) {
-            return false;
-        }
-
-        return type.getType().equals(other.type.getType())
-            && ((local == other.local)
-                    || ((local != null) && local.equals(other.local)));
-    }
-
-    /**
      * Helper for {@link #equals} and {@link #ForComparison.equals},
      * which actually does the test.
      * 
@@ -226,35 +188,6 @@
                     || ((this.local != null) && this.local.equals(local)));
     }
 
-    /**
-     * Compares by (in priority order) register number, unwrapped type
-     * (that is types not {@link TypeBearer}s, and local info.
-     * 
-     * @param other non-null; spec to compare to
-     * @return {@code -1..1}; standard result of comparison
-     */
-    public int compareTo(RegisterSpec other) {
-        if (this.reg < other.reg) {
-            return -1;
-        } else if (this.reg > other.reg) {
-            return 1;
-        }
-
-        int compare = type.getType().compareTo(other.type.getType());
-
-        if (compare != 0) {
-            return compare;
-        }
-
-        if (this.local == null) {
-            return (other.local == null) ? 0 : -1;
-        } else if (other.local == null) {
-            return 1;
-        }
-
-        return this.local.compareTo(other.local);
-    }    
-
     /** {@inheritDoc} */
     @Override
     public int hashCode() {
@@ -359,8 +292,6 @@
      * Gets the category of this instance's type. This is just a convenient
      * shorthand for <code>getType().getCategory()</code>.
      * 
-     * @see #isCategory1
-     * @see #isCategory2
      * @return 1..2; the category of this instance's type
      */
     public int getCategory() {
@@ -368,30 +299,6 @@
     }
 
     /**
-     * Gets whether this instance's type is category 1. This is just a
-     * convenient shorthand for <code>getType().isCategory1()</code>.
-     * 
-     * @see #getCategory
-     * @see #isCategory2
-     * @return whether or not this instance's type is of category 1
-     */
-    public boolean isCategory1() {
-        return type.getType().isCategory1();
-    }
-
-    /**
-     * Gets whether this instance's type is category 2. This is just a
-     * convenient shorthand for <code>getType().isCategory2()</code>.
-     * 
-     * @see #getCategory
-     * @see #isCategory1
-     * @return whether or not this instance's type is of category 2
-     */
-    public boolean isCategory2() {
-        return type.getType().isCategory2();
-    }
-
-    /**
      * Gets the string form for just the register number of this instance.
      * 
      * @return non-null; the register string form
@@ -416,16 +323,16 @@
      *     are <code>equals()</code>, then the intersection's type bearer
      *     is the one from this instance. Otherwise, the intersection's
      *     type bearer is the <code>getType()</code> of this instance.</li>
-     *   <li>If the locals are <code>equals()</code>, then the local info
-     *     of the intersection is the local info of this instance. Otherwise,
-     *     the local info of the intersection is <code>null</code>.</li>
+     *   <li>If the locals are <code>equals()</code>, then the local info of the
+     *     intersection is the local info of this instance. Otherwise, the local info
+     *     of the intersection is <code>null</code>.</li>
      * </ul>
      * 
      * @param other null-ok; instance to intersect with (or <code>null</code>)
-     * @param localPrimary whether local variables are primary to the
-     * intersection; if <code>true</code>, then the only non-null
-     * results occur when registers being intersected have equal local
-     * infos (or both have <code>null</code> local infos)
+     * @param localPrimary whether local variables are primary to
+     * the intersection; if <code>true</code>, then the only non-null
+     * results occur when registers being intersected have equal local infos (or
+     * both have <code>null</code> local infos)
      * @return null-ok; the intersection
      */
     public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) {
@@ -439,8 +346,7 @@
         }
 
         LocalItem resultLocal =
-            ((local == null) || !local.equals(other.getLocalItem()))
-            ? null : local;
+            ((local == null) || !local.equals(other.getLocalItem())) ? null : local;
         boolean sameName = (resultLocal == local);
 
         if (localPrimary && !sameName) {
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
index adc77c3..4eb2f65 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
@@ -187,47 +187,16 @@
     }
 
     /**
-     * Returns the spec in this set that's currently associated with a
-     * given local (type, name, and signature), or {@code null} if there is
-     * none. This ignores the register number of the given spec but
-     * matches on everything else.
-     * 
-     * @param spec non-null; local to look for
-     * @return null-ok; first register found that matches, if any
-     */
-    public RegisterSpec findMatchingLocal(RegisterSpec spec) {
-        int length = specs.length;
-        
-        for (int reg = 0; reg < length; reg++) {
-            RegisterSpec s = specs[reg];
-
-            if (s == null) {
-                continue;
-            }
-
-            if (spec.matchesVariable(s)) {
-                return s;
-            }
-        }
-
-        return null;
-    }
-
-    /**
      * Returns the spec in this set that's currently associated with a given
-     * local (name and signature), or {@code null} if there is none.
+     * name, or null if there is none.
      *
      * @param local non-null; local item to search for
-     * @return null-ok; first register found with matching name and signature
+     * @return null-ok; first register found with name.
      */
     public RegisterSpec localItemToSpec(LocalItem local) {
-        int length = specs.length;
-        
-        for (int reg = 0; reg < length; reg++) {
-            RegisterSpec spec = specs[reg];
-            
-            if ((spec != null) && local.equals(spec.getLocalItem())) {
-                return spec;
+        for (int reg = 0; reg < specs.length; reg++) {
+            if (specs[reg] != null && local.equals(specs[reg].getLocalItem())) {
+                return specs[reg];
             }
         }
 
@@ -291,22 +260,6 @@
     }
 
     /**
-     * Put the entire contents of the given set into this one.
-     * 
-     * @param set non-null; the set to put into this instance
-     */
-    public void putAll(RegisterSpecSet set) {
-        int max = set.getMaxSize();
-
-        for (int i = 0; i < max; i++) {
-            RegisterSpec spec = set.get(i);
-            if (spec != null) {
-                put(spec);
-            }
-        }
-    }
-
-    /**
      * Intersects this instance with the given one, modifying this
      * instance. The intersection consists of the pairwise
      * {@link RegisterSpec#intersect} of corresponding elements from
diff --git a/libcore/icu/src/main/native/DecimalFormatInterface.cpp b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
index 6221826..fb5cf9f 100644
--- a/libcore/icu/src/main/native/DecimalFormatInterface.cpp
+++ b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
@@ -50,13 +50,13 @@
             default :
                 exception = env->FindClass("java/lang/RuntimeException");
         }
-
+        
         return (env->ThrowNew(exception, emsg) != 0);
     }
     return 0;
 }
 
-static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale,
+static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale, 
         jstring pattern) {
 
     // the errorcode returned by unum_open
@@ -70,9 +70,9 @@
     const char *localeChars = env->GetStringUTFChars(locale, NULL);
 
     // open a default type number format
-    UNumberFormat *fmt = unum_open(UNUM_PATTERN_DECIMAL, pattChars, pattLen,
+    UNumberFormat *fmt = unum_open(UNUM_PATTERN_DECIMAL, pattChars, pattLen, 
             localeChars, NULL, &status);
-
+    
     // release the allocated strings
     env->ReleaseStringChars(pattern, pattChars);
     env->ReleaseStringUTFChars(locale, localeChars);
@@ -88,20 +88,20 @@
 
 static void closeDecimalFormatImpl(JNIEnv *env, jclass clazz, jint addr) {
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     // close this number format
     unum_close(fmt);
 }
 
-static void setSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol,
+static void setSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol, 
         jstring text) {
-
+    
     // the errorcode returned by unum_setSymbol
     UErrorCode status = U_ZERO_ERROR;
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     // prepare the symbol string for the call to unum_setSymbol
@@ -109,9 +109,9 @@
     int textLen = env->GetStringLength(text);
 
     // set the symbol
-    unum_setSymbol(fmt, (UNumberFormatSymbol) symbol, textChars, textLen,
+    unum_setSymbol(fmt, (UNumberFormatSymbol) symbol, textChars, textLen, 
             &status);
-
+    
     // release previously allocated space
     env->ReleaseStringChars(text, textChars);
 
@@ -126,14 +126,14 @@
     // the errorcode returned by unum_getSymbol
     UErrorCode status = U_ZERO_ERROR;
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     UChar* result = NULL;
     resultlength=0;
 
     // find out how long the result will be
-    reslenneeded=unum_getSymbol(fmt, (UNumberFormatSymbol) symbol, result,
+    reslenneeded=unum_getSymbol(fmt, (UNumberFormatSymbol) symbol, result, 
             resultlength, &status);
 
     result = NULL;
@@ -141,7 +141,7 @@
         status=U_ZERO_ERROR;
         resultlength=reslenneeded+1;
         result=(UChar*)malloc(sizeof(UChar) * resultlength);
-        reslenneeded=unum_getSymbol(fmt, (UNumberFormatSymbol) symbol, result,
+        reslenneeded=unum_getSymbol(fmt, (UNumberFormatSymbol) symbol, result, 
                 resultlength, &status);
     }
     if (icuError(env, status) != FALSE) {
@@ -154,17 +154,17 @@
 
     return res;
 }
-
-static void setAttribute(JNIEnv *env, jclass clazz, jint addr, jint symbol,
+    
+static void setAttribute(JNIEnv *env, jclass clazz, jint addr, jint symbol, 
         jint value) {
-
+    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     unum_setAttribute(fmt, (UNumberFormatAttribute) symbol, value);
 }
-
+    
 static jint getAttribute(JNIEnv *env, jclass clazz, jint addr, jint symbol) {
-
+    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     int res = unum_getAttribute(fmt, (UNumberFormatAttribute) symbol);
@@ -172,27 +172,27 @@
     return res;
 }
 
-static void setTextAttribute(JNIEnv *env, jclass clazz, jint addr, jint symbol,
+static void setTextAttribute(JNIEnv *env, jclass clazz, jint addr, jint symbol, 
         jstring text) {
 
     // the errorcode returned by unum_setTextAttribute
     UErrorCode status = U_ZERO_ERROR;
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     const UChar *textChars = env->GetStringChars(text, NULL);
     int textLen = env->GetStringLength(text);
 
-    unum_setTextAttribute(fmt, (UNumberFormatTextAttribute) symbol, textChars,
+    unum_setTextAttribute(fmt, (UNumberFormatTextAttribute) symbol, textChars, 
             textLen, &status);
-
+    
     env->ReleaseStringChars(text, textChars);
 
     icuError(env, status);
 }
 
-static jstring getTextAttribute(JNIEnv *env, jclass clazz, jint addr,
+static jstring getTextAttribute(JNIEnv *env, jclass clazz, jint addr, 
         jint symbol) {
 
     uint32_t resultlength, reslenneeded;
@@ -200,14 +200,14 @@
     // the errorcode returned by unum_getTextAttribute
     UErrorCode status = U_ZERO_ERROR;
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     UChar* result = NULL;
     resultlength=0;
 
     // find out how long the result will be
-    reslenneeded=unum_getTextAttribute(fmt, (UNumberFormatTextAttribute) symbol,
+    reslenneeded=unum_getTextAttribute(fmt, (UNumberFormatTextAttribute) symbol, 
             result, resultlength, &status);
 
     result = NULL;
@@ -215,8 +215,8 @@
         status=U_ZERO_ERROR;
         resultlength=reslenneeded+1;
         result=(UChar*)malloc(sizeof(UChar) * resultlength);
-        reslenneeded=unum_getTextAttribute(fmt,
-                (UNumberFormatTextAttribute) symbol, result, resultlength,
+        reslenneeded=unum_getTextAttribute(fmt, 
+                (UNumberFormatTextAttribute) symbol, result, resultlength, 
                 &status);
     }
     if (icuError(env, status) != FALSE) {
@@ -230,13 +230,13 @@
     return res;
 }
 
-static void applyPatternImpl(JNIEnv *env, jclass clazz, jint addr,
+static void applyPatternImpl(JNIEnv *env, jclass clazz, jint addr, 
         jboolean localized, jstring pattern) {
 
     // the errorcode returned by unum_applyPattern
     UErrorCode status = U_ZERO_ERROR;
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     const UChar *pattChars = env->GetStringChars(pattern, NULL);
@@ -249,7 +249,7 @@
     icuError(env, status);
 }
 
-static jstring toPatternImpl(JNIEnv *env, jclass clazz, jint addr,
+static jstring toPatternImpl(JNIEnv *env, jclass clazz, jint addr, 
         jboolean localized) {
 
     uint32_t resultlength, reslenneeded;
@@ -257,7 +257,7 @@
     // the errorcode returned by unum_toPattern
     UErrorCode status = U_ZERO_ERROR;
 
-    // get the pointer to the number format
+    // get the pointer to the number format    
     UNumberFormat *fmt = (UNumberFormat *)(int)addr;
 
     UChar* result = NULL;
@@ -271,7 +271,7 @@
         status=U_ZERO_ERROR;
         resultlength=reslenneeded+1;
         result=(UChar*)malloc(sizeof(UChar) * resultlength);
-        reslenneeded=unum_toPattern(fmt, localized, result, resultlength,
+        reslenneeded=unum_toPattern(fmt, localized, result, resultlength, 
                 &status);
     }
     if (icuError(env, status) != FALSE) {
@@ -284,19 +284,19 @@
 
     return res;
 }
-
-static jstring formatLong(JNIEnv *env, jclass clazz, jint addr, jlong value,
+    
+static jstring formatLong(JNIEnv *env, jclass clazz, jint addr, jlong value, 
         jobject field, jstring fieldType, jobject attributes) {
 
     const char * fieldPositionClassName = "java/text/FieldPosition";
     const char * stringBufferClassName = "java/lang/StringBuffer";
     jclass fieldPositionClass = env->FindClass(fieldPositionClassName);
     jclass stringBufferClass = env->FindClass(stringBufferClassName);
-    jmethodID setBeginIndexMethodID = env->GetMethodID(fieldPositionClass,
+    jmethodID setBeginIndexMethodID = env->GetMethodID(fieldPositionClass, 
             "setBeginIndex", "(I)V");
-    jmethodID setEndIndexMethodID = env->GetMethodID(fieldPositionClass,
+    jmethodID setEndIndexMethodID = env->GetMethodID(fieldPositionClass, 
             "setEndIndex", "(I)V");
-    jmethodID appendMethodID = env->GetMethodID(stringBufferClass,
+    jmethodID appendMethodID = env->GetMethodID(stringBufferClass, 
             "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
 
     const char * fieldName = NULL;
@@ -331,7 +331,7 @@
     if(status==U_BUFFER_OVERFLOW_ERROR) {
         status=U_ZERO_ERROR;
 
-        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));
+        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));    
 
         res->extract(result, reslenneeded + 1, status);
     }
@@ -393,18 +393,18 @@
     return resulting;
 }
 
-static jstring formatDouble(JNIEnv *env, jclass clazz, jint addr, jdouble value,
+static jstring formatDouble(JNIEnv *env, jclass clazz, jint addr, jdouble value, 
         jobject field, jstring fieldType, jobject attributes) {
 
     const char * fieldPositionClassName = "java/text/FieldPosition";
     const char * stringBufferClassName = "java/lang/StringBuffer";
     jclass fieldPositionClass = env->FindClass(fieldPositionClassName);
     jclass stringBufferClass = env->FindClass(stringBufferClassName);
-    jmethodID setBeginIndexMethodID = env->GetMethodID(fieldPositionClass,
+    jmethodID setBeginIndexMethodID = env->GetMethodID(fieldPositionClass, 
             "setBeginIndex", "(I)V");
-    jmethodID setEndIndexMethodID = env->GetMethodID(fieldPositionClass,
+    jmethodID setEndIndexMethodID = env->GetMethodID(fieldPositionClass, 
             "setEndIndex", "(I)V");
-    jmethodID appendMethodID = env->GetMethodID(stringBufferClass,
+    jmethodID appendMethodID = env->GetMethodID(stringBufferClass, 
             "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
 
     const char * fieldName = NULL;
@@ -439,7 +439,7 @@
     if(status==U_BUFFER_OVERFLOW_ERROR) {
         status=U_ZERO_ERROR;
 
-        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));
+        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));    
 
         res->extract(result, reslenneeded + 1, status);
 
@@ -502,7 +502,7 @@
     return resulting;
 }
 
-static jstring formatDigitList(JNIEnv *env, jclass clazz, jint addr, jstring value,
+static jstring formatDigitList(JNIEnv *env, jclass clazz, jint addr, jstring value, 
         jobject field, jstring fieldType, jobject attributes, jint scale) {
 
     // const char * valueUTF = env->GetStringUTFChars(value, NULL);
@@ -521,36 +521,21 @@
 
     uint32_t reslenneeded;
 
+    bool isInteger = (scale == 0);
+
     // prepare digit list
 
-    const char *valueChars = env->GetStringUTFChars(value, NULL);
+    const char *digits = env->GetStringUTFChars(value, NULL);
 
-    bool isInteger = (scale == 0);
-    bool isPositive = (*valueChars != '-');
-
-    // skip the '-' if the number is negative
-    const char *digits = (isPositive ? valueChars : valueChars + 1);
-    int length = strlen(digits);
-
-    // The length of our digit list buffer must be the actual string length + 3,
-    // because ICU will append some additional characters at the head and at the
-    // tail of the string, in order to keep strtod() happy:
-    //
-    // - The sign "+" or "-" is appended at the head
-    // - The exponent "e" and the "\0" terminator is appended at the tail
-    //
-    // In retrospect, the changes to ICU's DigitList that were necessary for
-    // big numbers look a bit hacky. It would make sense to rework all this
-    // once ICU 4.x has been integrated into Android. Ideally, big number
-    // support would make it into ICU itself, so we don't need our private
-    // fix anymore.
-    DigitList digitList(length + 3);
-    digitList.fCount = length;
+    // length must be string lengt + 2 because there's an additional
+    // character in front of the string ("+" or "-") and a \0 at the end
+    DigitList digitList(strlen(digits) + 2);
+    digitList.fCount = strlen(digits);
     strcpy(digitList.fDigits, digits);
-    env->ReleaseStringUTFChars(value, valueChars);
+    env->ReleaseStringUTFChars(value, digits);
 
     digitList.fDecimalAt = digitList.fCount - scale;
-    digitList.fIsPositive = isPositive;
+    digitList.fIsPositive = (*digits != '-');
     digitList.fRoundingMode = DecimalFormat::kRoundHalfUp;
 
     UChar *result = NULL;
@@ -563,9 +548,10 @@
     UErrorCode status = U_ZERO_ERROR;
 
     DecimalFormat::AttributeBuffer *attrBuffer = NULL;
-    attrBuffer = (DecimalFormat::AttributeBuffer *) calloc(sizeof(DecimalFormat::AttributeBuffer), 1);
+    attrBuffer = (DecimalFormat::AttributeBuffer *) malloc(sizeof(DecimalFormat::AttributeBuffer));
     attrBuffer->bufferSize = 128;
-    attrBuffer->buffer = (char *) calloc(129 * sizeof(char), 1);
+    attrBuffer->buffer = (char *) malloc(129 * sizeof(char));
+    attrBuffer->buffer[0] = '\0';
 
     DecimalFormat *fmt = (DecimalFormat *)(int)addr;
 
@@ -578,7 +564,7 @@
     if(status==U_BUFFER_OVERFLOW_ERROR) {
         status=U_ZERO_ERROR;
 
-        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));
+        result = (UChar*)malloc(sizeof(UChar) * (reslenneeded + 1));    
 
         res.extract(result, reslenneeded + 1, status);
 
@@ -598,7 +584,7 @@
         }
         free(attrBuffer->buffer);
         free(attrBuffer);
-        return NULL;
+        return NULL;        
     }
 
     int attrLength = (strlen(attrBuffer->buffer) + 1 );
@@ -610,7 +596,7 @@
             // prepare the classes and method ids
             const char * stringBufferClassName = "java/lang/StringBuffer";
             jclass stringBufferClass = env->FindClass(stringBufferClassName);
-            jmethodID appendMethodID = env->GetMethodID(stringBufferClass,
+            jmethodID appendMethodID = env->GetMethodID(stringBufferClass, 
                     "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
 
             jstring attrString = env->NewStringUTF(attrBuffer->buffer + 1);  // cut off the leading ';'
@@ -669,7 +655,7 @@
     return resulting;
 }
 
-static jobject parse(JNIEnv *env, jclass clazz, jint addr, jstring text,
+static jobject parse(JNIEnv *env, jclass clazz, jint addr, jstring text, 
         jobject position) {
 
     const char * textUTF = env->GetStringUTFChars(text, NULL);
@@ -694,11 +680,11 @@
     jclass bigDecimalClass = env->FindClass(bigDecimalClassName);
     jclass bigIntegerClass = env->FindClass(bigIntegerClassName);
 
-    jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass,
+    jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass, 
             "getIndex", "()I");
-    jmethodID setIndexMethodID = env->GetMethodID(parsePositionClass,
+    jmethodID setIndexMethodID = env->GetMethodID(parsePositionClass, 
             "setIndex", "(I)V");
-    jmethodID setErrorIndexMethodID = env->GetMethodID(parsePositionClass,
+    jmethodID setErrorIndexMethodID = env->GetMethodID(parsePositionClass, 
             "setErrorIndex", "(I)V");
 
     jmethodID longInitMethodID = env->GetMethodID(longClass, "<init>", "(J)V");
@@ -710,8 +696,8 @@
     bool resultAssigned;
     int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
 
-    // make sure the ParsePosition is valid. Actually icu4c would parse a number
-    // correctly even if the parsePosition is set to -1, but since the RI fails
+    // make sure the ParsePosition is valid. Actually icu4c would parse a number 
+    // correctly even if the parsePosition is set to -1, but since the RI fails 
     // for that case we have to fail too
     if(parsePos < 0 || parsePos > strlength) {
         return NULL;
@@ -721,9 +707,9 @@
 
     const UnicodeString src((UChar*)str, strlength, strlength);
     ParsePosition pp;
-
+    
     pp.setIndex(parsePos);
-
+    
     DigitList digits;
 
     ((const DecimalFormat*)fmt)->parse(src, resultAssigned, res, pp, FALSE, digits);
@@ -733,8 +719,8 @@
     if(pp.getErrorIndex() == -1) {
         parsePos = pp.getIndex();
     } else {
-        env->CallVoidMethod(position, setErrorIndexMethodID,
-                (jint) pp.getErrorIndex());
+        env->CallVoidMethod(position, setErrorIndexMethodID, 
+                (jint) pp.getErrorIndex());        
         return NULL;
     }
 
@@ -759,17 +745,17 @@
         case Formattable::kDouble:
             resultDouble = res.getDouble();
             env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
-            return env->NewObject(doubleClass, dblInitMethodID,
+            return env->NewObject(doubleClass, dblInitMethodID, 
                     (jdouble) resultDouble);
         case Formattable::kLong:
             resultLong = res.getLong();
             env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
-            return env->NewObject(longClass, longInitMethodID,
+            return env->NewObject(longClass, longInitMethodID, 
                     (jlong) resultLong);
         case Formattable::kInt64:
             resultInt64 = res.getInt64();
             env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
-            return env->NewObject(longClass, longInitMethodID,
+            return env->NewObject(longClass, longInitMethodID, 
                     (jlong) resultInt64);
         default:
             return NULL;
@@ -819,7 +805,7 @@
 
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    {"openDecimalFormatImpl", "(Ljava/lang/String;Ljava/lang/String;)I",
+    {"openDecimalFormatImpl", "(Ljava/lang/String;Ljava/lang/String;)I", 
             (void*) openDecimalFormatImpl},
     {"closeDecimalFormatImpl", "(I)V", (void*) closeDecimalFormatImpl},
     {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol},
@@ -830,22 +816,22 @@
     {"getTextAttribute", "(II)Ljava/lang/String;", (void*) getTextAttribute},
     {"applyPatternImpl", "(IZLjava/lang/String;)V", (void*) applyPatternImpl},
     {"toPatternImpl", "(IZ)Ljava/lang/String;", (void*) toPatternImpl},
-    {"format",
-            "(IJLjava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;)Ljava/lang/String;",
+    {"format", 
+            "(IJLjava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;)Ljava/lang/String;", 
             (void*) formatLong},
-    {"format",
-            "(IDLjava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;)Ljava/lang/String;",
+    {"format", 
+            "(IDLjava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;)Ljava/lang/String;", 
             (void*) formatDouble},
-    {"format",
-            "(ILjava/lang/String;Ljava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;I)Ljava/lang/String;",
+    {"format", 
+            "(ILjava/lang/String;Ljava/text/FieldPosition;Ljava/lang/String;Ljava/lang/StringBuffer;I)Ljava/lang/String;", 
             (void*) formatDigitList},
-    {"parse",
-            "(ILjava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Number;",
+    {"parse", 
+            "(ILjava/lang/String;Ljava/text/ParsePosition;)Ljava/lang/Number;", 
             (void*) parse},
     {"cloneImpl", "(I)I", (void*) cloneImpl}
 };
 int register_com_ibm_icu4jni_text_NativeDecimalFormat(JNIEnv* env) {
-    return jniRegisterNativeMethods(env,
-            "com/ibm/icu4jni/text/NativeDecimalFormat", gMethods,
+    return jniRegisterNativeMethods(env, 
+            "com/ibm/icu4jni/text/NativeDecimalFormat", gMethods, 
             NELEM(gMethods));
 }
diff --git a/libcore/luni/src/main/java/java/io/BufferedInputStream.java b/libcore/luni/src/main/java/java/io/BufferedInputStream.java
index 0b9afc3..1720366 100644
--- a/libcore/luni/src/main/java/java/io/BufferedInputStream.java
+++ b/libcore/luni/src/main/java/java/io/BufferedInputStream.java
@@ -108,7 +108,7 @@
         Logger.global.info(
                 "Default buffer size used in BufferedInputStream " +
                 "constructor. It would be " +
-                "better to be explicit if an 8k buffer is required.");
+                "better to be explicit if a 8k buffer is required.");
         // END android-added
     }
 
diff --git a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
index 835d13f..55419d1 100644
--- a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
@@ -80,7 +80,7 @@
         Logger.global.info(
                 "Default buffer size used in BufferedOutputStream " +
                 "constructor. It would be " +
-                "better to be explicit if an 8k buffer is required.");
+                "better to be explicit if a 8k buffer is required.");
         // END android-added
     }
 
diff --git a/libcore/luni/src/main/java/java/io/BufferedReader.java b/libcore/luni/src/main/java/java/io/BufferedReader.java
index e82e538..c490b89 100644
--- a/libcore/luni/src/main/java/java/io/BufferedReader.java
+++ b/libcore/luni/src/main/java/java/io/BufferedReader.java
@@ -80,7 +80,7 @@
         Logger.global.info(
                 "Default buffer size used in BufferedReader " +
                 "constructor. It would be " +
-                "better to be explicit if an 8k-char buffer is required.");
+                "better to be explicit if a 8k-char buffer is required.");
         // END android-added
     }
 
diff --git a/libcore/luni/src/main/java/java/io/BufferedWriter.java b/libcore/luni/src/main/java/java/io/BufferedWriter.java
index 761b9c5..66bfcc9 100644
--- a/libcore/luni/src/main/java/java/io/BufferedWriter.java
+++ b/libcore/luni/src/main/java/java/io/BufferedWriter.java
@@ -80,7 +80,7 @@
         Logger.global.info(
                 "Default buffer size used in BufferedWriter " +
                 "constructor. It would be " +
-                "better to be explicit if an 8k-char buffer is required.");
+                "better to be explicit if a 8k-char buffer is required.");
         // END android-added
     }
 
diff --git a/libcore/luni/src/main/java/java/util/ArrayList.java b/libcore/luni/src/main/java/java/util/ArrayList.java
index 3bae372..5ea316a 100644
--- a/libcore/luni/src/main/java/java/util/ArrayList.java
+++ b/libcore/luni/src/main/java/java/util/ArrayList.java
@@ -112,7 +112,7 @@
      * @param object
      *            the object to add.
      * @throws IndexOutOfBoundsException
-     *             when {@code location < 0 || > size()}
+     *             when {@code location < 0 || >= size()}
      * @since Android 1.0
      */
     @Override
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java
index 30510c2..6c995bb 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringTest.java
@@ -17,14 +17,15 @@
 
 package org.apache.harmony.luni.tests.java.lang;
 
+import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
 
 import junit.framework.TestCase;
 
 import java.io.UnsupportedEncodingException;
-import java.math.BigDecimal;
+import java.lang.reflect.Constructor;
 
 @TestTargetClass(String.class) 
 public class StringTest extends TestCase {
@@ -700,40 +701,4 @@
         } catch (IndexOutOfBoundsException e) {
         }
     }
-
-    @TestTargetNew(
-        level = TestLevel.ADDITIONAL,
-        notes = "Regression test for some existing bugs and crashes",
-        method = "format",
-        args = { String.class, Object.class }
-    )
-    public void testProblemCases() {
-        BigDecimal[] input = new BigDecimal[] {
-            new BigDecimal("20.00000"),
-            new BigDecimal("20.000000"),
-            new BigDecimal(".2"),
-            new BigDecimal("2"),
-            new BigDecimal("-2"),
-            new BigDecimal("200000000000000000000000"),
-            new BigDecimal("20000000000000000000000000000000000000000000000000")
-        };
-
-        String[] output = new String[] {
-                "20.00",
-                "20.00",
-                "0.20",
-                "2.00",
-                "-2.00",
-                "200000000000000000000000.00",
-                "20000000000000000000000000000000000000000000000000.00"
-        };
-        
-        for (int i = 0; i < input.length; i++) {
-            String result = String.format("%.2f", input[i]);
-            assertEquals("Format test for \"" + input[i] + "\" failed, " +
-                    "expected=" + output[i] + ", " +
-                    "actual=" + result, output[i], result);
-        }
-    }
-    
 }
diff --git a/libcore/run-core-tests b/libcore/run-core-tests
index 25e53ee..3656e2d 100755
--- a/libcore/run-core-tests
+++ b/libcore/run-core-tests
@@ -26,5 +26,6 @@
 chmod 777 $tmp
   
 exec dalvikvm -Duser.language=en -Duser.region=US -Djava.io.tmpdir=$tmp \
-     -Xbootclasspath:$BOOTCLASSPATH:/system/framework/core-tests.jar \
+     -Xbootclasspath:$BOOTCLASSPATH \
+     -classpath /system/framework/core-tests.jar \
      com.google.coretests.Main "$@"
diff --git a/libcore/security/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java b/libcore/security/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java
index 8f0d08b..035e924 100644
--- a/libcore/security/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java
+++ b/libcore/security/src/main/java/org/bouncycastle/asn1/x509/X509NameTokenizer.java
@@ -66,17 +66,6 @@
             {
                 if (escaped || quoted)
                 {
-                    // BEGIN android-added
-                    // copied from a newer version of BouncyCastle
-                    if (c == '#' && buf.charAt(buf.length() - 1) == '=')
-                    {
-                        buf.append('\\');
-                    }
-                    else if (c == '+' && seperator != '+')
-                    {
-                        buf.append('\\');
-                    }
-                    // END android-added
                     buf.append(c);
                     escaped = false;
                 }
@@ -99,4 +88,4 @@
         index = end;
         return buf.toString().trim();
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java
index 2b7c03e..cb821c2 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java
@@ -24,7 +24,6 @@
 // BEGIN android-added
 import java.lang.reflect.Method;
 import java.net.UnknownHostException;
-import java.util.logging.Logger;
 // END android-added
 
 import javax.net.SocketFactory;
@@ -58,56 +57,60 @@
      * @since Android 1.0
      */
     public static SocketFactory getDefault() {
-        synchronized (SSLSocketFactory.class) {
-            if (defaultSocketFactory != null) {
-                // BEGIN android-added
-                log("SSLSocketFactory", "Using factory " + defaultSocketFactory);
-                // END android-added
-                return defaultSocketFactory;
-            }
-            if (defaultName == null) {
-                AccessController.doPrivileged(new java.security.PrivilegedAction(){
-                    public Object run() {
-                        defaultName = Security.getProperty("ssl.SocketFactory.provider");
-                        if (defaultName != null) {
-                            ClassLoader cl = Thread.currentThread().getContextClassLoader();
-                            if (cl == null) {
-                                cl = ClassLoader.getSystemClassLoader();
-                            }
-                            try {
-                                defaultSocketFactory = (SocketFactory) Class.forName(
-                                        defaultName, true, cl).newInstance();
-                             } catch (Exception e) {
-                                return e;
-                            }
-                        }
-                        return null;
-                    }
-                });
-            }
-
-            if (defaultSocketFactory == null) {
-                // Try to find in providers
-                SSLContext context = DefaultSSLContext.getContext();
-                if (context != null) {
-                    defaultSocketFactory = context.getSocketFactory();
-                }
-            }
-            if (defaultSocketFactory == null) {
-                // Use internal implementation
-                defaultSocketFactory = new DefaultSSLSocketFactory("No SSLSocketFactory installed");
-            }
+        if (defaultSocketFactory != null) {
             // BEGIN android-added
             log("SSLSocketFactory", "Using factory " + defaultSocketFactory);
             // END android-added
             return defaultSocketFactory;
         }
+        if (defaultName == null) {
+            AccessController.doPrivileged(new java.security.PrivilegedAction(){
+                public Object run() {
+                    defaultName = Security.getProperty("ssl.SocketFactory.provider");
+                    if (defaultName != null) {    
+                        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+                        if (cl == null) {
+                            cl = ClassLoader.getSystemClassLoader();
+                        }
+                        try {
+                            defaultSocketFactory = (SocketFactory) Class.forName(
+                                    defaultName, true, cl).newInstance();
+                         } catch (Exception e) {
+                            return e;
+                        }
+                    }
+                    return null;
+                }
+            });
+        }
+
+        if (defaultSocketFactory == null) {
+            // Try to find in providers
+            SSLContext context = DefaultSSLContext.getContext();
+            if (context != null) {
+                defaultSocketFactory = context.getSocketFactory();
+            }
+        }
+        if (defaultSocketFactory == null) {
+            // Use internal implementation
+            defaultSocketFactory = new DefaultSSLSocketFactory("No SSLSocketFactory installed");
+        }
+        // BEGIN android-added
+        log("SSLSocketFactory", "Using factory " + defaultSocketFactory);
+        // END android-added
+        return defaultSocketFactory;
     }
 
     // BEGIN android-added
     @SuppressWarnings("unchecked")
     private static void log(String tag, String msg) {
-        Logger.getLogger(tag).info(msg);
+        try {
+            Class clazz = Class.forName("android.util.Log");
+            Method method = clazz.getMethod("d", new Class[] { String.class, String.class });
+            method.invoke(null, new Object[] { tag, msg });
+        } catch (Exception ex) {
+            // Silently ignore.
+        }
     }
     // END android-added
 
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
deleted file mode 100644
index a95d38f..0000000
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import java.util.*;
-import java.util.logging.Level;
-import java.io.*;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-import javax.security.cert.X509Certificate;
-import javax.security.cert.CertificateEncodingException;
-import javax.security.cert.CertificateException;
-
-/**
- * Supports SSL session caches.
- */
-abstract class AbstractSessionContext implements SSLSessionContext {
-
-    volatile int maximumSize;
-    volatile int timeout;
-
-    final SSLParameters parameters;
-
-    /** Identifies OpenSSL sessions. */
-    static final int OPEN_SSL = 1;
-
-    /**
-     * Constructs a new session context.
-     *
-     * @param parameters
-     * @param maximumSize of cache
-     * @param timeout for cache entries
-     */
-    AbstractSessionContext(SSLParameters parameters, int maximumSize,
-            int timeout) {
-        this.parameters = parameters;
-        this.maximumSize = maximumSize;
-        this.timeout = timeout;
-    }
-
-    /**
-     * Returns the collection of sessions ordered by least-recently-used first.
-     */
-    abstract Iterator<SSLSession> sessionIterator();
-
-    public final Enumeration getIds() {
-        final Iterator<SSLSession> iterator = sessionIterator();
-        return new Enumeration<byte[]>() {
-            public boolean hasMoreElements() {
-                return iterator.hasNext();
-            }
-            public byte[] nextElement() {
-                return iterator.next().getId();
-            }
-        };
-    }
-
-    public final int getSessionCacheSize() {
-        return maximumSize;
-    }
-
-    public final int getSessionTimeout() {
-        return timeout;
-    }
-
-    /**
-     * Makes sure cache size is < maximumSize.
-     */
-    abstract void trimToSize();
-
-    public final void setSessionCacheSize(int size)
-            throws IllegalArgumentException {
-        if (size < 0) {
-            throw new IllegalArgumentException("size < 0");
-        }
-
-        int oldMaximum = maximumSize;
-        maximumSize = size;
-
-        // Trim cache to size if necessary.
-        if (size < oldMaximum) {
-            trimToSize();
-        }
-    }
-
-    /**
-     * Converts the given session to bytes.
-     *
-     * @return session data as bytes or null if the session can't be converted
-     */
-    byte[] toBytes(SSLSession session) {
-        // TODO: Support SSLSessionImpl, too.
-        if (!(session instanceof OpenSSLSessionImpl)) {
-            return null;
-        }
-
-        OpenSSLSessionImpl sslSession = (OpenSSLSessionImpl) session;
-        try {
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataOutputStream daos = new DataOutputStream(baos);
-
-            daos.writeInt(OPEN_SSL); // session type ID
-
-            // Session data.
-            byte[] data = sslSession.getEncoded();
-            daos.writeInt(data.length);
-            daos.write(data);
-
-            // Certificates.
-            X509Certificate[] certs = session.getPeerCertificateChain();
-            daos.writeInt(certs.length);
-
-            // TODO: Call nativegetpeercertificates()
-            for (X509Certificate cert : certs) {
-                data = cert.getEncoded();
-                daos.writeInt(data.length);
-                daos.write(data);
-            }
-
-            return baos.toByteArray();
-        } catch (IOException e) {
-            log(e);
-            return null;
-        } catch (CertificateEncodingException e) {
-            log(e);
-            return null;
-        }
-    }
-
-    /**
-     * Creates a session from the given bytes.
-     *
-     * @return a session or null if the session can't be converted
-     */
-    SSLSession toSession(byte[] data, String host, int port) {
-        ByteArrayInputStream bais = new ByteArrayInputStream(data);
-        DataInputStream dais = new DataInputStream(bais);
-        try {
-            int type = dais.readInt();
-            if (type != OPEN_SSL) {
-                log(new AssertionError("Unexpected type ID: " + type));
-                return null;
-            }
-
-            int length = dais.readInt();
-            byte[] sessionData = new byte[length];
-            dais.readFully(sessionData);
-
-            int count = dais.readInt();
-            X509Certificate[] certs = new X509Certificate[count];
-            for (int i = 0; i < count; i++) {
-                length = dais.readInt();
-                byte[] certData = new byte[length];
-                dais.readFully(certData);
-                certs[i] = X509Certificate.getInstance(certData);
-            }
-
-            return new OpenSSLSessionImpl(sessionData, parameters, host, port,
-                    certs, this);
-        } catch (IOException e) {
-            log(e);
-            return null;
-        } catch (CertificateException e) {
-            log(e);
-            return null;
-        }
-    }
-
-    static void log(Throwable t) {
-        java.util.logging.Logger.global.log(Level.WARNING,
-                "Error converting session.", t);
-    }
-
-    /**
-     * Byte array wrapper. Implements equals() and hashCode().
-     */
-    static class ByteArray {
-
-        private final byte[] bytes;
-
-        ByteArray(byte[] bytes) {
-            this.bytes = bytes;
-        }
-
-        @Override
-        public int hashCode() {
-            return Arrays.hashCode(bytes);
-        }
-
-        @Override
-        @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
-        public boolean equals(Object o) {
-            ByteArray other = (ByteArray) o;
-            return Arrays.equals(bytes, other.bytes);
-        }
-    }
-}
\ No newline at end of file
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
index 55a06f5..8419096 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
@@ -613,18 +613,22 @@
             host = engineOwner.getPeerHost();
             port = engineOwner.getPeerPort();
         }
+        // END android-changed
         if (host == null || port == -1) {
             return null; // starts new session
         }
         
-        ClientSessionContext context = parameters.getClientSessionContext();
-        SSLSessionImpl session
-                = (SSLSessionImpl) context.getSession(host, port);
-        if (session != null) {
-            session = (SSLSessionImpl) session.clone();
+        byte[] id;
+        SSLSession ses;
+        SSLSessionContext context = parameters.getClientSessionContext();
+        for (Enumeration en = context.getIds(); en.hasMoreElements();) {
+            id = (byte[])en.nextElement();
+            ses = context.getSession(id);
+            if (host.equals(ses.getPeerHost()) && port == ses.getPeerPort()) {
+                return (SSLSessionImpl)((SSLSessionImpl)ses).clone(); // resume
+            }            
         }
-        return session;
-        // END android-changed
+        return null; // starts new session
     }
 
 }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
deleted file mode 100644
index 2c8738f..0000000
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import javax.net.ssl.SSLSession;
-
-/**
- * Caches client sessions. Indexes by host and port. Users are typically
- * looking to reuse any session for a given host and port. Users of the
- * standard API are forced to iterate over the sessions semi-linearly as
- * opposed to in constant time.
- */
-public class ClientSessionContext extends AbstractSessionContext {
-
-    /*
-     * We don't care about timeouts in the client implementation. Trying
-     * to reuse an expired session and having to start a new one requires no
-     * more effort than starting a new one, so you might as well try to reuse
-     * one on the off chance it's still valid.
-     */
-
-    /** Sessions indexed by host and port in access order. */
-    final Map<HostAndPort, SSLSession> sessions
-            = new LinkedHashMap<HostAndPort, SSLSession>() {
-        @Override
-        protected boolean removeEldestEntry(
-                Map.Entry<HostAndPort, SSLSession> eldest) {
-            // Called while lock is held on sessions.
-            boolean remove = maximumSize > 0 && size() > maximumSize;
-            if (remove) {
-                removeById(eldest.getValue());
-            }
-            return remove;
-        }
-    };
-
-    /**
-     * Sessions indexed by ID. Initialized on demand. Protected from concurrent
-     * access by holding a lock on sessions.
-     */
-    Map<ByteArray, SSLSession> sessionsById;
-
-    final SSLClientSessionCache persistentCache;
-
-    public ClientSessionContext(SSLParameters parameters,
-            SSLClientSessionCache persistentCache) {
-        super(parameters, 10, 0);
-        this.persistentCache = persistentCache;
-    }
-
-    public final void setSessionTimeout(int seconds)
-            throws IllegalArgumentException {
-        if (seconds < 0) {
-            throw new IllegalArgumentException("seconds < 0");
-        }
-        timeout = seconds;
-    }
-
-    Iterator<SSLSession> sessionIterator() {
-        synchronized (sessions) {
-            SSLSession[] array = sessions.values().toArray(
-                    new SSLSession[sessions.size()]);
-            return Arrays.asList(array).iterator();
-        }
-    }
-
-    void trimToSize() {
-        synchronized (sessions) {
-            int size = sessions.size();
-            if (size > maximumSize) {
-                int removals = size - maximumSize;
-                Iterator<SSLSession> i = sessions.values().iterator();
-                do {
-                    removeById(i.next());
-                    i.remove();
-                } while (--removals > 0);                
-            }
-        }
-    }
-
-    void removeById(SSLSession session) {
-        if (sessionsById != null) {
-            sessionsById.remove(new ByteArray(session.getId()));
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @see #getSession(String, int) for an implementation-specific but more
-     *  efficient approach
-     */
-    public SSLSession getSession(byte[] sessionId) {
-        /*
-         * This method is typically used in conjunction with getIds() to
-         * iterate over the sessions linearly, so it doesn't make sense for
-         * it to impact access order.
-         *
-         * It also doesn't load sessions from the persistent cache as doing
-         * so would likely force every session to load.
-         */
-
-        ByteArray id = new ByteArray(sessionId);
-        synchronized (sessions) {
-            indexById();
-            return sessionsById.get(id);
-        }
-    }
-
-    /**
-     * Ensures that the ID-based index is initialized.
-     */
-    private void indexById() {
-        if (sessionsById == null) {
-            sessionsById = new HashMap<ByteArray, SSLSession>();
-            for (SSLSession session : sessions.values()) {
-                sessionsById.put(new ByteArray(session.getId()), session);
-            }
-        }
-    }
-
-    /**
-     * Adds the given session to the ID-based index if the index has already
-     * been initialized.
-     */
-    private void indexById(SSLSession session) {
-        if (sessionsById != null) {
-            sessionsById.put(new ByteArray(session.getId()), session);
-        }
-    }
-
-    /**
-     * Finds a cached session for the given host name and port.
-     *
-     * @param host of server
-     * @param port of server
-     * @return cached session or null if none found
-     */
-    public SSLSession getSession(String host, int port) {
-        synchronized (sessions) {
-            SSLSession session = sessions.get(new HostAndPort(host, port));
-            if (session != null) {
-                return session;
-            }
-        }
-
-        // Look in persistent cache.
-        if (persistentCache != null) {
-            byte[] data = persistentCache.getSessionData(host, port);
-            if (data != null) {
-                SSLSession session = toSession(data, host, port);
-                if (session != null) {
-                    synchronized (sessions) {
-                        sessions.put(new HostAndPort(host, port), session);
-                        indexById(session);
-                    }
-                    return session;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    void putSession(SSLSession session) {
-        HostAndPort key = new HostAndPort(session.getPeerHost(),
-                session.getPeerPort());
-        synchronized (sessions) {
-            sessions.put(key, session);
-            indexById(session);
-        }
-
-        // TODO: This in a background thread.
-        if (persistentCache != null) {
-            byte[] data = toBytes(session);
-            if (data != null) {
-                persistentCache.putSessionData(session, data);
-            }
-        }
-    }
-
-    static class HostAndPort {
-        final String host;
-        final int port;
-
-        HostAndPort(String host, int port) {
-            this.host = host;
-            this.port = port;
-        }
-
-        @Override
-        public int hashCode() {
-            return host.hashCode() * 31 + port;
-        }
-
-        @Override
-        @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
-        public boolean equals(Object o) {
-            HostAndPort other = (HostAndPort) o;
-            return host.equals(other.host) && port == other.port;
-        }
-    }
-}
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java
deleted file mode 100644
index ab097e4..0000000
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import javax.net.ssl.SSLSession;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.Iterator;
-import java.util.Arrays;
-import java.util.logging.Level;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * File-based cache implementation. Only one process should access the
- * underlying directory at a time.
- */
-public class FileClientSessionCache {
-
-    static final int MAX_SIZE = 20;
-
-    static final java.util.logging.Logger logger
-            = java.util.logging.Logger.getLogger(
-                    FileClientSessionCache.class.getName());
-
-    private FileClientSessionCache() {}
-
-    /**
-     * This cache creates one file per SSL session using "host.port" for
-     * the file name. Files are created or replaced when session data is put
-     * in the cache (see {@link #putSessionData}). Files are read on
-     * cache hits, but not on cache misses.
-     *
-     * <p>When the number of session files exceeds MAX_SIZE, we delete the
-     * least-recently-used file. We don't current persist the last access time,
-     * so the ordering actually ends up being least-recently-modified in some
-     * cases and even just "not accessed in this process" if the filesystem
-     * doesn't track last modified times.
-     */
-    static class Impl implements SSLClientSessionCache {
-
-        /** Directory to store session files in. */
-        final File directory;
-
-        /**
-         * Map of name -> File. Keeps track of the order files were accessed in.
-         */
-        Map<String, File> accessOrder = newAccessOrder();
-
-        /** The number of files on disk. */
-        int size;
-
-        /**
-         * The initial set of files. We use this to defer adding information
-         * about all files to accessOrder until necessary.
-         */
-        String[] initialFiles;
-
-        /**
-         * Constructs a new cache backed by the given directory.
-         */
-        Impl(File directory) throws IOException {
-            boolean exists = directory.exists();
-            if (exists && !directory.isDirectory()) {
-                throw new IOException(directory
-                        + " exists but is not a directory.");
-            }
-
-            if (exists) {
-                // Read and sort initial list of files. We defer adding
-                // information about these files to accessOrder until necessary
-                // (see indexFiles()). Sorting the list enables us to detect
-                // cache misses in getSessionData().
-                // Note: Sorting an array here was faster than creating a
-                // HashSet on Dalvik.
-                initialFiles = directory.list();
-                Arrays.sort(initialFiles);
-                size = initialFiles.length;
-            } else {
-                // Create directory.
-                if (!directory.mkdirs()) {
-                    throw new IOException("Creation of " + directory
-                            + " directory failed.");
-                }
-                size = 0;
-            }
-
-            this.directory = directory;
-        }
-
-        /**
-         * Creates a new access-ordered linked hash map.
-         */
-        private static Map<String, File> newAccessOrder() {
-            return new LinkedHashMap<String, File>(
-                    MAX_SIZE, 0.75f, true /* access order */);
-        }
-
-        /**
-         * Gets the file name for the given host and port.
-         */
-        private static String fileName(String host, int port) {
-            if (host == null) {
-                throw new NullPointerException("host");
-            }
-            return host + "." + port;
-        }
-
-        public synchronized byte[] getSessionData(String host, int port) {
-            /*
-             * Note: This method is only called when the in-memory cache
-             * in SSLSessionContext misses, so it would be unnecesarily
-             * rendundant for this cache to store data in memory.
-             */
-
-            String name = fileName(host, port);
-            File file = accessOrder.get(name);
-
-            if (file == null) {
-                // File wasn't in access order. Check initialFiles...
-                if (initialFiles == null) {
-                    // All files are in accessOrder, so it doesn't exist.
-                    return null;
-                }
-
-                // Look in initialFiles.
-                if (Arrays.binarySearch(initialFiles, name) < 0) {
-                    // Not found.
-                    return null;
-                }
-
-                // The file is on disk but not in accessOrder yet.
-                file = new File(directory, name);
-                accessOrder.put(name, file);
-            }
-
-            FileInputStream in;
-            try {
-                in = new FileInputStream(file);
-            } catch (FileNotFoundException e) {
-                logReadError(host, e);
-                return null;
-            }
-            try {
-                int size = (int) file.length();
-                byte[] data = new byte[size];
-                new DataInputStream(in).readFully(data);
-                logger.log(Level.FINE, "Read session for " + host + ".");
-                return data;
-            } catch (IOException e) {
-                logReadError(host, e);
-                return null;
-            } finally {
-                try {
-                    in.close();
-                } catch (IOException e) { /* ignore */ }
-            }
-        }
-
-        static void logReadError(String host, Throwable t) {
-            logger.log(Level.INFO, "Error reading session data for " + host
-                    + ".", t);
-        }
-
-        public synchronized void putSessionData(SSLSession session,
-                byte[] sessionData) {
-            String host = session.getPeerHost();
-            if (sessionData == null) {
-                throw new NullPointerException("sessionData");
-            }
-
-            String name = fileName(host, session.getPeerPort());
-            File file = new File(directory, name);
-
-            // Used to keep track of whether or not we're expanding the cache.
-            boolean existedBefore = file.exists();
-
-            FileOutputStream out;
-            try {
-                out = new FileOutputStream(file);
-            } catch (FileNotFoundException e) {
-                // We can't write to the file.
-                logWriteError(host, e);
-                return;
-            }
-
-            // If we expanded the cache (by creating a new file)...
-            if (!existedBefore) {
-                size++;
-
-                // Delete an old file if necessary.
-                makeRoom();
-            }
-
-            boolean writeSuccessful = false;
-            try {
-                out.write(sessionData);
-                writeSuccessful = true;
-            } catch (IOException e) {
-                logWriteError(host, e);
-            } finally {
-                boolean closeSuccessful = false;
-                try {
-                    out.close();
-                    closeSuccessful = true;
-                } catch (IOException e) {
-                    logWriteError(host, e);
-                } finally {
-                    if (!writeSuccessful || !closeSuccessful) {
-                        // Storage failed. Clean up.
-                        delete(file);
-                    } else {
-                        // Success!
-                        accessOrder.put(name, file);
-                        logger.log(Level.FINE, "Stored session for " + host
-                                + ".");
-                    }
-                }
-            }
-        }
-
-        /**
-         * Deletes old files if necessary.
-         */
-        private void makeRoom() {
-            if (size <= MAX_SIZE) {
-                return;
-            }
-
-            indexFiles();
-
-            // Delete LRUed files.
-            int removals = size - MAX_SIZE;
-            Iterator<File> i = accessOrder.values().iterator();
-            do {
-                delete(i.next());
-                i.remove();
-            } while (--removals > 0);
-        }
-
-        /**
-         * Lazily updates accessOrder to know about all files as opposed to
-         * just the files accessed since this process started.
-         */
-        private void indexFiles() {
-            String[] initialFiles = this.initialFiles;
-            if (initialFiles != null) {
-                this.initialFiles = null;
-
-                // Files on disk only, sorted by last modified time.
-                // TODO: Use last access time.
-                Set<CacheFile> diskOnly = new TreeSet<CacheFile>();
-                for (String name : initialFiles) {
-                    // If the file hasn't been accessed in this process...
-                    if (!accessOrder.containsKey(name)) {
-                        diskOnly.add(new CacheFile(directory, name));
-                    }
-                }
-
-                if (!diskOnly.isEmpty()) {
-                    // Add files not accessed in this process to the beginning
-                    // of accessOrder.
-                    Map<String, File> newOrder = newAccessOrder();
-                    for (CacheFile cacheFile : diskOnly) {
-                        newOrder.put(cacheFile.name, cacheFile);
-                    }
-                    newOrder.putAll(accessOrder);
-    
-                    this.accessOrder = newOrder;
-                }
-            }
-        }
-
-        @SuppressWarnings("ThrowableInstanceNeverThrown")
-        private void delete(File file) {
-            if (!file.delete()) {
-                logger.log(Level.INFO, "Failed to delete " + file + ".",
-                        new IOException());
-            }
-            size--;
-        }
-
-        static void logWriteError(String host, Throwable t) {
-            logger.log(Level.INFO, "Error writing session data for "
-                    + host + ".", t);
-        }
-    }
-
-    /**
-     * Maps directories to the cache instances that are backed by those
-     * directories. We synchronize access using the cache instance, so it's
-     * important that everyone shares the same instance.
-     */
-    static final Map<File, FileClientSessionCache.Impl> caches
-            = new HashMap<File, FileClientSessionCache.Impl>();
-
-    /**
-     * Returns a cache backed by the given directory. Creates the directory
-     * (including parent directories) if necessary. This cache should have
-     * exclusive access to the given directory.
-     *
-     * @param directory to store files in
-     * @return a cache backed by the given directory
-     * @throws IOException if the file exists and is not a directory or if
-     *  creating the directories fails
-     */
-    public static synchronized SSLClientSessionCache usingDirectory(
-            File directory) throws IOException {
-        FileClientSessionCache.Impl cache = caches.get(directory);
-        if (cache == null) {
-            cache = new FileClientSessionCache.Impl(directory);
-            caches.put(directory, cache);
-        }
-        return cache;
-    }
-
-    /** For testing. */
-    static synchronized void reset() {
-        caches.clear();
-    }
-
-    /** A file containing a piece of cached data. */
-    static class CacheFile extends File {
-
-        final String name;
-
-        CacheFile(File dir, String name) {
-            super(dir, name);
-            this.name = name;
-        }
-
-        long lastModified = -1;
-
-        @Override
-        public long lastModified() {
-            long lastModified = this.lastModified;
-            if (lastModified == -1) {
-                lastModified = this.lastModified = super.lastModified();
-            }
-            return lastModified;
-        }
-
-        @Override
-        public int compareTo(File another) {
-            // Sort by last modified time.
-            long result = lastModified() - another.lastModified();
-            if (result == 0) {
-                return super.compareTo(another);
-            }
-            return result < 0 ? -1 : 1;
-        }
-    }
-}
\ No newline at end of file
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
index e985908..4fc6e99 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
@@ -302,8 +302,7 @@
 
     @Override
     public Socket accept() throws IOException {
-        OpenSSLSocketImpl socket
-                = new OpenSSLSocketImpl(sslParameters, ssl_op_no);
+        OpenSSLSocketImpl socket = new OpenSSLSocketImpl(sslParameters, ssl_op_no);
         implAccept(socket);
         socket.accept(ssl_ctx, client_mode);
 
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
index ca7d6f8..475d388 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
@@ -23,7 +23,6 @@
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Iterator;
-import java.util.UnknownFormatConversionException;
 import java.util.Vector;
 
 import javax.net.ssl.SSLPeerUnverifiedException;
@@ -56,41 +55,21 @@
     private SSLParameters sslParameters;
     private String peerHost;
     private int peerPort;
-    private final SSLSessionContext sessionContext;
 
     /**
      * Class constructor creates an SSL session context given the appropriate
      * SSL parameters.
-     *
-     * @param session the Identifier for SSL session
      * @param sslParameters the SSL parameters like ciphers' suites etc.
+     * @param ssl the Identifier for SSL session
      */
-    protected OpenSSLSessionImpl(int session, SSLParameters sslParameters,
-            String peerHost, int peerPort, SSLSessionContext sessionContext) {
+    protected OpenSSLSessionImpl(int session, SSLParameters sslParameters, String peerHost, int peerPort) {
         this.session = session;
         this.sslParameters = sslParameters;
         this.peerHost = peerHost;
         this.peerPort = peerPort;
-        this.sessionContext = sessionContext;
     }
 
     /**
-     * Constructs a session from a byte[].
-     */
-    OpenSSLSessionImpl(byte[] derData, SSLParameters sslParameters,
-            String peerHost, int peerPort,
-            javax.security.cert.X509Certificate[] peerCertificateChain,
-            SSLSessionContext sessionContext)
-            throws IOException {
-        this.sslParameters = sslParameters;
-        this.peerHost = peerHost;
-        this.peerPort = peerPort;
-        this.peerCertificateChain = peerCertificateChain;
-        this.sessionContext = sessionContext;
-        initializeNative(derData);
-    }
-  
-    /**
      * Returns the identifier of the actual OpenSSL session.
      */
     private native byte[] nativegetid();
@@ -111,40 +90,6 @@
     private native long nativegetcreationtime();
 
     /**
-     * Serialize the native state of the session ( ID, cypher, keys - but 
-     * not certs ), using openSSL i2d_SSL_SESSION()
-     * 
-     * @return the DER encoding of the session. 
-     */
-    private native byte[] nativeserialize();
-    
-    /**
-     * Create a SSL_SESSION object using d2i_SSL_SESSION.
-     */
-    private native int nativedeserialize(byte[] data, int size);
-
-    /**
-     * Get the session object in DER format. This allows saving the session
-     * data or sharing it with other processes.  
-     */
-    byte[] getEncoded() {
-      return nativeserialize();
-    }
-
-    /**
-     * Init the underlying native object from DER data. This 
-     * allows loading the saved session.
-     * @throws IOException 
-     */
-    private void initializeNative(byte[] derData) throws IOException {
-      this.session = nativedeserialize(derData, derData.length);
-      if (this.session == 0) { 
-        throw new IOException("Invalid session data");
-      }
-    }
-    
-    
-    /**
      * Gets the creation time of the SSL session.
      * @return the session's creation time in milli seconds since 12.00 PM,
      * January 1st, 1970
@@ -392,7 +337,7 @@
         if (sm != null) {
             sm.checkPermission(new SSLPermission("getSSLSessionContext"));
         }
-        return sessionContext;
+        return sslParameters.getClientSessionContext();
     }
 
     /**
@@ -402,7 +347,7 @@
      * @return true if this session may be resumed.
      */
     public boolean isValid() {
-        SSLSessionContext context = sessionContext;
+        SSLSessionContextImpl context = sslParameters.getClientSessionContext();
         if (isValid
                 && context != null
                 && context.getSessionTimeout() != 0
@@ -427,7 +372,7 @@
      * of security, by the full machinery of the <code>AccessController</code>
      * class.
      *
-     * @param name the name of the binding to find.
+     * @param <code>String name</code> the name of the binding to find.
      * @return the value bound to that name, or null if the binding does not
      *         exist.
      * @throws <code>IllegalArgumentException</code> if the argument is null.
@@ -471,9 +416,9 @@
      * -data bounds are monitored, as a matter of security, by the full
      * machinery of the <code>AccessController</code> class.
      *
-     * @param name the name of the link (no null are
+     * @param <code>String name</code> the name of the link (no null are
      *            accepted!)
-     * @param value data object that shall be bound to
+     * @param <code>Object value</code> data object that shall be bound to
      *            name.
      * @throws <code>IllegalArgumentException</code> if one or both
      *             argument(s) is null.
@@ -499,7 +444,7 @@
      * monitored, as a matter of security, by the full machinery of the
      * <code>AccessController</code> class.
      *
-     * @param name the name of the link (no null are
+     * @param <code>String name</code> the name of the link (no null are
      *            accepted!)
      * @throws <code>IllegalArgumentException</code> if the argument is null.
      */
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
index 8779736..1d38ca9 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
@@ -21,6 +21,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
@@ -30,6 +31,7 @@
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -56,7 +58,7 @@
     private int ssl;
     private InputStream is;
     private OutputStream os;
-    private final Object handshakeLock = new Object();
+    private Object handshakeLock = new Object();
     private Object readLock = new Object();
     private Object writeLock = new Object();
     private SSLParameters sslParameters;
@@ -64,7 +66,7 @@
     private Socket socket;
     private boolean autoClose;
     private boolean handshakeStarted = false;
-    private ArrayList<HandshakeCompletedListener> listeners;
+    private ArrayList listeners;
     private long ssl_op_no = 0x00000000L;
     private int timeout = 0;
     private InetSocketAddress address;
@@ -135,11 +137,11 @@
     /**
      * Class constructor with 2 parameters
      *
-     * @param sslParameters Parameters for the SSL
+     * @param <code>SSLParameters sslParameters</code> Parameters for the SSL
      *            context
-     * @param ssl_op_no Parameter to set the enabled
+     * @param <code>long ssl_op_no</code> Parameter to set the enabled
      *            protocols
-     * @throws IOException if network fails
+     * @throws <code>IOException</code> if network fails
      */
     protected OpenSSLSocketImpl(SSLParameters sslParameters, long ssl_op_no) throws IOException {
         super();
@@ -151,9 +153,9 @@
     /**
      * Class constructor with 1 parameter
      *
-     * @param sslParameters Parameters for the SSL
+     * @param <code>SSLParameters sslParameters</code> Parameters for the SSL
      *            context
-     * @throws IOException if network fails
+     * @throws <code>IOException</code> if network fails
      */
     protected OpenSSLSocketImpl(SSLParameters sslParameters) throws IOException {
         super();
@@ -165,8 +167,11 @@
     /**
      * Class constructor with 3 parameters
      *
-     * @throws IOException if network fails
-     * @throws java.net.UnknownHostException host not defined
+     * @param <code> String host</code>
+     * @param <code>int port</code>
+     * @param <code>SSLParameters sslParameters</code>
+     * @throws <code>IOException</code> if network fails
+     * @throws <code>UnknownHostException</code> host not defined
      */
     protected OpenSSLSocketImpl(String host, int port,
             SSLParameters sslParameters)
@@ -181,8 +186,11 @@
     /**
      * Class constructor with 3 parameters: 1st is InetAddress
      *
-     * @throws IOException if network fails
-     * @throws java.net.UnknownHostException host not defined
+     * @param <code>InetAddress address</code>
+     * @param <code>int port</code>
+     * @param <code>SSLParameters sslParameters</code>
+     * @throws <code>IOException</code> if network fails
+     * @throws <code>UnknownHostException</code> host not defined
      */
     protected OpenSSLSocketImpl(InetAddress address, int port,
             SSLParameters sslParameters)
@@ -197,8 +205,13 @@
     /**
      * Class constructor with 5 parameters: 1st is host
      *
-     * @throws IOException if network fails
-     * @throws java.net.UnknownHostException host not defined
+     * @param <code>String host</code>
+     * @param <code>int port</code>
+     * @param <code>InetAddress localHost</code>
+     * @param <code>int localPort</code>
+     * @param <code>SSLParameters sslParameters</code>
+     * @throws <code>IOException</code> if network fails
+     * @throws <code>UnknownHostException</code> host not defined
      */
     protected OpenSSLSocketImpl(String host, int port, InetAddress clientAddress,
             int clientPort, SSLParameters sslParameters)
@@ -212,8 +225,13 @@
     /**
      * Class constructor with 5 parameters: 1st is InetAddress
      *
-     * @throws IOException if network fails
-     * @throws java.net.UnknownHostException host not defined
+     * @param <code>InetAddress address</code>
+     * @param <code>int port</code>
+     * @param <code>InetAddress localAddress</code>
+     * @param <code>int localPort</code>
+     * @param <code>SSLParameters sslParameters</code>
+     * @throws <code>IOException</code> if network fails
+     * @throws <code>UnknownHostException</code> host not defined
      */
     protected OpenSSLSocketImpl(InetAddress address, int port,
             InetAddress clientAddress, int clientPort, SSLParameters sslParameters)
@@ -228,7 +246,12 @@
      * Constructor with 5 parameters: 1st is socket. Enhances an existing socket
      * with SSL functionality.
      *
-     * @throws IOException if network fails
+     * @param <code>Socket socket</code>
+     * @param <code>String host</code>
+     * @param <code>int port</code>
+     * @param <code>boolean autoClose</code>
+     * @param <code>SSLParameters sslParameters</code>
+     * @throws <code>IOException</code> if network fails
      */
     protected OpenSSLSocketImpl(Socket socket, String host, int port,
             boolean autoClose, SSLParameters sslParameters) throws IOException {
@@ -255,26 +278,26 @@
      *
      * @return OpenSSLSessionImpl
      */
-    private OpenSSLSessionImpl getCachedClientSession() {
-        if (super.getInetAddress() == null ||
-                super.getInetAddress().getHostAddress() == null ||
-                super.getInetAddress().getHostName() == null) {
-            return null;
+    private OpenSSLSessionImpl getOpenSSLSessionImpl() {
+        try {
+            byte[] id;
+            SSLSession ses;
+            for (Enumeration<byte[]> en = sslParameters.getClientSessionContext().getIds(); en.hasMoreElements();) {
+                id = en.nextElement();
+                ses = sslParameters.getClientSessionContext().getSession(id);
+                if (ses instanceof OpenSSLSessionImpl && ses.isValid() &&
+                        super.getInetAddress() != null &&
+                        super.getInetAddress().getHostAddress() != null &&
+                        super.getInetAddress().getHostName().equals(ses.getPeerHost()) &&
+                        super.getPort() == ses.getPeerPort()) {
+                        return (OpenSSLSessionImpl) ses;
+                }
+            }
+        } catch (Exception ex) {
+            // It's not clear to me under what circumstances the above code
+            // might fail. I also can't reproduce it.
         }
-        ClientSessionContext sessionContext
-                = sslParameters.getClientSessionContext();
-        return (OpenSSLSessionImpl) sessionContext.getSession(
-                super.getInetAddress().getHostName(),
-                super.getPort());
-    }
-
-    /**
-     * Ensures that logger is lazily loaded. The outer class seems to load
-     * before logging is ready.
-     */
-    static class LoggerHolder {
-        static final Logger logger = Logger.getLogger(
-                OpenSSLSocketImpl.class.getName());
+        return null;
     }
 
     /**
@@ -294,60 +317,38 @@
                 return;
             }
         }
-
-        OpenSSLSessionImpl session = getCachedClientSession();
+        
+        {
+            // Debug
+            int size = 0;
+            for (Enumeration<byte[]> en = sslParameters.getClientSessionContext().getIds();
+                    en.hasMoreElements(); en.nextElement()) { size++; };
+        }
+        OpenSSLSessionImpl session = getOpenSSLSessionImpl();
 
         // Check if it's allowed to create a new session (default is true)
-        if (session == null && !sslParameters.getEnableSessionCreation()) {
+        if (!sslParameters.getEnableSessionCreation() && session == null) {
             throw new SSLHandshakeException("SSL Session may not be created");
         } else {
-            Socket socket = this.socket != null ? this.socket : this;
-            int sessionId = session != null ? session.session : 0;
-            if (nativeconnect(ssl_ctx, socket, sslParameters.getUseClientMode(),
-                    sessionId)) {
-                // nativeconnect shouldn't return true if the session is not
-                // done
+            if (nativeconnect(ssl_ctx, this.socket != null ?
+                    this.socket : this, sslParameters.getUseClientMode(), session != null ? session.session : 0)) {
                 session.lastAccessedTime = System.currentTimeMillis();
                 sslSession = session;
-
-                LoggerHolder.logger.fine("Reused cached session for "
-                        + getInetAddress().getHostName() + ".");
             } else {
-                if (session != null) {
-                    LoggerHolder.logger.fine("Reuse of cached session for "
-                            + getInetAddress().getHostName() + " failed.");
-                } else {
-                    LoggerHolder.logger.fine("Created new session for "
-                            + getInetAddress().getHostName() + ".");
-                }
-
-                ClientSessionContext sessionContext
-                        = sslParameters.getClientSessionContext();
-                if (address == null) {
-                    sslSession = new OpenSSLSessionImpl(
-                            nativegetsslsession(ssl), sslParameters,
-                            super.getInetAddress().getHostName(),
-                            super.getPort(), sessionContext);
-                } else  {
-                    sslSession = new OpenSSLSessionImpl(
-                            nativegetsslsession(ssl), sslParameters,
-                            address.getHostName(), address.getPort(),
-                            sessionContext);
-                }
-
+                if (address == null) sslSession = new OpenSSLSessionImpl(nativegetsslsession(ssl),
+                        sslParameters, super.getInetAddress().getHostName(), super.getPort());
+                else sslSession = new OpenSSLSessionImpl(nativegetsslsession(ssl),
+                        sslParameters, address.getHostName(), address.getPort());
                 try {
-                    X509Certificate[] peerCertificates = (X509Certificate[])
-                            sslSession.getPeerCertificates();
+                    X509Certificate[] peerCertificates = (X509Certificate[]) sslSession.getPeerCertificates();
 
-                    if (peerCertificates == null
-                            || peerCertificates.length == 0) {
+                    if (peerCertificates == null || peerCertificates.length == 0) {
                         throw new SSLException("Server sends no certificate");
                     }
 
-                    sslParameters.getTrustManager().checkServerTrusted(
-                            peerCertificates,
-                            nativecipherauthenticationmethod());
-                    sessionContext.putSession(sslSession);
+                    sslParameters.getTrustManager().checkServerTrusted(peerCertificates,
+                                                                       nativecipherauthenticationmethod());
+                    sslParameters.getClientSessionContext().putSession(sslSession);
                 } catch (CertificateException e) {
                     throw new SSLException("Not trusted server certificate", e);
                 }
@@ -359,8 +360,9 @@
             HandshakeCompletedEvent event =
                 new HandshakeCompletedEvent(this, sslSession);
             int size = listeners.size();
-            for (int i = 0; i < size; i++) {
-                listeners.get(i).handshakeCompleted(event);
+            for (int i=0; i<size; i++) {
+                ((HandshakeCompletedListener)listeners.get(i))
+                    .handshakeCompleted(event);
             }
         }
     }
@@ -379,27 +381,22 @@
 
         nativeaccept(this, m_ctx, client_mode);
 
-        ServerSessionContext sessionContext
-                = sslParameters.getServerSessionContext();
         sslSession = new OpenSSLSessionImpl(nativegetsslsession(ssl),
-                sslParameters, super.getInetAddress().getHostName(),
-                super.getPort(), sessionContext);
+                sslParameters, super.getInetAddress().getHostName(), super.getPort());
         sslSession.lastAccessedTime = System.currentTimeMillis();
-        sessionContext.putSession(sslSession);
     }
 
     /**
      * Callback methode for the OpenSSL native certificate verification process.
      *
-     * @param bytes Byte array containing the cert's
+     * @param <code>byte[][] bytes</code> Byte array containing the cert's
      *            information.
      * @return 0 if the certificate verification fails or 1 if OK
      */
     @SuppressWarnings("unused")
     private int verify_callback(byte[][] bytes) {
         try {
-            X509Certificate[] peerCertificateChain
-                    = new X509Certificate[bytes.length];
+            X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
             for(int i = 0; i < bytes.length; i++) {
                 peerCertificateChain[i] =
                     new X509CertImpl(javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded());
@@ -585,6 +582,7 @@
     /**
      * Registers a listener to be notified that a SSL handshake
      * was successfully completed on this connection.
+     * @param <code>HandShakeCompletedListener listener</code>
      * @throws <code>IllegalArgumentException</code> if listener is null.
      */
     public void addHandshakeCompletedListener(
@@ -600,6 +598,7 @@
 
     /**
      * The method removes a registered listener.
+     * @param <code>HandShakeCompletedListener listener</code>
      * @throws IllegalArgumentException if listener is null or not registered
      */
     public void removeHandshakeCompletedListener(
@@ -632,7 +631,7 @@
      * SSL sessions. If the flag is set to false, and there are no actual
      * sessions to resume, then there will be no successful handshaking.
      *
-     * @param flag true if session may be created; false
+     * @param <code>boolean flag</code> true if session may be created; false
      *            if a session already exists and must be resumed.
      */
     public void setEnableSessionCreation(boolean flag) {
@@ -684,9 +683,9 @@
      * This method enables the cipher suites listed by
      * getSupportedCipherSuites().
      *
-     * @param suites names of all the cipher suites to
+     * @param <code> String[] suites</code> names of all the cipher suites to
      *            put on use
-     * @throws IllegalArgumentException when one or more of the
+     * @throws <code>IllegalArgumentException</code> when one or more of the
      *             ciphers in array suites are not supported, or when the array
      *             is null.
      */
@@ -782,9 +781,9 @@
     /**
      * This method set the actual SSL socket to client mode.
      *
-     * @param mode true if the socket starts in client
+     * @param <code>boolean mode</code> true if the socket starts in client
      *            mode
-     * @throws IllegalArgumentException if mode changes during
+     * @throws <code>IllegalArgumentException</code> if mode changes during
      *             handshake.
      */
     public synchronized void setUseClientMode(boolean mode) {
@@ -819,7 +818,7 @@
      * Sets the SSL socket to use client's authentication. Relevant only for
      * server sockets!
      *
-     * @param need true if client authentication is
+     * @param <code>boolean need</code> true if client authentication is
      *            desired, false if not.
      */
     public void setNeedClientAuth(boolean need) {
@@ -832,7 +831,7 @@
      * method will continue the negotiation if the client decide not to send
      * authentication credentials.
      *
-     * @param want true if client authentication is
+     * @param <code>boolean want</code> true if client authentication is
      *            desired, false if not.
      */
     public void setWantClientAuth(boolean want) {
@@ -879,9 +878,6 @@
      *             socket's closure.
      */
     public void close() throws IOException {
-        // TODO: Close SSL sockets using a background thread so they close
-        // gracefully.
-
         synchronized (handshakeLock) {
             if (!handshakeStarted) {
                 handshakeStarted = true;
@@ -991,11 +987,10 @@
     }
 
     /**
-     * Helper class for a thread that knows how to call
-     * {@link OpenSSLSocketImpl#close} on behalf of instances being finalized,
-     * since that call can take arbitrarily long (e.g., due to a slow network),
-     * and an overly long-running finalizer will cause the process to be
-     * totally aborted.
+     * Helper class for a thread that knows how to call {@link #close} on behalf
+     * of instances being finalized, since that call can take arbitrarily long
+     * (e.g., due to a slow network), and an overly long-running finalizer will
+     * cause the process to be totally aborted.
      */
     private class Finalizer extends Thread {
         public void run() {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java
deleted file mode 100644
index 8a73fa5..0000000
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import javax.net.ssl.SSLSession;
-
-/**
- * A persistent {@link javax.net.ssl.SSLSession} cache used by
- * {@link javax.net.ssl.SSLSessionContext} to share client-side SSL sessions
- * across processes. For example, this cache enables applications to
- * persist and reuse sessions across restarts.
- *
- * <p>The {@code SSLSessionContext} implementation converts
- * {@code SSLSession}s into raw bytes and vice versa. The exact makeup of the
- * session data is dependent upon the caller's implementation and is opaque to
- * the {@code SSLClientSessionCache} implementation.
- */
-public interface SSLClientSessionCache {
-
-  /**
-   * Gets data from a pre-existing session for a given server host and port.
-   *
-   * @param host from {@link javax.net.ssl.SSLSession#getPeerHost()}
-   * @param port from {@link javax.net.ssl.SSLSession#getPeerPort()}
-   * @return the session data or null if none is cached
-   * @throws NullPointerException if host is null
-   */
-  public byte[] getSessionData(String host, int port);
-
-  /**
-   * Stores session data for the given session.
-   *
-   * @param session to cache data for
-   * @param sessionData to cache
-   * @throws NullPointerException if session, result of
-   *  {@code session.getPeerHost()} or data is null
-   */
-  public void putSessionData(SSLSession session, byte[] sessionData);
-}
\ No newline at end of file
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
index 2e4de04..3f4ab96 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
@@ -22,6 +22,9 @@
 
 package org.apache.harmony.xnet.provider.jsse;
 
+// BEGIN android-removed
+// import org.apache.harmony.xnet.provider.jsse.SSLSocketFactoryImpl;
+// END android-removed
 import org.apache.harmony.xnet.provider.jsse.SSLEngineImpl;
 import org.apache.harmony.xnet.provider.jsse.SSLParameters;
 // BEGIN android-removed
@@ -39,21 +42,19 @@
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 
-// BEGIN android-note
-//  Modified heavily during SSLSessionContext refactoring. Added support for
-//  persistent session caches.
-// END android-note
-
 /**
  * Implementation of SSLContext service provider interface.
  */
 public class SSLContextImpl extends SSLContextSpi {
 
-    /** Client session cache. */
-    private ClientSessionContext clientSessionContext;
-
-    /** Server session cache. */
-    private ServerSessionContext serverSessionContext;
+    // client session context contains the set of reusable
+    // client-side SSL sessions
+    private SSLSessionContextImpl clientSessionContext =
+        new SSLSessionContextImpl();
+    // server session context contains the set of reusable
+    // server-side SSL sessions
+    private SSLSessionContextImpl serverSessionContext =
+        new SSLSessionContextImpl();
 
     protected SSLParameters sslParameters;
 
@@ -63,44 +64,26 @@
 
     public void engineInit(KeyManager[] kms, TrustManager[] tms,
             SecureRandom sr) throws KeyManagementException {
-        engineInit(kms, tms, sr, null, null);
-    }
-
-    /**
-     * Initializes this {@code SSLContext} instance. All of the arguments are
-     * optional, and the security providers will be searched for the required
-     * implementations of the needed algorithms.
-     *
-     * @param kms the key sources or {@code null}
-     * @param tms the trust decision sources or {@code null}
-     * @param sr the randomness source or {@code null}
-     * @param clientCache persistent client session cache or {@code null}
-     * @param serverCache persistent server session cache or {@code null}
-     * @throws KeyManagementException if initializing this instance fails
-     * 
-     * @since Android 1.1
-     */
-    public void engineInit(KeyManager[] kms, TrustManager[] tms,
-            SecureRandom sr, SSLClientSessionCache clientCache,
-            SSLServerSessionCache serverCache) throws KeyManagementException {
-        sslParameters = new SSLParameters(kms, tms, sr,
-                clientCache, serverCache);
-        clientSessionContext = sslParameters.getClientSessionContext();
-        serverSessionContext = sslParameters.getServerSessionContext();
+        sslParameters = new SSLParameters(kms, tms, sr, clientSessionContext,
+                serverSessionContext);
     }
 
     public SSLSocketFactory engineGetSocketFactory() {
         if (sslParameters == null) {
             throw new IllegalStateException("SSLContext is not initiallized.");
         }
+        // BEGIN android-changed
         return new OpenSSLSocketFactoryImpl(sslParameters);
+        // END android-changed
     }
 
     public SSLServerSocketFactory engineGetServerSocketFactory() {
         if (sslParameters == null) {
             throw new IllegalStateException("SSLContext is not initiallized.");
         }
+        // BEGIN android-changed
         return new OpenSSLServerSocketFactoryImpl(sslParameters);
+        // END android-changed
     }
 
     public SSLEngine engineCreateSSLEngine(String host, int port) {
@@ -118,11 +101,12 @@
         return new SSLEngineImpl((SSLParameters) sslParameters.clone());
     }
 
-    public ServerSessionContext engineGetServerSessionContext() {
+    public SSLSessionContext engineGetServerSessionContext() {
         return serverSessionContext;
     }
 
-    public ClientSessionContext engineGetClientSessionContext() {
+    public SSLSessionContext engineGetClientSessionContext() {
         return clientSessionContext;
     }
-}
\ No newline at end of file
+}
+
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
index 60a5535..9a14f46 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
@@ -22,6 +22,8 @@
 
 package org.apache.harmony.xnet.provider.jsse;
 
+import org.apache.harmony.xnet.provider.jsse.SSLSessionContextImpl;
+
 import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -43,9 +45,7 @@
  * and controls whether new SSL sessions may be established by this
  * socket or not.
  */
-// BEGIN android-changed
-public class SSLParameters implements Cloneable {
-// END android-changed
+public class SSLParameters {
 
     // default source of authentication keys
     private static X509KeyManager defaultKeyManager;
@@ -58,12 +58,10 @@
 
     // client session context contains the set of reusable
     // client-side SSL sessions
-// BEGIN android-changed
-    private final ClientSessionContext clientSessionContext;
+    private SSLSessionContextImpl clientSessionContext;
     // server session context contains the set of reusable
     // server-side SSL sessions
-    private final ServerSessionContext serverSessionContext;
-// END android-changed
+    private SSLSessionContextImpl serverSessionContext;
     // source of authentication keys
     private X509KeyManager keyManager;
     // source of authentication trust decisions
@@ -90,7 +88,16 @@
     // if the peer with this parameters allowed to cteate new SSL session
     private boolean enable_session_creation = true;
 
-// BEGIN android-changed
+    /**
+     * Creates an instance of SSLParameters.
+     */
+    private SSLParameters() {
+        // BEGIN android-removed
+        // this.enabledCipherSuites = CipherSuite.defaultCipherSuites;
+        // END android-removed
+    }
+
+    // BEGIN android-added
     protected CipherSuite[] getEnabledCipherSuitesMember() {
         if (enabledCipherSuites == null) this.enabledCipherSuites = CipherSuite.defaultCipherSuites;
         return enabledCipherSuites;
@@ -113,26 +120,23 @@
         if (ssl_ctx == 0) ssl_ctx = nativeinitsslctx();
         return ssl_ctx;
     }
-// END android-changed
+    // END android-added
 
     /**
      * Initializes the parameters. Naturally this constructor is used
      * in SSLContextImpl.engineInit method which dirrectly passes its 
      * parameters. In other words this constructor holds all
      * the functionality provided by SSLContext.init method.
-     * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[],
-     * SecureRandom)} for more information
+     * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[],SecureRandom)}
+     * for more information
      */
     protected SSLParameters(KeyManager[] kms, TrustManager[] tms,
-// BEGIN android-changed
-            SecureRandom sr, SSLClientSessionCache clientCache,
-            SSLServerSessionCache serverCache)
+            SecureRandom sr, SSLSessionContextImpl clientSessionContext,
+            SSLSessionContextImpl serverSessionContext)
             throws KeyManagementException {
-        this.serverSessionContext
-                = new ServerSessionContext(this, serverCache);
-        this.clientSessionContext
-                = new ClientSessionContext(this, clientCache);
-// END android-changed
+        this();
+        this.serverSessionContext = serverSessionContext;
+        this.clientSessionContext = clientSessionContext;
         try {
             // initialize key manager
             boolean initialize_default = false;
@@ -224,9 +228,8 @@
 
     protected static SSLParameters getDefault() throws KeyManagementException {
         if (defaultParameters == null) {
-// BEGIN android-changed
-            defaultParameters = new SSLParameters(null, null, null, null, null);
-// END android-changed
+            defaultParameters = new SSLParameters(null, null, null,
+                    new SSLSessionContextImpl(), new SSLSessionContextImpl());
         }
         return (SSLParameters) defaultParameters.clone();
     }
@@ -234,18 +237,14 @@
     /**
      * @return server session context
      */
-// BEGIN android-changed
-    protected ServerSessionContext getServerSessionContext() {
-// END android-changed
+    protected SSLSessionContextImpl getServerSessionContext() {
         return serverSessionContext;
     }
 
     /**
      * @return client session context
      */
-// BEGIN android-changed
-    protected ClientSessionContext getClientSessionContext() {
-// END android-changed
+    protected SSLSessionContextImpl getClientSessionContext() {
         return clientSessionContext;
     }
 
@@ -336,7 +335,7 @@
 
     /**
      * Sets the set of available protocols for use in SSL connection.
-     * @param protocols String[]
+     * @param   suites: String[]
      */
     protected void setEnabledProtocols(String[] protocols) {
         if (protocols == null) {
@@ -423,13 +422,23 @@
      * @return the clone.
      */
     protected Object clone() {
-// BEGIN android-changed
-        try {
-            return super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError(e);
-        }
-// END android-changed
+        SSLParameters parameters = new SSLParameters();
+
+        parameters.clientSessionContext = clientSessionContext;
+        parameters.serverSessionContext = serverSessionContext;
+        parameters.keyManager = keyManager;
+        parameters.trustManager = trustManager;
+        parameters.secureRandom = secureRandom;
+
+        parameters.enabledCipherSuites = enabledCipherSuites;
+        parameters.enabledProtocols = enabledProtocols;
+
+        parameters.client_mode = client_mode;
+        parameters.need_client_auth = need_client_auth;
+        parameters.want_client_auth = want_client_auth;
+        parameters.enable_session_creation = enable_session_creation;
+
+        return parameters;
     }
 }
 
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java
deleted file mode 100644
index 32a0e72..0000000
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import javax.net.ssl.SSLSession;
-
-/**
- * A persistent {@link javax.net.ssl.SSLSession} cache used by
- * {@link javax.net.ssl.SSLSessionContext} to share server-side SSL sessions
- * across processes. For example, this cache enables one server to resume
- * a session started by a different server based on a session ID provided
- * by the client.
- *
- * <p>The {@code SSLSessionContext} implementation converts
- * {@code SSLSession}s into raw bytes and vice versa. The exact makeup of the
- * session data is dependent upon the caller's implementation and is opaque to
- * the {@code SSLServerSessionCache} implementation.
- */
-public interface SSLServerSessionCache {
-
-  /**
-   * Gets the session data for given session ID.
-   *
-   * @param id from {@link javax.net.ssl.SSLSession#getId()}
-   * @return the session data or null if none is cached
-   * @throws NullPointerException if id is null
-   */
-  public byte[] getSessionData(byte[] id);
-
-  /**
-   * Stores session data for the given session.
-   *
-   * @param session to cache data for
-   * @param sessionData to cache
-   * @throws NullPointerException if session or data is null
-   */
-  public void putSessionData(SSLSession session, byte[] sessionData);
-}
\ No newline at end of file
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionContextImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionContextImpl.java
new file mode 100644
index 0000000..6882aa1
--- /dev/null
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionContextImpl.java
@@ -0,0 +1,168 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author Boris Kuznetsov
+ * @version $Revision$
+ */
+package org.apache.harmony.xnet.provider.jsse;
+
+import java.nio.ByteBuffer;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+
+/**
+ * SSLSessionContext implementation
+ * 
+ * @see javax.net.ssl.SSLSessionContext
+ */
+public class SSLSessionContextImpl implements SSLSessionContext {
+
+    private int cacheSize = 20;
+    private long timeout = 0;
+    private final LinkedHashMap<ByteBuffer, SSLSession> sessions =
+        new LinkedHashMap<ByteBuffer, SSLSession>(cacheSize, 0.75f, true) {
+        @Override
+        public boolean removeEldestEntry(
+                Map.Entry<ByteBuffer, SSLSession> eldest) {
+            return cacheSize > 0 && this.size() > cacheSize;
+        }
+    };
+    private volatile LinkedHashMap<ByteBuffer, SSLSession> clone =
+            new LinkedHashMap<ByteBuffer, SSLSession>();
+
+    /**
+     * @see javax.net.ssl.SSLSessionContext#getIds()
+     */
+    public Enumeration<byte[]> getIds() {
+        return new Enumeration<byte[]>() {
+            Iterator<ByteBuffer> iterator = clone.keySet().iterator();
+            public boolean hasMoreElements() {
+                return iterator.hasNext();
+            }
+            public byte[] nextElement() {
+                return iterator.next().array();
+            }
+        };
+    }
+
+    /**
+     * @see javax.net.ssl.SSLSessionContext#getSession(byte[] sessionId)
+     */
+    public SSLSession getSession(byte[] sessionId) {
+        synchronized (sessions) {
+            return sessions.get(ByteBuffer.wrap(sessionId));
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.SSLSessionContext#getSessionCacheSize()
+     */
+    public int getSessionCacheSize() {
+        synchronized (sessions) {
+            return cacheSize;
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.SSLSessionContext#getSessionTimeout()
+     */
+    public int getSessionTimeout() {
+        synchronized (sessions) {
+            return (int) (timeout/1000);
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.SSLSessionContext#setSessionCacheSize(int size)
+     */
+    public void setSessionCacheSize(int size) throws IllegalArgumentException {
+        if (size < 0) {
+            throw new IllegalArgumentException("size < 0");
+        }
+        synchronized (sessions) {
+            cacheSize = size;
+            if (cacheSize > 0 && cacheSize < sessions.size()) {
+                int removals = sessions.size() - cacheSize;
+                Iterator<ByteBuffer> iterator = sessions.keySet().iterator();
+                while (removals-- > 0) {
+                    iterator.next();
+                    iterator.remove();
+                }
+                clone = (LinkedHashMap<ByteBuffer, SSLSession>)
+                        sessions.clone();
+            }
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.SSLSessionContext#setSessionTimeout(int seconds)
+     */
+    public void setSessionTimeout(int seconds) throws IllegalArgumentException {
+        if (seconds < 0) {
+            throw new IllegalArgumentException("seconds < 0");
+        }
+        synchronized (sessions) {
+            timeout = seconds*1000;
+            // Check timeouts and remove expired sessions
+            SSLSession ses;
+            Iterator<Map.Entry<ByteBuffer, SSLSession>> iterator =
+                    sessions.entrySet().iterator();
+            while (iterator.hasNext()) {
+                SSLSession session = iterator.next().getValue();
+                if (!session.isValid()) {
+                    // safe to remove with this special method since it doesn't
+                    // make the iterator throw a ConcurrentModificationException
+                    iterator.remove();
+                }
+            }
+            clone = (LinkedHashMap<ByteBuffer, SSLSession>) sessions.clone();
+        }
+    }
+
+    /**
+     * Adds session to the session cache
+     * @param ses
+     */
+    void putSession(SSLSession ses) {
+        synchronized (sessions) {
+            sessions.put(ByteBuffer.wrap(ses.getId()), ses);
+            clone = (LinkedHashMap<ByteBuffer, SSLSession>) sessions.clone();
+        }
+    }
+}
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
index 4510c96..df46094 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
@@ -40,6 +40,7 @@
 import javax.net.ssl.SSLSessionContext;
 
 import org.apache.harmony.luni.util.TwoKeyHashMap;
+import org.apache.harmony.xnet.provider.jsse.SSLSessionContextImpl;
 
 /**
  * 
@@ -82,9 +83,8 @@
     /**
      * Context of the session
      */
-// BEGIN android-changed
-    SSLSessionContext context;
-// END android-changed
+    SSLSessionContextImpl context;
+
 
     /**
      * certificates were sent to the peer 
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
index f6eef23..93dc9c4 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
@@ -81,6 +81,7 @@
 
     /**
      * Start session negotiation
+     * @param session
      */
     public void start() {
         if (session == null) { // initial handshake
@@ -298,7 +299,7 @@
                     clientFinished = new Finished(io_stream, length);
                     verifyFinished(clientFinished.getData());
                     // BEGIN android-added
-                    session.context = parameters.getServerSessionContext();
+                    session.context = parameters.getClientSessionContext();
                     // END android-added
                     parameters.getServerSessionContext().putSession(session);
                     if (!isResuming) {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
deleted file mode 100644
index a3c2c6d..0000000
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Iterator;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import javax.net.ssl.SSLSession;
-
-/**
- * Caches server sessions. Indexes by session ID. Users typically look up
- * sessions using the ID provided by an SSL client.
- */
-public class ServerSessionContext extends AbstractSessionContext {
-
-    /*
-     * TODO: Expire timed-out sessions more pro-actively.
-     */
-
-    private final Map<ByteArray, SSLSession> sessions
-            = new LinkedHashMap<ByteArray, SSLSession>() {
-        @Override
-        protected boolean removeEldestEntry(
-                Map.Entry<ByteArray, SSLSession> eldest) {
-            return maximumSize > 0 && size() > maximumSize;
-        }
-    };
-
-    private final SSLServerSessionCache persistentCache;
-
-    public ServerSessionContext(SSLParameters parameters,
-            SSLServerSessionCache persistentCache) {
-        super(parameters, 100, 0);
-        this.persistentCache = persistentCache;
-    }
-
-    Iterator<SSLSession> sessionIterator() {
-        synchronized (sessions) {
-            SSLSession[] array = sessions.values().toArray(
-                    new SSLSession[sessions.size()]);
-            return Arrays.asList(array).iterator();
-        }
-    }
-
-    void trimToSize() {
-        synchronized (sessions) {
-            int size = sessions.size();
-            if (size > maximumSize) {
-                int removals = size - maximumSize;
-                Iterator<SSLSession> i = sessions.values().iterator();
-                do {
-                    i.next();
-                    i.remove();
-                } while (--removals > 0);
-            }
-        }
-    }
-
-    public void setSessionTimeout(int seconds)
-            throws IllegalArgumentException {
-        if (seconds < 0) {
-            throw new IllegalArgumentException("seconds < 0");
-        }
-        timeout = seconds;
-    }
-
-    public SSLSession getSession(byte[] sessionId) {
-        ByteArray key = new ByteArray(sessionId);
-        synchronized (sessions) {
-            SSLSession session = sessions.get(key);
-            if (session != null) {
-                return session;
-            }
-        }
-
-        // Check persistent cache.
-        if (persistentCache != null) {
-            byte[] data = persistentCache.getSessionData(sessionId);
-            if (data != null) {
-                SSLSession session = toSession(data, null, -1);
-                if (session != null) {
-                    synchronized (sessions) {
-                        sessions.put(key, session);
-                    }
-                    return session;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    void putSession(SSLSession session) {
-        ByteArray key = new ByteArray(session.getId());
-        synchronized (sessions) {
-            sessions.put(key, session);
-        }
-
-        // TODO: In background thread.
-        if (persistentCache != null) {
-            byte[] data = toBytes(session);
-            if (data != null) {
-                persistentCache.putSessionData(session, data);
-            }
-        }
-    }
-}
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
index feae690..0c0e455 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
@@ -61,7 +61,7 @@
 }
 
 /**
- * Gets the peer certificate in the chain and fills a byte array with the
+ * Gets the peer certificate in the chain and fills a byte array with the 
  * information therein.
  */
 static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeercertificates(JNIEnv* env,
@@ -91,62 +91,7 @@
 }
 
 /**
- * Serialize the session.
- * See apache mod_ssl
- */
-static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_serialize(JNIEnv* env, jobject object)
-{
-  SSL_SESSION * ssl_session;
-  jbyteArray bytes = NULL;
-  jbyte *tmp;
-  int size;
-  unsigned char *ucp;
-
-  ssl_session = getSslSessionPointer(env, object);
-  if (ssl_session == NULL) {
-    return NULL;
-  }
-
-  // Compute the size of the DER data
-  size = i2d_SSL_SESSION(ssl_session, NULL);
-  if (size == 0) {
-    return NULL;
-  }
-
-  bytes = env->NewByteArray(size);
-  if (bytes != NULL) {
-        tmp = env->GetByteArrayElements(bytes, NULL);
-        ucp = (unsigned char *) tmp;
-        i2d_SSL_SESSION(ssl_session, &ucp);
-        env->ReleaseByteArrayElements(bytes, tmp, 0);
-  }
-
-  return bytes;
-
-}
-
-/**
- * Deserialize the session.
- */
-static jint org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_deserialize(JNIEnv* env, jobject object, jbyteArray bytes, jint size)
-{
-  const unsigned char *ucp;
-  jbyte *tmp;
-  SSL_SESSION *ssl_session;
-
-  if (bytes != NULL) {
-        tmp = env->GetByteArrayElements(bytes, NULL);
-        ucp = (const unsigned char *) tmp;
-        ssl_session = d2i_SSL_SESSION(NULL, &ucp, (long) size);
-        env->ReleaseByteArrayElements(bytes, tmp, 0);
-
-        return (jint) ssl_session;
-  }
-  return 0;
-}
-
-/**
- * Gets and returns in a byte array the ID of the actual SSL session.
+ * Gets and returns in a byte array the ID of the actual SSL session. 
  */
 static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getid(JNIEnv* env, jobject object)
 {
@@ -167,8 +112,8 @@
 }
 
 /**
- * Gets and returns in a long integer the creation's time of the
- * actual SSL session.
+ * Gets and returns in a long integer the creation's time of the 
+ * actual SSL session. 
  */
 static jlong org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getcreationtime(JNIEnv* env, jobject object)
 {
@@ -181,7 +126,7 @@
 }
 
 /**
- * Gets and returns in a string the peer's host's name.
+ * Gets and returns in a string the peer's host's name. 
  */
 static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerhost(JNIEnv* env, jobject object)
 {
@@ -213,7 +158,7 @@
 }
 
 /**
- * Gets and returns in a string the peer's port name (https, ftp, etc.).
+ * Gets and returns in a string the peer's port name (https, ftp, etc.). 
  */
 static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeerport(JNIEnv* env, jobject object)
 {
@@ -234,7 +179,7 @@
     bio = SSL_get_rbio(ssl);
     port = BIO_get_conn_port(bio);
 
-    /* Notice: port name can be NULL */
+    /* Notice: port name can be NULL */    
     result = env->NewStringUTF(port);
 
     SSL_free(ssl);
@@ -244,7 +189,7 @@
 }
 
 /**
- * Gets and returns in a string the version of the SSL protocol. If it
+ * Gets and returns in a string the version of the SSL protocol. If it 
  * returns the string "unknown" it means that no connection is established.
  */
 static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getprotocol(JNIEnv* env, jobject object)
@@ -273,7 +218,7 @@
 }
 
 /**
- * Gets and returns in a string the set of ciphers the actual SSL session uses.
+ * Gets and returns in a string the set of ciphers the actual SSL session uses. 
  */
 static jstring org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getciphersuite(JNIEnv* env, jobject object)
 {
@@ -319,9 +264,7 @@
     {"nativegetprotocol", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getprotocol},
     {"nativegetciphersuite", "()Ljava/lang/String;", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getciphersuite},
     {"nativegetpeercertificates", "()[[B", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getpeercertificates},
-    {"nativefree", "(I)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_free},
-    {"nativeserialize", "()[B", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_serialize},
-    {"nativedeserialize", "([BI)I", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_deserialize}
+    {"nativefree", "(I)V", (void*)org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_free}
 };
 
 /**
diff --git a/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java b/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java
deleted file mode 100644
index af4490b..0000000
--- a/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import junit.framework.TestCase;
-
-import javax.net.ssl.SSLSession;
-import java.util.Enumeration;
-import java.util.Set;
-import java.util.HashSet;
-
-public class ClientSessionContextTest extends TestCase {
-
-    public void testGetSessionById() {
-        ClientSessionContext context = new ClientSessionContext(null, null);
-
-        SSLSession a = new FakeSession("a");
-        SSLSession b = new FakeSession("b");
-
-        context.putSession(a);
-        context.putSession(b);
-
-        assertSame(a, context.getSession("a".getBytes()));
-        assertSame(b, context.getSession("b".getBytes()));
-
-        assertSame(a, context.getSession("a", 443));
-        assertSame(b, context.getSession("b", 443));
-
-        assertEquals(2, context.sessions.size());
-
-        Set<SSLSession> sessions = new HashSet<SSLSession>();
-        Enumeration ids = context.getIds();
-        while (ids.hasMoreElements()) {
-            sessions.add(context.getSession((byte[]) ids.nextElement()));
-        }
-
-        Set<SSLSession> expected = new HashSet<SSLSession>();
-        expected.add(a);
-        expected.add(b);
-
-        assertEquals(expected, sessions);
-    }
-
-    public void testTrimToSize() {
-        ClientSessionContext context = new ClientSessionContext(null, null);
-
-        FakeSession a = new FakeSession("a");
-        FakeSession b = new FakeSession("b");
-        FakeSession c = new FakeSession("c");
-        FakeSession d = new FakeSession("d");
-
-        context.putSession(a);
-        context.putSession(b);
-        context.putSession(c);
-        context.putSession(d);
-
-        context.setSessionCacheSize(2);
-
-        Set<SSLSession> sessions = new HashSet<SSLSession>();
-        Enumeration ids = context.getIds();
-        while (ids.hasMoreElements()) {
-            sessions.add(context.getSession((byte[]) ids.nextElement()));
-        }
-
-        Set<SSLSession> expected = new HashSet<SSLSession>();
-        expected.add(c);
-        expected.add(d);
-
-        assertEquals(expected, sessions);               
-    }
-
-}
diff --git a/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/FakeSession.java b/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/FakeSession.java
deleted file mode 100644
index 4a793dd..0000000
--- a/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/FakeSession.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-import java.security.cert.Certificate;
-import java.security.Principal;
-
-class FakeSession implements SSLSession {
-    final String host;
-
-    FakeSession(String host) {
-        this.host = host;
-    }
-
-    public int getApplicationBufferSize() {
-        throw new UnsupportedOperationException();
-    }
-
-    public String getCipherSuite() {
-        throw new UnsupportedOperationException();
-    }
-
-    public long getCreationTime() {
-        throw new UnsupportedOperationException();
-    }
-
-    public byte[] getId() {
-        return host.getBytes();
-    }
-
-    public long getLastAccessedTime() {
-        throw new UnsupportedOperationException();
-    }
-
-    public Certificate[] getLocalCertificates() {
-        throw new UnsupportedOperationException();
-    }
-
-    public Principal getLocalPrincipal() {
-        throw new UnsupportedOperationException();
-    }
-
-    public int getPacketBufferSize() {
-        throw new UnsupportedOperationException();
-    }
-
-    public javax.security.cert.X509Certificate[] getPeerCertificateChain() {
-        throw new UnsupportedOperationException();
-    }
-
-    public Certificate[] getPeerCertificates() {
-        throw new UnsupportedOperationException();
-    }
-
-    public String getPeerHost() {
-        return host;
-    }
-
-    public int getPeerPort() {
-        return 443;
-    }
-
-    public Principal getPeerPrincipal() {
-        throw new UnsupportedOperationException();
-    }
-
-    public String getProtocol() {
-        throw new UnsupportedOperationException();
-    }
-
-    public SSLSessionContext getSessionContext() {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object getValue(String name) {
-        throw new UnsupportedOperationException();
-    }
-
-    public String[] getValueNames() {
-        throw new UnsupportedOperationException();
-    }
-
-    public void invalidate() {
-        throw new UnsupportedOperationException();
-    }
-
-    public boolean isValid() {
-        throw new UnsupportedOperationException();
-    }
-
-    public void putValue(String name, Object value) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void removeValue(String name) {
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java b/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java
deleted file mode 100644
index ee50863..0000000
--- a/libcore/x-net/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.xnet.provider.jsse;
-
-import junit.framework.TestCase;
-
-import java.io.File;
-import java.io.IOException;
-
-public class FileClientSessionCacheTest extends TestCase {
-
-    public void testMaxSize() throws IOException, InterruptedException {
-        String tmpDir = System.getProperty("java.io.tmpdir");
-        if (tmpDir == null) {
-            fail("Please set 'java.io.tmpdir' system property.");
-        }
-        File cacheDir = new File(tmpDir
-                + "/" + FileClientSessionCacheTest.class.getName() + "/cache");
-        final SSLClientSessionCache cache
-                = FileClientSessionCache.usingDirectory(cacheDir);
-        Thread[] threads = new Thread[10];
-        final int iterations = FileClientSessionCache.MAX_SIZE * 10;
-        for (int i = 0; i < threads.length; i++) {
-            final int id = i;
-            threads[i] = new Thread() {
-                @Override
-                public void run() {
-                    for (int i = 0; i < iterations; i++) {
-                        cache.putSessionData(new FakeSession(id + "." + i),
-                                new byte[10]);
-                    }
-                }
-            };
-        }
-        for (int i = 0; i < threads.length; i++) {
-            threads[i].start();
-        }
-        for (int i = 0; i < threads.length; i++) {
-            threads[i].join();
-        }
-        assertEquals(FileClientSessionCache.MAX_SIZE, cacheDir.list().length);
-    }
-}
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 8f7cc41..3a725ed 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -379,23 +379,22 @@
 
     /* call, r0 gets catchRelPc (a code-unit offset) */
     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
-
-    /* fix earlier stack overflow if necessary; may trash rFP */
-    ldrb    r1, [r10, #offThread_stackOverflowed]
-    cmp     r1, #0                      @ did we overflow earlier?
-    beq     1f                          @ no, skip ahead
-    mov     rFP, r0                     @ save relPc result in rFP
-    mov     r0, r10                     @ r0<- self
-    bl      dvmCleanupStackOverflow     @ call(self)
-    mov     r0, rFP                     @ restore result
-1:
-
-    /* update frame pointer and check result from dvmFindCatchBlock */
     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
     cmp     r0, #0                      @ is catchRelPc < 0?
     add     sp, sp, #8                  @ restore stack
     bmi     .LnotCaughtLocally
 
+    /* fix stack overflow if necessary; must preserve r0 */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    beq     1f                          @ no, skip ahead
+    mov     r9, r0                      @ r9<- r0 (save it)
+    mov     r0, r10                     @ r0<- self
+    bl      dvmCleanupStackOverflow     @ call(self)
+    mov     r0, r9                      @ r0<- r9 (restore it)
+    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
+1:
+
     /* adjust locals to match self->curFrame and updated PC */
     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index f52e3f0..f97adf5 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -636,10 +636,6 @@
          * exception this won't happen until some other exception gets
          * thrown.  If the code keeps pushing the stack bounds we'll end
          * up aborting the VM.
-         *
-         * Note we want to do this *after* the call to dvmFindCatchBlock,
-         * because that may need extra stack space to resolve exception
-         * classes (e.g. through a class loader).
          */
         if (self->stackOverflowed)
             dvmCleanupStackOverflow(self);
diff --git a/vm/mterp/out/InterpAsm-armv4.S b/vm/mterp/out/InterpAsm-armv4.S
index 3de7aea..07acd91 100644
--- a/vm/mterp/out/InterpAsm-armv4.S
+++ b/vm/mterp/out/InterpAsm-armv4.S
@@ -9667,23 +9667,22 @@
 
     /* call, r0 gets catchRelPc (a code-unit offset) */
     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
-
-    /* fix earlier stack overflow if necessary; may trash rFP */
-    ldrb    r1, [r10, #offThread_stackOverflowed]
-    cmp     r1, #0                      @ did we overflow earlier?
-    beq     1f                          @ no, skip ahead
-    mov     rFP, r0                     @ save relPc result in rFP
-    mov     r0, r10                     @ r0<- self
-    bl      dvmCleanupStackOverflow     @ call(self)
-    mov     r0, rFP                     @ restore result
-1:
-
-    /* update frame pointer and check result from dvmFindCatchBlock */
     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
     cmp     r0, #0                      @ is catchRelPc < 0?
     add     sp, sp, #8                  @ restore stack
     bmi     .LnotCaughtLocally
 
+    /* fix stack overflow if necessary; must preserve r0 */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    beq     1f                          @ no, skip ahead
+    mov     r9, r0                      @ r9<- r0 (save it)
+    mov     r0, r10                     @ r0<- self
+    bl      dvmCleanupStackOverflow     @ call(self)
+    mov     r0, r9                      @ r0<- r9 (restore it)
+    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
+1:
+
     /* adjust locals to match self->curFrame and updated PC */
     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 9987ff5..765cdb2 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -9661,23 +9661,22 @@
 
     /* call, r0 gets catchRelPc (a code-unit offset) */
     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
-
-    /* fix earlier stack overflow if necessary; may trash rFP */
-    ldrb    r1, [r10, #offThread_stackOverflowed]
-    cmp     r1, #0                      @ did we overflow earlier?
-    beq     1f                          @ no, skip ahead
-    mov     rFP, r0                     @ save relPc result in rFP
-    mov     r0, r10                     @ r0<- self
-    bl      dvmCleanupStackOverflow     @ call(self)
-    mov     r0, rFP                     @ restore result
-1:
-
-    /* update frame pointer and check result from dvmFindCatchBlock */
     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
     cmp     r0, #0                      @ is catchRelPc < 0?
     add     sp, sp, #8                  @ restore stack
     bmi     .LnotCaughtLocally
 
+    /* fix stack overflow if necessary; must preserve r0 */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    beq     1f                          @ no, skip ahead
+    mov     r9, r0                      @ r9<- r0 (save it)
+    mov     r0, r10                     @ r0<- self
+    bl      dvmCleanupStackOverflow     @ call(self)
+    mov     r0, r9                      @ r0<- r9 (restore it)
+    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
+1:
+
     /* adjust locals to match self->curFrame and updated PC */
     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index a80e59e..749cdde 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -1,3 +1,4 @@
+
 /*
  * This file was generated automatically by gen-mterp.py for 'x86'.
  *
@@ -6556,7 +6557,7 @@
     sarl    $4,rINST_FULL
     .endif
     movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
-    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
+    call    dvmAllocArrayByClass                  # eax<- call(typeCh, length, flags)
     UNSPILL(rPC)
     GET_GLUE(%ecx)
     testl   %eax,%eax                             # alloc successful?
@@ -6661,7 +6662,7 @@
     sarl    $4,rINST_FULL
     .endif
     movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
-    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
+    call    dvmAllocArrayByClass                  # eax<- call(typeCh, length, flags)
     UNSPILL(rPC)
     GET_GLUE(%ecx)
     testl   %eax,%eax                             # alloc successful?
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 635a873..8d253e0 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -3661,10 +3661,6 @@
          * exception this won't happen until some other exception gets
          * thrown.  If the code keeps pushing the stack bounds we'll end
          * up aborting the VM.
-         *
-         * Note we want to do this *after* the call to dvmFindCatchBlock,
-         * because that may need extra stack space to resolve exception
-         * classes (e.g. through a class loader).
          */
         if (self->stackOverflowed)
             dvmCleanupStackOverflow(self);
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index d527cc0..503425d 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -3922,10 +3922,6 @@
          * exception this won't happen until some other exception gets
          * thrown.  If the code keeps pushing the stack bounds we'll end
          * up aborting the VM.
-         *
-         * Note we want to do this *after* the call to dvmFindCatchBlock,
-         * because that may need extra stack space to resolve exception
-         * classes (e.g. through a class loader).
          */
         if (self->stackOverflowed)
             dvmCleanupStackOverflow(self);
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index 64e5ccd..7292c0b 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -3642,10 +3642,6 @@
          * exception this won't happen until some other exception gets
          * thrown.  If the code keeps pushing the stack bounds we'll end
          * up aborting the VM.
-         *
-         * Note we want to do this *after* the call to dvmFindCatchBlock,
-         * because that may need extra stack space to resolve exception
-         * classes (e.g. through a class loader).
          */
         if (self->stackOverflowed)
             dvmCleanupStackOverflow(self);
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index cd5fe95..fa45730 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1811,10 +1811,6 @@
          * exception this won't happen until some other exception gets
          * thrown.  If the code keeps pushing the stack bounds we'll end
          * up aborting the VM.
-         *
-         * Note we want to do this *after* the call to dvmFindCatchBlock,
-         * because that may need extra stack space to resolve exception
-         * classes (e.g. through a class loader).
          */
         if (self->stackOverflowed)
             dvmCleanupStackOverflow(self);
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index c7ab763..151a9e3 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -177,10 +177,6 @@
 #if LOG_CLASS_LOADING
 /*
  * Logs information about a class loading with given timestamp.
- *
- * TODO: In the case where we fail in dvmLinkClass() and log the class as closing (type='<'),
- * it would probably be better to use a new type code to indicate the failure.  This change would
- * require a matching change in the parser and analysis code in frameworks/base/tools/preload.
  */
 static void logClassLoadWithTime(char type, ClassObject* clazz, u8 time) {
     pid_t ppid = getppid();
@@ -200,7 +196,7 @@
 }
 #endif
 
-/*
+/* 
  * Some LinearAlloc unit tests.
  */
 static void linearAllocTests()
@@ -1099,7 +1095,7 @@
  *
  * The class will be loaded and initialized if it has not already been.
  * If necessary, the superclass will be loaded.
- *
+ * 
  * If the class can't be found, returns NULL with an appropriate exception
  * raised.
  */
@@ -1395,7 +1391,7 @@
             goto bail;
         }
 
-        /*
+        /* 
          * Lock the class while we link it so other threads must wait for us
          * to finish.  Set the "initThreadId" so we can identify recursive
          * invocation.
@@ -1455,17 +1451,6 @@
             dvmObjectNotifyAll(self, (Object*) clazz);
             dvmUnlockObject(self, (Object*) clazz);
 
-#if LOG_CLASS_LOADING
-            LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
-                clazz->descriptor, get_process_name());
-
-            /*
-             * TODO: It would probably be better to use a new type code here (instead of '<') to
-             * indicate the failure.  This change would require a matching change in the parser
-             * and analysis code in frameworks/base/tools/preload.
-             */
-            logClassLoad('<', clazz);
-#endif
             clazz = NULL;
             if (gDvm.optimizing) {
                 /* happens with "external" libs */
@@ -1473,6 +1458,9 @@
             } else {
                 LOGW("Link of class '%s' failed\n", descriptor);
             }
+#if LOG_CLASS_LOADING
+            logClassLoad('<', clazz);
+#endif
             goto bail;
         }
         dvmObjectNotifyAll(self, (Object*) clazz);
@@ -2004,11 +1992,11 @@
 /*
  * jniArgInfo (32-bit int) layout:
  *   SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
- *
+ *   
  *   S - if set, do things the hard way (scan the signature)
  *   R - return-type enumeration
  *   H - target-specific hints
- *
+ *   
  * This info is used at invocation time by dvmPlatformInvoke.  In most
  * cases, the target-specific hints allow dvmPlatformInvoke to avoid
  * having to fully parse the signature.
@@ -3634,7 +3622,7 @@
         bool needRelease = false;
 
         if (! parsed) {
-            /*
+            /* 
              * TODO: Eventually verification should attempt to ensure
              * that this can't happen at least due to a data integrity
              * problem.
@@ -4501,7 +4489,7 @@
  */
 int dvmGetNumLoadedClasses()
 {
-    int count;
+    int count; 
     dvmHashTableLock(gDvm.loadedClasses);
     count = dvmHashTableNumEntries(gDvm.loadedClasses);
     dvmHashTableUnlock(gDvm.loadedClasses);