diff --git a/AstBuilding.py b/AstBuilding.py
index 0bc19f5c5f92c7fb452993c33a796cbcc07d190b..2f5f110b08e98a90e10ec3652da3f7965e97b8df 100644
--- a/AstBuilding.py
+++ b/AstBuilding.py
@@ -39,7 +39,6 @@ def buildEnvAndLink(ASTs):
     # hierarchy checking
     # print('--------->>> hierarchy checking time!')
     for t in ASTs:
-        # t[1].buildEnvFromImports(globalEnv)
         t[1].recurseAction("checkHierarchy")
 
 #######################################################
diff --git a/CompNode.py b/CompNode.py
index 61f5a3a4f4ab84948b7024b7a4236872f96754a8..738e7439079e3782da1d67a9c4d470830caf7806 100644
--- a/CompNode.py
+++ b/CompNode.py
@@ -8,7 +8,7 @@ class CompNode(ASTNode):
     def __init__(self, parseTree):
         self.parseTree = parseTree
         self.packageName = ''
-        self.importNames = ['java.lang.*'] # all compUnit automatically imports java.lang.*
+        self.importNames = []
         self.env = None
         self.typeDcl = None
         self.children = []
diff --git a/Environment.py b/Environment.py
index e8457c0f64905766ef5f48345adec3aff7a13e06..3d63f1411361298b52f1d0594e2521bd6bf38f4c 100644
--- a/Environment.py
+++ b/Environment.py
@@ -96,7 +96,11 @@ class GlobalEnv(Env):
 
     # Use getNode() from base class to get node using Canonical Name (full name)
     def getNode(self, key, imported, packageName):
+        # TODO: error if ambiguous
+        # TODO: not sure whether name is canonical or not????
+        #  i.e. there are more than one of this type. Currently it only gets the first occurence
         name = key[0]
+        
         # 1. enclosing class/interface
         #    - already did
         # 2. single-type import
@@ -114,6 +118,12 @@ class GlobalEnv(Env):
                 full = i.replace("*", name)
                 if full in self.map:
                     return self.map.get(full)
+        # imported implicitly: java.io.*, java.lang.*, java.util.*
+        implicitly = ['java.lang.', 'java.io.', 'java.util.']
+        for i in implicitly:
+            if i in name and name in self.map:
+                return self.map.get(name)
+
         raise Exception("ERROR: Can't find definition of {} in the Environment".format(key))
 
     # method for getting all the nodes under a package (import All)
diff --git a/MemberNodes.py b/MemberNodes.py
index 759f7216c3969debdb76d204ba6357ff57020530..591263bc6f220e2389079b86ee8e37e76220b72d 100644
--- a/MemberNodes.py
+++ b/MemberNodes.py
@@ -16,6 +16,10 @@ class FieldNode(ASTNode):
         self.env = None
         self.children = []
 
+        # get field name
+        nameNodes = getParseTreeNodes(['ID'], parseTree, ['params', 'type', 'methodBody'])
+        for n in nameNodes:
+            self.name = n.lex
 
         for node in parseTree.children:
             if node.name == 'methodMod':
diff --git a/Test.py b/Test.py
index 3deddfd6fb0a702091dedfdc923c0050e48de50a..3936a419a93341097957bbf8de46065a1afe7151 100644
--- a/Test.py
+++ b/Test.py
@@ -44,6 +44,8 @@ def a2Multiple():
         print("DIRECTORY")
         print(c)
         print("**********************************************************")
+        # get all files from stdlib folder
+        # testFiles = [join(dp, f) for dp, dn, filenames in walk('stdlib/2.0/java/') for f in filenames]
         # get all files in the folder recursively
         testFiles = [join(dp, f) for dp, dn, filenames in walk(c) for f in filenames]
         run(testFiles)
diff --git a/TypeNodes.py b/TypeNodes.py
index fb22369e534fb6c4aec8f27a952fce629faf1985..a75a773616a2bbb2ba6a30785f6913c0404cc63e 100644
--- a/TypeNodes.py
+++ b/TypeNodes.py
@@ -73,52 +73,64 @@ class ClassNode(ASTNode):
                     self.superInter[index] = newSuperInter
 
     def checkHierarchy(self):
+        # 1. A class must not extend an interface.
+        # 4. A class must not extend a final class.
         if self.superClass:
-            # A class must not extend an interface.
             if not isinstance(self.superClass, ClassNode):
-                raise Exception("ERROR: Class {} extends interface {}".format(self.name, self.superClass.name))
-            # A class must not extend a final class.
+                raise Exception("ERROR: Class '{}' extends non-class '{}'".format(self.name, self.superClass.name))
             if 'final' in self.superClass.mods:
-                raise Exception("ERROR: Class {} extends final class {}".format(self.name, self.superClass.name))
-        # A class must not implement a class. No duplicate interfaces.
+                raise Exception("ERROR: Class '{}' extends final class '{}'".format(self.name, self.superClass.name))
+
+        # 2. A class must not implement a class
+        # 3. An interface must not be repeated in an implements clause
         if self.superInter:
             unique = []
             for inter in self.superInter:
                 if not isinstance(inter, InterNode):
-                    raise Exception("ERROR: Class {} implements class {}".format(self.name, inter.name))
+                    raise Exception("ERROR: Class '{}' implements non-interface '{}'".format(self.name, inter.name))
                 if inter.name in unique:
-                    raise Exception("ERROR: Class {} implements duplicate interfaces {}".format(self.name, inter.name))
+                    raise Exception("ERROR: Class '{}' implements duplicate interfaces '{}'".format(self.name, inter.name))
                 unique.append(inter.name)
         
-        # A class or interface must not declare two methods with the same signature (name and parameter types).
+        # 7. A class or interface must not declare two methods with the same signature (name and parameter types).
         unique = []
         for method in self.methods:
+            # print(method.name)
             key = (method.name, method.paramTypes)
             if key in unique:
-                raise Exception("ERROR: Class {} declares 2 methods with the same signature {}".format(self.name, key[0]))
+                # print(self.methods)
+                # print(key)
+                # print(unique)
+                raise Exception("ERROR: Class '{}' declares 2 methods with the same signature '{}'".format(self.name, key[0]))
             unique.append(key)
 
-        # A class must not declare two constructors with the same parameter types
+        # 8. A class must not declare two constructors with the same parameter types
         unique = []
         for cons in self.constructors:
             key = (cons.name, cons.paramTypes)
             if key in unique:
-                raise Exception("ERROR: Class {} declares 2 constructors with the same parameter types".format(self.name))
+                raise Exception("ERROR: Class '{}' declares 2 constructors with the same parameter types".format(self.name))
             unique.append(key)
         
-        # A class or interface must not contain (declare or inherit) two methods with the same signature but different return types
-        # The hierarchy must be acyclic
+        # 6. The hierarchy must be acyclic
+        # 9. A class or interface must not contain (declare or inherit) two methods with the same signature but different return types
+        # 11. A nonstatic method must not replace a static method
+        # 13. A protected method must not replace a public method
+        # 14. A method must not replace a final method
         contains = self.getContains([])
-        # A class that contains (declares or inherits) any abstract methods must be abstract.
+        # 10. A class that contains (declares or inherits) any abstract methods must be abstract.
         for con in contains:
             if 'abstract' in con.mods and 'abstract' not in self.mods:
-                raise Exception("ERROR: Non-abstract Class {} contains an abstract method".format(self.name))
+                raise Exception("ERROR: Non-abstract Class '{}' contains an abstract method".format(self.name))
 
     # hierarchy: string[]
     def getContains(self, hierarchy):
+        # TODO: move this to a more centralized spot for both ClassNode and InterNode?
+        # TODO: need to check all of the implemented interfaces as well ***
+        
         # check if not acyclic
         if self.name in hierarchy:
-            raise Exception("ERROR: The hierarchy is not acyclic {}".format(hierarchy))
+            raise Exception("ERROR: The hierarchy is not acyclic '{}'".format(hierarchy))
         hierarchy.append(self.name)
         # get contains
         contains = self.methods
@@ -128,8 +140,18 @@ class ClassNode(ASTNode):
                 conOverwritten = False
                 for method in self.methods:
                     if (method == con):
+                        # cannot have same signiture but different return types
                         if (method.methodType != con.methodType):
-                            raise Exception("ERROR: Class {} contains 2 methods {} with the same signature but different return types".format(self.name, method.name))
+                            raise Exception("ERROR: Class '{}' contains 2 methods '{}' with the same signature but different return types".format(self.name, method.name))
+                        # must not replace final
+                        if 'final' in con.mods:
+                            raise Exception("ERROR: Method '{}' in class '{}' replaces final method '{}' in class '{}'".format(method.name, self.name, con.name, self.superClass.name))
+                        # nonstatic must not replace static
+                        if 'static' not in method.mods and 'static' in con.mods:
+                            raise Exception("ERROR: Non-static method '{}' in class '{}' replaces static method '{}' in class '{}'".format(method.name, self.name, con.name, self.superClass.name))
+                        # protected must not replace public
+                        if 'protected' in method.mods and 'public' in con.mods:
+                            raise Exception("ERROR: Protected method '{}' in class '{}' replaces public method '{}' in class {}".format(method.name, self.name, con.name, self.superClass.name))
                         conOverwritten = True
                         break
                 if not conOverwritten:
@@ -149,7 +171,7 @@ class InterNode(ASTNode):
         self.parseTree = parseTree
         self.name = ''
         self.methods = []
-        self.superInter = [] # list of strings of superInterface's name, then stores a pointer to the node after type linking
+        self.superInter = [] # list of strings of extendInterface's name, then stores a pointer to the node after type linking
         self.env = None
         self.children = []
 
@@ -157,7 +179,7 @@ class InterNode(ASTNode):
             if node.name == 'ID':
                 self.name = node.lex
 
-            elif node.name == 'superInterface':
+            elif node.name == 'extendInterface':
                 nameNodes = getParseTreeNodes(['ID', 'COMPID'], node)
                 for n in nameNodes:
                     self.superInter.append(n.lex)
@@ -185,4 +207,52 @@ class InterNode(ASTNode):
                     self.superInter[index] = newSuperInter
 
     def checkHierarchy(self):
-        pass
+        # 5. An interface must not extend a class.
+        # 3. An interface must not be repeated in an extends clause of an interface
+        if self.superInter:
+            unique = []
+            for inter in self.superInter:
+                if not isinstance(inter, InterNode):
+                    raise Exception("ERROR: Interface '{}' extends non-interface '{}'".format(self.name, inter.name))
+                if inter.name in unique:
+                    raise Exception("ERROR: Interface '{}' extends duplicate interfaces '{}'".format(self.name, inter.name))
+                unique.append(inter.name)
+
+        # 7. A class or interface must not declare two methods with the same signature (name and parameter types).
+        unique = []
+        for method in self.methods:
+            key = (method.name, method.paramTypes)
+            if key in unique:
+                raise Exception("ERROR: Interface '{}' declares 2 methods with the same signature '{}'".format(self.name, key[0]))
+            unique.append(key)
+
+        # 6. The hierarchy must be acyclic
+        # 9. A class or interface must not contain (declare or inherit) two methods with the same signature but different return types
+        # 13. A protected method must not replace a public method
+        contains = self.getContains([])
+
+    # hierarchy: string[]
+    def getContains(self, hierarchy):
+        # check if not acyclic
+        if self.name in hierarchy:
+            raise Exception("ERROR: The hierarchy is not acyclic '{}'".format(hierarchy))
+        hierarchy.append(self.name)
+        # get contains
+        contains = self.methods
+        for inter in self.superInter:
+            superContains = inter.getContains(hierarchy)
+            for con in superContains:
+                conOverwritten = False
+                for method in self.methods:
+                    if (method == con):
+                        # cannot have same signiture but different return types
+                        if (method.methodType != con.methodType):
+                            raise Exception("ERROR: Interface '{}' contains 2 methods '{}' with the same signature but different return types".format(self.name, method.name))
+                        # protected must not replace public
+                        if 'protected' in method.mods and 'public' in con.mods:
+                            raise Exception("ERROR: Protected method '{}' in class '{}' replaces public method '{}' in class {}".format(method.name, self.name, con.name, inter.name))
+                        conOverwritten = True
+                        break
+                if not conOverwritten:
+                    contains.append(con)
+        return contains
\ No newline at end of file
diff --git a/stdlib/2.0/java/io/OutputStream.java b/stdlib/2.0/java/io/OutputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..9de76e9713e940d701c53a1ed2766547b0aef09b
--- /dev/null
+++ b/stdlib/2.0/java/io/OutputStream.java
@@ -0,0 +1,14 @@
+package java.io;
+public class OutputStream {
+    public OutputStream() {
+    }
+    public void write(char c) {
+        write((int)c);
+    }
+    public void write(int b) {
+        PrintStream.nativeWrite(b);
+    }
+    protected static native int nativeWrite(int b);
+    public void flush() {
+    }
+}
diff --git a/stdlib/2.0/java/io/PrintStream.java b/stdlib/2.0/java/io/PrintStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..08ea27135dfbdf9e5830e5cc268cdc18e9e7c345
--- /dev/null
+++ b/stdlib/2.0/java/io/PrintStream.java
@@ -0,0 +1,53 @@
+package java.io;
+public class PrintStream extends OutputStream {
+    public PrintStream() {
+    }
+    public void print(String s) {
+        for(int i = 0; i < s.length(); i = i + 1) {
+            write(s.charAt(i));
+        }
+    }
+    public void println() {
+        println("");
+    }
+    public void println(String s) {
+        print(s);
+        write('\n');
+    }
+    public void println(Object b) {
+        println(String.valueOf(b));
+    }
+    public void println(boolean b) {
+        println(String.valueOf(b));
+    }
+    public void println(byte b) {
+        println(String.valueOf(b));
+    }
+    public void println(char b) {
+        println(String.valueOf(b));
+    }
+    public void println(short b) {
+        println(String.valueOf(b));
+    }
+    public void println(int b) {
+        println(String.valueOf(b));
+    }
+    public void print(Object b) {
+        print(String.valueOf(b));
+    }
+    public void print(boolean b) {
+        print(String.valueOf(b));
+    }
+    public void print(byte b) {
+        print(String.valueOf(b));
+    }
+    public void print(char b) {
+        print(String.valueOf(b));
+    }
+    public void print(short b) {
+        print(String.valueOf(b));
+    }
+    public void print(int b) {
+        print(String.valueOf(b));
+    }
+}
diff --git a/stdlib/2.0/java/io/Serializable.java b/stdlib/2.0/java/io/Serializable.java
new file mode 100644
index 0000000000000000000000000000000000000000..071b7d5149b4bdc54a778bc0f3ef196abea023c7
--- /dev/null
+++ b/stdlib/2.0/java/io/Serializable.java
@@ -0,0 +1,3 @@
+package java.io;
+public interface Serializable {
+}
diff --git a/stdlib/2.0/java/lang/Boolean.java b/stdlib/2.0/java/lang/Boolean.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdeb75e96ac5fd352e3d49b3c61b02ac7b3462a5
--- /dev/null
+++ b/stdlib/2.0/java/lang/Boolean.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Boolean {
+    public boolean value;
+    public Boolean(boolean i) {
+        value = i;
+    }
+    public Boolean() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/2.0/java/lang/Byte.java b/stdlib/2.0/java/lang/Byte.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea6388fbb3a704a2bb0b98831a4b1a6b221a4b35
--- /dev/null
+++ b/stdlib/2.0/java/lang/Byte.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Byte {
+    public byte value;
+    public Byte(byte i) {
+        value = i;
+    }
+    public Byte() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/2.0/java/lang/Character.java b/stdlib/2.0/java/lang/Character.java
new file mode 100644
index 0000000000000000000000000000000000000000..726c2ecaf190da36ab9b858adf5fa2e1b220fab0
--- /dev/null
+++ b/stdlib/2.0/java/lang/Character.java
@@ -0,0 +1,12 @@
+package java.lang;
+public final class Character {
+    public char value;
+    public Character(char i) {
+        value = i;
+    }
+    public Character() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/2.0/java/lang/Class.java b/stdlib/2.0/java/lang/Class.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccc97605214ef9fca9b3d8db1f0e7f9007601900
--- /dev/null
+++ b/stdlib/2.0/java/lang/Class.java
@@ -0,0 +1,5 @@
+package java.lang;
+public class Class {
+    public Class() {
+    }
+}
diff --git a/stdlib/2.0/java/lang/Cloneable.java b/stdlib/2.0/java/lang/Cloneable.java
new file mode 100644
index 0000000000000000000000000000000000000000..d14aed45f7f828a3bb46dc59599c4e3c5adef073
--- /dev/null
+++ b/stdlib/2.0/java/lang/Cloneable.java
@@ -0,0 +1,4 @@
+package java.lang;
+
+public interface Cloneable {
+}
diff --git a/stdlib/2.0/java/lang/Integer.java b/stdlib/2.0/java/lang/Integer.java
new file mode 100644
index 0000000000000000000000000000000000000000..14106cafe7841ba4e9e4a1fe2db5b603a038e51e
--- /dev/null
+++ b/stdlib/2.0/java/lang/Integer.java
@@ -0,0 +1,35 @@
+package java.lang;
+public final class Integer extends Number {
+    public int value;
+    public Integer(int i) {
+        value = i;
+    }
+    public int intValue() {
+        return value;
+    }
+    public static int parseInt(String s) {
+        int ret = 0;
+        boolean neg = false;
+        int i = 0;
+        while(i < s.length() && 
+          (s.charAt(i) == '-' || (s.charAt(i) >= '0' && s.charAt(i) <= '9'))) {
+            if(s.charAt(i) == '-') neg = !neg;
+            else {
+                ret = ret * 10 + s.charAt(i)-'0';
+            }
+            i = i+1;
+        }
+        if(neg) ret = -ret;
+        return ret;
+    }
+    public Integer(String s) {
+        value = Integer.parseInt(s);
+    }
+    public Integer() {
+        value = 0;
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static int MAX_VALUE = 2147483647;
+}
diff --git a/stdlib/2.0/java/lang/Number.java b/stdlib/2.0/java/lang/Number.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf9685eafe1d7858a76e6b9c5bb976dfa9b224c3
--- /dev/null
+++ b/stdlib/2.0/java/lang/Number.java
@@ -0,0 +1,6 @@
+package java.lang;
+public abstract class Number {
+    public abstract int intValue();
+    public Number() {
+    }
+}
diff --git a/stdlib/2.0/java/lang/Object.java b/stdlib/2.0/java/lang/Object.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6cd3a264b5684f834b098760f4bee8bd345a8a9
--- /dev/null
+++ b/stdlib/2.0/java/lang/Object.java
@@ -0,0 +1,20 @@
+package java.lang;
+public class Object {
+    public Object() {
+    }
+    public boolean equals(Object other) {
+        return this == other;
+    }
+    public String toString() {
+        return "Some random object";
+    }
+    public int hashCode() {
+        return 42;
+    }
+    protected Object clone() {
+        return this;
+    }
+    public final Class getClass() {
+        return null;
+    }
+}
diff --git a/stdlib/2.0/java/lang/Short.java b/stdlib/2.0/java/lang/Short.java
new file mode 100644
index 0000000000000000000000000000000000000000..61a97a210a21985fe22f8983c87142d8291c75cf
--- /dev/null
+++ b/stdlib/2.0/java/lang/Short.java
@@ -0,0 +1,15 @@
+package java.lang;
+public final class Short extends Number {
+    public short value;
+    public Short(short i) {
+        value = i;
+    }
+    public int intValue() {
+        return (int) value;
+    }
+    public Short() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/2.0/java/lang/String.java b/stdlib/2.0/java/lang/String.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cfe123d36835aa28ab3cd31efd38f584c2b480e
--- /dev/null
+++ b/stdlib/2.0/java/lang/String.java
@@ -0,0 +1,147 @@
+package java.lang;
+import java.util.Arrays;
+
+public class String {
+    public char[] chars;
+    public int length() {
+        return chars.length;
+    }
+    public char charAt(int i) {
+        return chars[i];
+    }
+    public String() {
+        chars = new char[0];
+    }
+    public String(char[] chars) {
+        this.chars = new char[chars.length];
+        for(int i = 0; i < chars.length; i = i + 1) this.chars[i] = chars[i];
+    }
+    public String(String other) {
+        this.chars = other.chars;
+    }
+    public String concat(String s2) {
+        int i = 0;
+        char[] newchars = new char[length() + s2.length()];
+        for(i = 0; i < length(); i = i + 1)
+            newchars[i] = chars[i];
+        for(i = 0; i < s2.length(); i = i + 1)
+            newchars[i+length()] = s2.chars[i];
+        return new String(newchars);
+    }
+    public static String valueOf(char c) {
+        char[] newchars = new char[1];
+        newchars[0] = c;
+        return new String(newchars);
+    }
+    public static String valueOf(int i) {
+        char[] ret = new char[15];
+        int j = 0;
+        boolean wasneg = false;
+        if(i == -2147483648) return "-2147483648";
+        if(i<0) {
+            wasneg = true;
+            i = -i;
+        }
+        if(i == 0) {
+            ret[j] = '0';
+            j = j + 1;
+        } else {
+            while(i > 0) {
+                int d = i % 10;
+                i = i / 10;
+                ret[j] = (char) (d + '0');
+                j = j + 1;
+            }
+        }
+        if(wasneg) {
+            ret[j] = '-';
+            j = j + 1;
+        }
+        char[] ret2 = new char[j];
+        for(i = 0; i < j; i = i + 1) ret2[i] = ret[j-1-i];
+        return new String(ret2);
+    }
+    public static String valueOf(short i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(byte i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(boolean b) {
+        if(b) return "true"; else return "false";
+    }
+    public static String valueOf(Object o) {
+        if(o == null)  return "null"; else return o.toString();
+    }
+    public static String valueOf(String o) {
+        if(o == null)  return "null"; else return o;
+    }
+    public boolean equals(Object o) {
+        if(o == null) return false;
+        if(!(o instanceof String)) return false;
+        return Arrays.equals(chars, ((String)o).chars);
+    }
+    public String substring(int i, int j) {
+        int k = 0;
+        if(i<0) return "";
+        if(j>length()) return "";
+        if(j<i) return "";
+        char[] ret = new char[j-i];
+        for(k=i;k<j;k=k+1) ret[k-i] = charAt(k);
+        return new String(ret);
+    }
+    public String trim() {
+        int i = 0;
+        int j = 0;
+        for(i=0;i<length() && charAt(i)<=' ';i=i+1) {}
+        for(j=length()-1;j>=0 && charAt(j)<=' ';j=j-1) {}
+        if(i>j) return ""; else return substring(i,j+1);
+    }
+    public int hashCode() {
+        int h = 0;
+        for (int i = 0; i < chars.length; i = i+1) {
+            h = 31*h + chars[i];
+        }
+
+        return h;
+    }
+    public String toString() {
+        return this;
+    }
+    public int compareTo(Object other) {
+        return compareTo((String) other);
+    }
+    public int compareTo(String other) {
+        int i = 0;
+        boolean b = true;
+        while(b) {
+            if(i >= chars.length && i >= other.chars.length) return 0;
+            if(i >= chars.length) return -1;
+            if(i >= other.chars.length) return 1;
+            if(chars[i] < other.chars[i])  return -1;
+            if(chars[i] > other.chars[i])  return 1;
+            i = i + 1;
+        }
+        return 0;
+    }
+    public char[] toCharArray() {
+        char[] ret = new char[chars.length];
+        for(int i = 0; i < ret.length; i = i+1) {
+            ret[i] = chars[i];
+        }
+        return ret;
+    }
+    public int indexOf(String needle) {
+        int offset = 0;
+        int i = 0;
+        for(offset = 0; offset < length(); offset = offset + 1) {
+            boolean found = true;
+            for(i = 0; i < needle.length(); i = i + 1) {
+                if(i+offset >= length()) found = false;
+                else if(chars[i+offset] != needle.chars[i]) found = false;
+            }
+            if(found) return offset;
+        }
+        return -1;
+    }
+}
diff --git a/stdlib/2.0/java/lang/System.java b/stdlib/2.0/java/lang/System.java
new file mode 100644
index 0000000000000000000000000000000000000000..a321db885510df85c643e36eaa20c57799e1de2c
--- /dev/null
+++ b/stdlib/2.0/java/lang/System.java
@@ -0,0 +1,10 @@
+package java.lang;
+import java.io.PrintStream;
+
+public class System {
+    public static PrintStream out = new PrintStream();
+    public static void gc() {
+    }
+    public System() {
+    }
+}
diff --git a/stdlib/2.0/java/util/Arrays.java b/stdlib/2.0/java/util/Arrays.java
new file mode 100644
index 0000000000000000000000000000000000000000..e19406172869e03c67a7dfe18d244da782fffd1c
--- /dev/null
+++ b/stdlib/2.0/java/util/Arrays.java
@@ -0,0 +1,20 @@
+package java.util;
+
+public class Arrays {
+    public Arrays() {
+    }
+    public static boolean equals(boolean[] a1, boolean[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+    public static boolean equals(char[] a1, char[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+}
diff --git a/stdlib/2.0/runtime.o b/stdlib/2.0/runtime.o
new file mode 100644
index 0000000000000000000000000000000000000000..4767c7ba28f6a79c8f44b8013061d5877678f457
Binary files /dev/null and b/stdlib/2.0/runtime.o differ
diff --git a/stdlib/2.0/runtime.s b/stdlib/2.0/runtime.s
new file mode 100644
index 0000000000000000000000000000000000000000..7449aa1b0465f6295d2cb16ba36d346ed6ecf40e
--- /dev/null
+++ b/stdlib/2.0/runtime.s
@@ -0,0 +1,56 @@
+section .text
+
+; Allocates eax bytes of memory. Pointer to allocated memory returned in eax.
+    global __malloc
+__malloc:
+    push eax
+    mov eax, 45  ; sys_brk system call
+    mov ebx, 0   ; 0 bytes - query current brk
+    int 0x80
+    pop ebx
+    push eax
+    add ebx, eax ; move brk ahead by number of bytes requested
+    mov eax, 45  ; sys_brk system call
+    int 0x80
+    pop ebx
+    cmp eax, 0   ; on error, exit with code 22
+    jne ok
+    mov eax, 22
+    call __debexit
+ok:
+    mov eax, ebx
+    ret
+
+; Debugging exit: ends the process, returning the value of
+; eax as the exit code.
+    global __debexit
+__debexit:
+    mov ebx, eax
+    mov eax, 1   ; sys_exit system call
+    int 0x80
+
+; Exceptional exit: ends the process with exit code 13.
+; Call this in cases where the Joos code would throw an exception.
+    global __exception
+__exception:
+    mov eax, 1   ; sys_exit system call
+    mov ebx, 13
+    int 0x80
+
+; Implementation of java.io.OutputStream.nativeWrite method.
+; Outputs the low-order byte of eax to standard output.
+    global NATIVEjava.io.OutputStream.nativeWrite
+NATIVEjava.io.OutputStream.nativeWrite:
+    mov [char], al ; save the low order byte in memory
+    mov eax, 4     ; sys_write system call
+    mov ecx, char  ; address of bytes to write
+    mov ebx, 1     ; stdout
+    mov edx, 1     ; number of bytes to write
+    int 0x80
+    mov eax, 0     ; return 0
+    ret
+
+section .data
+
+char:
+    dd 0
diff --git a/stdlib/3.0/java/io/OutputStream.java b/stdlib/3.0/java/io/OutputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..9de76e9713e940d701c53a1ed2766547b0aef09b
--- /dev/null
+++ b/stdlib/3.0/java/io/OutputStream.java
@@ -0,0 +1,14 @@
+package java.io;
+public class OutputStream {
+    public OutputStream() {
+    }
+    public void write(char c) {
+        write((int)c);
+    }
+    public void write(int b) {
+        PrintStream.nativeWrite(b);
+    }
+    protected static native int nativeWrite(int b);
+    public void flush() {
+    }
+}
diff --git a/stdlib/3.0/java/io/PrintStream.java b/stdlib/3.0/java/io/PrintStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..08ea27135dfbdf9e5830e5cc268cdc18e9e7c345
--- /dev/null
+++ b/stdlib/3.0/java/io/PrintStream.java
@@ -0,0 +1,53 @@
+package java.io;
+public class PrintStream extends OutputStream {
+    public PrintStream() {
+    }
+    public void print(String s) {
+        for(int i = 0; i < s.length(); i = i + 1) {
+            write(s.charAt(i));
+        }
+    }
+    public void println() {
+        println("");
+    }
+    public void println(String s) {
+        print(s);
+        write('\n');
+    }
+    public void println(Object b) {
+        println(String.valueOf(b));
+    }
+    public void println(boolean b) {
+        println(String.valueOf(b));
+    }
+    public void println(byte b) {
+        println(String.valueOf(b));
+    }
+    public void println(char b) {
+        println(String.valueOf(b));
+    }
+    public void println(short b) {
+        println(String.valueOf(b));
+    }
+    public void println(int b) {
+        println(String.valueOf(b));
+    }
+    public void print(Object b) {
+        print(String.valueOf(b));
+    }
+    public void print(boolean b) {
+        print(String.valueOf(b));
+    }
+    public void print(byte b) {
+        print(String.valueOf(b));
+    }
+    public void print(char b) {
+        print(String.valueOf(b));
+    }
+    public void print(short b) {
+        print(String.valueOf(b));
+    }
+    public void print(int b) {
+        print(String.valueOf(b));
+    }
+}
diff --git a/stdlib/3.0/java/io/Serializable.java b/stdlib/3.0/java/io/Serializable.java
new file mode 100644
index 0000000000000000000000000000000000000000..071b7d5149b4bdc54a778bc0f3ef196abea023c7
--- /dev/null
+++ b/stdlib/3.0/java/io/Serializable.java
@@ -0,0 +1,3 @@
+package java.io;
+public interface Serializable {
+}
diff --git a/stdlib/3.0/java/lang/Boolean.java b/stdlib/3.0/java/lang/Boolean.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdeb75e96ac5fd352e3d49b3c61b02ac7b3462a5
--- /dev/null
+++ b/stdlib/3.0/java/lang/Boolean.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Boolean {
+    public boolean value;
+    public Boolean(boolean i) {
+        value = i;
+    }
+    public Boolean() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/3.0/java/lang/Byte.java b/stdlib/3.0/java/lang/Byte.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea6388fbb3a704a2bb0b98831a4b1a6b221a4b35
--- /dev/null
+++ b/stdlib/3.0/java/lang/Byte.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Byte {
+    public byte value;
+    public Byte(byte i) {
+        value = i;
+    }
+    public Byte() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/3.0/java/lang/Character.java b/stdlib/3.0/java/lang/Character.java
new file mode 100644
index 0000000000000000000000000000000000000000..726c2ecaf190da36ab9b858adf5fa2e1b220fab0
--- /dev/null
+++ b/stdlib/3.0/java/lang/Character.java
@@ -0,0 +1,12 @@
+package java.lang;
+public final class Character {
+    public char value;
+    public Character(char i) {
+        value = i;
+    }
+    public Character() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/3.0/java/lang/Class.java b/stdlib/3.0/java/lang/Class.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccc97605214ef9fca9b3d8db1f0e7f9007601900
--- /dev/null
+++ b/stdlib/3.0/java/lang/Class.java
@@ -0,0 +1,5 @@
+package java.lang;
+public class Class {
+    public Class() {
+    }
+}
diff --git a/stdlib/3.0/java/lang/Cloneable.java b/stdlib/3.0/java/lang/Cloneable.java
new file mode 100644
index 0000000000000000000000000000000000000000..d14aed45f7f828a3bb46dc59599c4e3c5adef073
--- /dev/null
+++ b/stdlib/3.0/java/lang/Cloneable.java
@@ -0,0 +1,4 @@
+package java.lang;
+
+public interface Cloneable {
+}
diff --git a/stdlib/3.0/java/lang/Integer.java b/stdlib/3.0/java/lang/Integer.java
new file mode 100644
index 0000000000000000000000000000000000000000..14106cafe7841ba4e9e4a1fe2db5b603a038e51e
--- /dev/null
+++ b/stdlib/3.0/java/lang/Integer.java
@@ -0,0 +1,35 @@
+package java.lang;
+public final class Integer extends Number {
+    public int value;
+    public Integer(int i) {
+        value = i;
+    }
+    public int intValue() {
+        return value;
+    }
+    public static int parseInt(String s) {
+        int ret = 0;
+        boolean neg = false;
+        int i = 0;
+        while(i < s.length() && 
+          (s.charAt(i) == '-' || (s.charAt(i) >= '0' && s.charAt(i) <= '9'))) {
+            if(s.charAt(i) == '-') neg = !neg;
+            else {
+                ret = ret * 10 + s.charAt(i)-'0';
+            }
+            i = i+1;
+        }
+        if(neg) ret = -ret;
+        return ret;
+    }
+    public Integer(String s) {
+        value = Integer.parseInt(s);
+    }
+    public Integer() {
+        value = 0;
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static int MAX_VALUE = 2147483647;
+}
diff --git a/stdlib/3.0/java/lang/Number.java b/stdlib/3.0/java/lang/Number.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf9685eafe1d7858a76e6b9c5bb976dfa9b224c3
--- /dev/null
+++ b/stdlib/3.0/java/lang/Number.java
@@ -0,0 +1,6 @@
+package java.lang;
+public abstract class Number {
+    public abstract int intValue();
+    public Number() {
+    }
+}
diff --git a/stdlib/3.0/java/lang/Object.java b/stdlib/3.0/java/lang/Object.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6cd3a264b5684f834b098760f4bee8bd345a8a9
--- /dev/null
+++ b/stdlib/3.0/java/lang/Object.java
@@ -0,0 +1,20 @@
+package java.lang;
+public class Object {
+    public Object() {
+    }
+    public boolean equals(Object other) {
+        return this == other;
+    }
+    public String toString() {
+        return "Some random object";
+    }
+    public int hashCode() {
+        return 42;
+    }
+    protected Object clone() {
+        return this;
+    }
+    public final Class getClass() {
+        return null;
+    }
+}
diff --git a/stdlib/3.0/java/lang/Short.java b/stdlib/3.0/java/lang/Short.java
new file mode 100644
index 0000000000000000000000000000000000000000..61a97a210a21985fe22f8983c87142d8291c75cf
--- /dev/null
+++ b/stdlib/3.0/java/lang/Short.java
@@ -0,0 +1,15 @@
+package java.lang;
+public final class Short extends Number {
+    public short value;
+    public Short(short i) {
+        value = i;
+    }
+    public int intValue() {
+        return (int) value;
+    }
+    public Short() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/3.0/java/lang/String.java b/stdlib/3.0/java/lang/String.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cfe123d36835aa28ab3cd31efd38f584c2b480e
--- /dev/null
+++ b/stdlib/3.0/java/lang/String.java
@@ -0,0 +1,147 @@
+package java.lang;
+import java.util.Arrays;
+
+public class String {
+    public char[] chars;
+    public int length() {
+        return chars.length;
+    }
+    public char charAt(int i) {
+        return chars[i];
+    }
+    public String() {
+        chars = new char[0];
+    }
+    public String(char[] chars) {
+        this.chars = new char[chars.length];
+        for(int i = 0; i < chars.length; i = i + 1) this.chars[i] = chars[i];
+    }
+    public String(String other) {
+        this.chars = other.chars;
+    }
+    public String concat(String s2) {
+        int i = 0;
+        char[] newchars = new char[length() + s2.length()];
+        for(i = 0; i < length(); i = i + 1)
+            newchars[i] = chars[i];
+        for(i = 0; i < s2.length(); i = i + 1)
+            newchars[i+length()] = s2.chars[i];
+        return new String(newchars);
+    }
+    public static String valueOf(char c) {
+        char[] newchars = new char[1];
+        newchars[0] = c;
+        return new String(newchars);
+    }
+    public static String valueOf(int i) {
+        char[] ret = new char[15];
+        int j = 0;
+        boolean wasneg = false;
+        if(i == -2147483648) return "-2147483648";
+        if(i<0) {
+            wasneg = true;
+            i = -i;
+        }
+        if(i == 0) {
+            ret[j] = '0';
+            j = j + 1;
+        } else {
+            while(i > 0) {
+                int d = i % 10;
+                i = i / 10;
+                ret[j] = (char) (d + '0');
+                j = j + 1;
+            }
+        }
+        if(wasneg) {
+            ret[j] = '-';
+            j = j + 1;
+        }
+        char[] ret2 = new char[j];
+        for(i = 0; i < j; i = i + 1) ret2[i] = ret[j-1-i];
+        return new String(ret2);
+    }
+    public static String valueOf(short i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(byte i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(boolean b) {
+        if(b) return "true"; else return "false";
+    }
+    public static String valueOf(Object o) {
+        if(o == null)  return "null"; else return o.toString();
+    }
+    public static String valueOf(String o) {
+        if(o == null)  return "null"; else return o;
+    }
+    public boolean equals(Object o) {
+        if(o == null) return false;
+        if(!(o instanceof String)) return false;
+        return Arrays.equals(chars, ((String)o).chars);
+    }
+    public String substring(int i, int j) {
+        int k = 0;
+        if(i<0) return "";
+        if(j>length()) return "";
+        if(j<i) return "";
+        char[] ret = new char[j-i];
+        for(k=i;k<j;k=k+1) ret[k-i] = charAt(k);
+        return new String(ret);
+    }
+    public String trim() {
+        int i = 0;
+        int j = 0;
+        for(i=0;i<length() && charAt(i)<=' ';i=i+1) {}
+        for(j=length()-1;j>=0 && charAt(j)<=' ';j=j-1) {}
+        if(i>j) return ""; else return substring(i,j+1);
+    }
+    public int hashCode() {
+        int h = 0;
+        for (int i = 0; i < chars.length; i = i+1) {
+            h = 31*h + chars[i];
+        }
+
+        return h;
+    }
+    public String toString() {
+        return this;
+    }
+    public int compareTo(Object other) {
+        return compareTo((String) other);
+    }
+    public int compareTo(String other) {
+        int i = 0;
+        boolean b = true;
+        while(b) {
+            if(i >= chars.length && i >= other.chars.length) return 0;
+            if(i >= chars.length) return -1;
+            if(i >= other.chars.length) return 1;
+            if(chars[i] < other.chars[i])  return -1;
+            if(chars[i] > other.chars[i])  return 1;
+            i = i + 1;
+        }
+        return 0;
+    }
+    public char[] toCharArray() {
+        char[] ret = new char[chars.length];
+        for(int i = 0; i < ret.length; i = i+1) {
+            ret[i] = chars[i];
+        }
+        return ret;
+    }
+    public int indexOf(String needle) {
+        int offset = 0;
+        int i = 0;
+        for(offset = 0; offset < length(); offset = offset + 1) {
+            boolean found = true;
+            for(i = 0; i < needle.length(); i = i + 1) {
+                if(i+offset >= length()) found = false;
+                else if(chars[i+offset] != needle.chars[i]) found = false;
+            }
+            if(found) return offset;
+        }
+        return -1;
+    }
+}
diff --git a/stdlib/3.0/java/lang/System.java b/stdlib/3.0/java/lang/System.java
new file mode 100644
index 0000000000000000000000000000000000000000..a321db885510df85c643e36eaa20c57799e1de2c
--- /dev/null
+++ b/stdlib/3.0/java/lang/System.java
@@ -0,0 +1,10 @@
+package java.lang;
+import java.io.PrintStream;
+
+public class System {
+    public static PrintStream out = new PrintStream();
+    public static void gc() {
+    }
+    public System() {
+    }
+}
diff --git a/stdlib/3.0/java/util/Arrays.java b/stdlib/3.0/java/util/Arrays.java
new file mode 100644
index 0000000000000000000000000000000000000000..e19406172869e03c67a7dfe18d244da782fffd1c
--- /dev/null
+++ b/stdlib/3.0/java/util/Arrays.java
@@ -0,0 +1,20 @@
+package java.util;
+
+public class Arrays {
+    public Arrays() {
+    }
+    public static boolean equals(boolean[] a1, boolean[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+    public static boolean equals(char[] a1, char[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+}
diff --git a/stdlib/3.0/runtime.o b/stdlib/3.0/runtime.o
new file mode 100644
index 0000000000000000000000000000000000000000..4767c7ba28f6a79c8f44b8013061d5877678f457
Binary files /dev/null and b/stdlib/3.0/runtime.o differ
diff --git a/stdlib/3.0/runtime.s b/stdlib/3.0/runtime.s
new file mode 100644
index 0000000000000000000000000000000000000000..7449aa1b0465f6295d2cb16ba36d346ed6ecf40e
--- /dev/null
+++ b/stdlib/3.0/runtime.s
@@ -0,0 +1,56 @@
+section .text
+
+; Allocates eax bytes of memory. Pointer to allocated memory returned in eax.
+    global __malloc
+__malloc:
+    push eax
+    mov eax, 45  ; sys_brk system call
+    mov ebx, 0   ; 0 bytes - query current brk
+    int 0x80
+    pop ebx
+    push eax
+    add ebx, eax ; move brk ahead by number of bytes requested
+    mov eax, 45  ; sys_brk system call
+    int 0x80
+    pop ebx
+    cmp eax, 0   ; on error, exit with code 22
+    jne ok
+    mov eax, 22
+    call __debexit
+ok:
+    mov eax, ebx
+    ret
+
+; Debugging exit: ends the process, returning the value of
+; eax as the exit code.
+    global __debexit
+__debexit:
+    mov ebx, eax
+    mov eax, 1   ; sys_exit system call
+    int 0x80
+
+; Exceptional exit: ends the process with exit code 13.
+; Call this in cases where the Joos code would throw an exception.
+    global __exception
+__exception:
+    mov eax, 1   ; sys_exit system call
+    mov ebx, 13
+    int 0x80
+
+; Implementation of java.io.OutputStream.nativeWrite method.
+; Outputs the low-order byte of eax to standard output.
+    global NATIVEjava.io.OutputStream.nativeWrite
+NATIVEjava.io.OutputStream.nativeWrite:
+    mov [char], al ; save the low order byte in memory
+    mov eax, 4     ; sys_write system call
+    mov ecx, char  ; address of bytes to write
+    mov ebx, 1     ; stdout
+    mov edx, 1     ; number of bytes to write
+    int 0x80
+    mov eax, 0     ; return 0
+    ret
+
+section .data
+
+char:
+    dd 0
diff --git a/stdlib/4.0/java/io/OutputStream.java b/stdlib/4.0/java/io/OutputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..9de76e9713e940d701c53a1ed2766547b0aef09b
--- /dev/null
+++ b/stdlib/4.0/java/io/OutputStream.java
@@ -0,0 +1,14 @@
+package java.io;
+public class OutputStream {
+    public OutputStream() {
+    }
+    public void write(char c) {
+        write((int)c);
+    }
+    public void write(int b) {
+        PrintStream.nativeWrite(b);
+    }
+    protected static native int nativeWrite(int b);
+    public void flush() {
+    }
+}
diff --git a/stdlib/4.0/java/io/PrintStream.java b/stdlib/4.0/java/io/PrintStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..08ea27135dfbdf9e5830e5cc268cdc18e9e7c345
--- /dev/null
+++ b/stdlib/4.0/java/io/PrintStream.java
@@ -0,0 +1,53 @@
+package java.io;
+public class PrintStream extends OutputStream {
+    public PrintStream() {
+    }
+    public void print(String s) {
+        for(int i = 0; i < s.length(); i = i + 1) {
+            write(s.charAt(i));
+        }
+    }
+    public void println() {
+        println("");
+    }
+    public void println(String s) {
+        print(s);
+        write('\n');
+    }
+    public void println(Object b) {
+        println(String.valueOf(b));
+    }
+    public void println(boolean b) {
+        println(String.valueOf(b));
+    }
+    public void println(byte b) {
+        println(String.valueOf(b));
+    }
+    public void println(char b) {
+        println(String.valueOf(b));
+    }
+    public void println(short b) {
+        println(String.valueOf(b));
+    }
+    public void println(int b) {
+        println(String.valueOf(b));
+    }
+    public void print(Object b) {
+        print(String.valueOf(b));
+    }
+    public void print(boolean b) {
+        print(String.valueOf(b));
+    }
+    public void print(byte b) {
+        print(String.valueOf(b));
+    }
+    public void print(char b) {
+        print(String.valueOf(b));
+    }
+    public void print(short b) {
+        print(String.valueOf(b));
+    }
+    public void print(int b) {
+        print(String.valueOf(b));
+    }
+}
diff --git a/stdlib/4.0/java/io/Serializable.java b/stdlib/4.0/java/io/Serializable.java
new file mode 100644
index 0000000000000000000000000000000000000000..071b7d5149b4bdc54a778bc0f3ef196abea023c7
--- /dev/null
+++ b/stdlib/4.0/java/io/Serializable.java
@@ -0,0 +1,3 @@
+package java.io;
+public interface Serializable {
+}
diff --git a/stdlib/4.0/java/lang/Boolean.java b/stdlib/4.0/java/lang/Boolean.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdeb75e96ac5fd352e3d49b3c61b02ac7b3462a5
--- /dev/null
+++ b/stdlib/4.0/java/lang/Boolean.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Boolean {
+    public boolean value;
+    public Boolean(boolean i) {
+        value = i;
+    }
+    public Boolean() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/4.0/java/lang/Byte.java b/stdlib/4.0/java/lang/Byte.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea6388fbb3a704a2bb0b98831a4b1a6b221a4b35
--- /dev/null
+++ b/stdlib/4.0/java/lang/Byte.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Byte {
+    public byte value;
+    public Byte(byte i) {
+        value = i;
+    }
+    public Byte() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/4.0/java/lang/Character.java b/stdlib/4.0/java/lang/Character.java
new file mode 100644
index 0000000000000000000000000000000000000000..726c2ecaf190da36ab9b858adf5fa2e1b220fab0
--- /dev/null
+++ b/stdlib/4.0/java/lang/Character.java
@@ -0,0 +1,12 @@
+package java.lang;
+public final class Character {
+    public char value;
+    public Character(char i) {
+        value = i;
+    }
+    public Character() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/4.0/java/lang/Class.java b/stdlib/4.0/java/lang/Class.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccc97605214ef9fca9b3d8db1f0e7f9007601900
--- /dev/null
+++ b/stdlib/4.0/java/lang/Class.java
@@ -0,0 +1,5 @@
+package java.lang;
+public class Class {
+    public Class() {
+    }
+}
diff --git a/stdlib/4.0/java/lang/Cloneable.java b/stdlib/4.0/java/lang/Cloneable.java
new file mode 100644
index 0000000000000000000000000000000000000000..d14aed45f7f828a3bb46dc59599c4e3c5adef073
--- /dev/null
+++ b/stdlib/4.0/java/lang/Cloneable.java
@@ -0,0 +1,4 @@
+package java.lang;
+
+public interface Cloneable {
+}
diff --git a/stdlib/4.0/java/lang/Integer.java b/stdlib/4.0/java/lang/Integer.java
new file mode 100644
index 0000000000000000000000000000000000000000..14106cafe7841ba4e9e4a1fe2db5b603a038e51e
--- /dev/null
+++ b/stdlib/4.0/java/lang/Integer.java
@@ -0,0 +1,35 @@
+package java.lang;
+public final class Integer extends Number {
+    public int value;
+    public Integer(int i) {
+        value = i;
+    }
+    public int intValue() {
+        return value;
+    }
+    public static int parseInt(String s) {
+        int ret = 0;
+        boolean neg = false;
+        int i = 0;
+        while(i < s.length() && 
+          (s.charAt(i) == '-' || (s.charAt(i) >= '0' && s.charAt(i) <= '9'))) {
+            if(s.charAt(i) == '-') neg = !neg;
+            else {
+                ret = ret * 10 + s.charAt(i)-'0';
+            }
+            i = i+1;
+        }
+        if(neg) ret = -ret;
+        return ret;
+    }
+    public Integer(String s) {
+        value = Integer.parseInt(s);
+    }
+    public Integer() {
+        value = 0;
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static int MAX_VALUE = 2147483647;
+}
diff --git a/stdlib/4.0/java/lang/Number.java b/stdlib/4.0/java/lang/Number.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf9685eafe1d7858a76e6b9c5bb976dfa9b224c3
--- /dev/null
+++ b/stdlib/4.0/java/lang/Number.java
@@ -0,0 +1,6 @@
+package java.lang;
+public abstract class Number {
+    public abstract int intValue();
+    public Number() {
+    }
+}
diff --git a/stdlib/4.0/java/lang/Object.java b/stdlib/4.0/java/lang/Object.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6cd3a264b5684f834b098760f4bee8bd345a8a9
--- /dev/null
+++ b/stdlib/4.0/java/lang/Object.java
@@ -0,0 +1,20 @@
+package java.lang;
+public class Object {
+    public Object() {
+    }
+    public boolean equals(Object other) {
+        return this == other;
+    }
+    public String toString() {
+        return "Some random object";
+    }
+    public int hashCode() {
+        return 42;
+    }
+    protected Object clone() {
+        return this;
+    }
+    public final Class getClass() {
+        return null;
+    }
+}
diff --git a/stdlib/4.0/java/lang/Short.java b/stdlib/4.0/java/lang/Short.java
new file mode 100644
index 0000000000000000000000000000000000000000..61a97a210a21985fe22f8983c87142d8291c75cf
--- /dev/null
+++ b/stdlib/4.0/java/lang/Short.java
@@ -0,0 +1,15 @@
+package java.lang;
+public final class Short extends Number {
+    public short value;
+    public Short(short i) {
+        value = i;
+    }
+    public int intValue() {
+        return (int) value;
+    }
+    public Short() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/4.0/java/lang/String.java b/stdlib/4.0/java/lang/String.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cfe123d36835aa28ab3cd31efd38f584c2b480e
--- /dev/null
+++ b/stdlib/4.0/java/lang/String.java
@@ -0,0 +1,147 @@
+package java.lang;
+import java.util.Arrays;
+
+public class String {
+    public char[] chars;
+    public int length() {
+        return chars.length;
+    }
+    public char charAt(int i) {
+        return chars[i];
+    }
+    public String() {
+        chars = new char[0];
+    }
+    public String(char[] chars) {
+        this.chars = new char[chars.length];
+        for(int i = 0; i < chars.length; i = i + 1) this.chars[i] = chars[i];
+    }
+    public String(String other) {
+        this.chars = other.chars;
+    }
+    public String concat(String s2) {
+        int i = 0;
+        char[] newchars = new char[length() + s2.length()];
+        for(i = 0; i < length(); i = i + 1)
+            newchars[i] = chars[i];
+        for(i = 0; i < s2.length(); i = i + 1)
+            newchars[i+length()] = s2.chars[i];
+        return new String(newchars);
+    }
+    public static String valueOf(char c) {
+        char[] newchars = new char[1];
+        newchars[0] = c;
+        return new String(newchars);
+    }
+    public static String valueOf(int i) {
+        char[] ret = new char[15];
+        int j = 0;
+        boolean wasneg = false;
+        if(i == -2147483648) return "-2147483648";
+        if(i<0) {
+            wasneg = true;
+            i = -i;
+        }
+        if(i == 0) {
+            ret[j] = '0';
+            j = j + 1;
+        } else {
+            while(i > 0) {
+                int d = i % 10;
+                i = i / 10;
+                ret[j] = (char) (d + '0');
+                j = j + 1;
+            }
+        }
+        if(wasneg) {
+            ret[j] = '-';
+            j = j + 1;
+        }
+        char[] ret2 = new char[j];
+        for(i = 0; i < j; i = i + 1) ret2[i] = ret[j-1-i];
+        return new String(ret2);
+    }
+    public static String valueOf(short i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(byte i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(boolean b) {
+        if(b) return "true"; else return "false";
+    }
+    public static String valueOf(Object o) {
+        if(o == null)  return "null"; else return o.toString();
+    }
+    public static String valueOf(String o) {
+        if(o == null)  return "null"; else return o;
+    }
+    public boolean equals(Object o) {
+        if(o == null) return false;
+        if(!(o instanceof String)) return false;
+        return Arrays.equals(chars, ((String)o).chars);
+    }
+    public String substring(int i, int j) {
+        int k = 0;
+        if(i<0) return "";
+        if(j>length()) return "";
+        if(j<i) return "";
+        char[] ret = new char[j-i];
+        for(k=i;k<j;k=k+1) ret[k-i] = charAt(k);
+        return new String(ret);
+    }
+    public String trim() {
+        int i = 0;
+        int j = 0;
+        for(i=0;i<length() && charAt(i)<=' ';i=i+1) {}
+        for(j=length()-1;j>=0 && charAt(j)<=' ';j=j-1) {}
+        if(i>j) return ""; else return substring(i,j+1);
+    }
+    public int hashCode() {
+        int h = 0;
+        for (int i = 0; i < chars.length; i = i+1) {
+            h = 31*h + chars[i];
+        }
+
+        return h;
+    }
+    public String toString() {
+        return this;
+    }
+    public int compareTo(Object other) {
+        return compareTo((String) other);
+    }
+    public int compareTo(String other) {
+        int i = 0;
+        boolean b = true;
+        while(b) {
+            if(i >= chars.length && i >= other.chars.length) return 0;
+            if(i >= chars.length) return -1;
+            if(i >= other.chars.length) return 1;
+            if(chars[i] < other.chars[i])  return -1;
+            if(chars[i] > other.chars[i])  return 1;
+            i = i + 1;
+        }
+        return 0;
+    }
+    public char[] toCharArray() {
+        char[] ret = new char[chars.length];
+        for(int i = 0; i < ret.length; i = i+1) {
+            ret[i] = chars[i];
+        }
+        return ret;
+    }
+    public int indexOf(String needle) {
+        int offset = 0;
+        int i = 0;
+        for(offset = 0; offset < length(); offset = offset + 1) {
+            boolean found = true;
+            for(i = 0; i < needle.length(); i = i + 1) {
+                if(i+offset >= length()) found = false;
+                else if(chars[i+offset] != needle.chars[i]) found = false;
+            }
+            if(found) return offset;
+        }
+        return -1;
+    }
+}
diff --git a/stdlib/4.0/java/lang/System.java b/stdlib/4.0/java/lang/System.java
new file mode 100644
index 0000000000000000000000000000000000000000..a321db885510df85c643e36eaa20c57799e1de2c
--- /dev/null
+++ b/stdlib/4.0/java/lang/System.java
@@ -0,0 +1,10 @@
+package java.lang;
+import java.io.PrintStream;
+
+public class System {
+    public static PrintStream out = new PrintStream();
+    public static void gc() {
+    }
+    public System() {
+    }
+}
diff --git a/stdlib/4.0/java/util/Arrays.java b/stdlib/4.0/java/util/Arrays.java
new file mode 100644
index 0000000000000000000000000000000000000000..e19406172869e03c67a7dfe18d244da782fffd1c
--- /dev/null
+++ b/stdlib/4.0/java/util/Arrays.java
@@ -0,0 +1,20 @@
+package java.util;
+
+public class Arrays {
+    public Arrays() {
+    }
+    public static boolean equals(boolean[] a1, boolean[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+    public static boolean equals(char[] a1, char[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+}
diff --git a/stdlib/4.0/runtime.o b/stdlib/4.0/runtime.o
new file mode 100644
index 0000000000000000000000000000000000000000..4767c7ba28f6a79c8f44b8013061d5877678f457
Binary files /dev/null and b/stdlib/4.0/runtime.o differ
diff --git a/stdlib/4.0/runtime.s b/stdlib/4.0/runtime.s
new file mode 100644
index 0000000000000000000000000000000000000000..7449aa1b0465f6295d2cb16ba36d346ed6ecf40e
--- /dev/null
+++ b/stdlib/4.0/runtime.s
@@ -0,0 +1,56 @@
+section .text
+
+; Allocates eax bytes of memory. Pointer to allocated memory returned in eax.
+    global __malloc
+__malloc:
+    push eax
+    mov eax, 45  ; sys_brk system call
+    mov ebx, 0   ; 0 bytes - query current brk
+    int 0x80
+    pop ebx
+    push eax
+    add ebx, eax ; move brk ahead by number of bytes requested
+    mov eax, 45  ; sys_brk system call
+    int 0x80
+    pop ebx
+    cmp eax, 0   ; on error, exit with code 22
+    jne ok
+    mov eax, 22
+    call __debexit
+ok:
+    mov eax, ebx
+    ret
+
+; Debugging exit: ends the process, returning the value of
+; eax as the exit code.
+    global __debexit
+__debexit:
+    mov ebx, eax
+    mov eax, 1   ; sys_exit system call
+    int 0x80
+
+; Exceptional exit: ends the process with exit code 13.
+; Call this in cases where the Joos code would throw an exception.
+    global __exception
+__exception:
+    mov eax, 1   ; sys_exit system call
+    mov ebx, 13
+    int 0x80
+
+; Implementation of java.io.OutputStream.nativeWrite method.
+; Outputs the low-order byte of eax to standard output.
+    global NATIVEjava.io.OutputStream.nativeWrite
+NATIVEjava.io.OutputStream.nativeWrite:
+    mov [char], al ; save the low order byte in memory
+    mov eax, 4     ; sys_write system call
+    mov ecx, char  ; address of bytes to write
+    mov ebx, 1     ; stdout
+    mov edx, 1     ; number of bytes to write
+    int 0x80
+    mov eax, 0     ; return 0
+    ret
+
+section .data
+
+char:
+    dd 0
diff --git a/stdlib/5.0/java/io/OutputStream.java b/stdlib/5.0/java/io/OutputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..9de76e9713e940d701c53a1ed2766547b0aef09b
--- /dev/null
+++ b/stdlib/5.0/java/io/OutputStream.java
@@ -0,0 +1,14 @@
+package java.io;
+public class OutputStream {
+    public OutputStream() {
+    }
+    public void write(char c) {
+        write((int)c);
+    }
+    public void write(int b) {
+        PrintStream.nativeWrite(b);
+    }
+    protected static native int nativeWrite(int b);
+    public void flush() {
+    }
+}
diff --git a/stdlib/5.0/java/io/PrintStream.java b/stdlib/5.0/java/io/PrintStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..08ea27135dfbdf9e5830e5cc268cdc18e9e7c345
--- /dev/null
+++ b/stdlib/5.0/java/io/PrintStream.java
@@ -0,0 +1,53 @@
+package java.io;
+public class PrintStream extends OutputStream {
+    public PrintStream() {
+    }
+    public void print(String s) {
+        for(int i = 0; i < s.length(); i = i + 1) {
+            write(s.charAt(i));
+        }
+    }
+    public void println() {
+        println("");
+    }
+    public void println(String s) {
+        print(s);
+        write('\n');
+    }
+    public void println(Object b) {
+        println(String.valueOf(b));
+    }
+    public void println(boolean b) {
+        println(String.valueOf(b));
+    }
+    public void println(byte b) {
+        println(String.valueOf(b));
+    }
+    public void println(char b) {
+        println(String.valueOf(b));
+    }
+    public void println(short b) {
+        println(String.valueOf(b));
+    }
+    public void println(int b) {
+        println(String.valueOf(b));
+    }
+    public void print(Object b) {
+        print(String.valueOf(b));
+    }
+    public void print(boolean b) {
+        print(String.valueOf(b));
+    }
+    public void print(byte b) {
+        print(String.valueOf(b));
+    }
+    public void print(char b) {
+        print(String.valueOf(b));
+    }
+    public void print(short b) {
+        print(String.valueOf(b));
+    }
+    public void print(int b) {
+        print(String.valueOf(b));
+    }
+}
diff --git a/stdlib/5.0/java/io/Serializable.java b/stdlib/5.0/java/io/Serializable.java
new file mode 100644
index 0000000000000000000000000000000000000000..071b7d5149b4bdc54a778bc0f3ef196abea023c7
--- /dev/null
+++ b/stdlib/5.0/java/io/Serializable.java
@@ -0,0 +1,3 @@
+package java.io;
+public interface Serializable {
+}
diff --git a/stdlib/5.0/java/lang/Boolean.java b/stdlib/5.0/java/lang/Boolean.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdeb75e96ac5fd352e3d49b3c61b02ac7b3462a5
--- /dev/null
+++ b/stdlib/5.0/java/lang/Boolean.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Boolean {
+    public boolean value;
+    public Boolean(boolean i) {
+        value = i;
+    }
+    public Boolean() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/5.0/java/lang/Byte.java b/stdlib/5.0/java/lang/Byte.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea6388fbb3a704a2bb0b98831a4b1a6b221a4b35
--- /dev/null
+++ b/stdlib/5.0/java/lang/Byte.java
@@ -0,0 +1,13 @@
+package java.lang;
+public final class Byte {
+    public byte value;
+    public Byte(byte i) {
+        value = i;
+    }
+    public Byte() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static byte MAX_VALUE = (byte)127;
+}
diff --git a/stdlib/5.0/java/lang/Character.java b/stdlib/5.0/java/lang/Character.java
new file mode 100644
index 0000000000000000000000000000000000000000..726c2ecaf190da36ab9b858adf5fa2e1b220fab0
--- /dev/null
+++ b/stdlib/5.0/java/lang/Character.java
@@ -0,0 +1,12 @@
+package java.lang;
+public final class Character {
+    public char value;
+    public Character(char i) {
+        value = i;
+    }
+    public Character() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/5.0/java/lang/Class.java b/stdlib/5.0/java/lang/Class.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccc97605214ef9fca9b3d8db1f0e7f9007601900
--- /dev/null
+++ b/stdlib/5.0/java/lang/Class.java
@@ -0,0 +1,5 @@
+package java.lang;
+public class Class {
+    public Class() {
+    }
+}
diff --git a/stdlib/5.0/java/lang/Cloneable.java b/stdlib/5.0/java/lang/Cloneable.java
new file mode 100644
index 0000000000000000000000000000000000000000..d14aed45f7f828a3bb46dc59599c4e3c5adef073
--- /dev/null
+++ b/stdlib/5.0/java/lang/Cloneable.java
@@ -0,0 +1,4 @@
+package java.lang;
+
+public interface Cloneable {
+}
diff --git a/stdlib/5.0/java/lang/Integer.java b/stdlib/5.0/java/lang/Integer.java
new file mode 100644
index 0000000000000000000000000000000000000000..14106cafe7841ba4e9e4a1fe2db5b603a038e51e
--- /dev/null
+++ b/stdlib/5.0/java/lang/Integer.java
@@ -0,0 +1,35 @@
+package java.lang;
+public final class Integer extends Number {
+    public int value;
+    public Integer(int i) {
+        value = i;
+    }
+    public int intValue() {
+        return value;
+    }
+    public static int parseInt(String s) {
+        int ret = 0;
+        boolean neg = false;
+        int i = 0;
+        while(i < s.length() && 
+          (s.charAt(i) == '-' || (s.charAt(i) >= '0' && s.charAt(i) <= '9'))) {
+            if(s.charAt(i) == '-') neg = !neg;
+            else {
+                ret = ret * 10 + s.charAt(i)-'0';
+            }
+            i = i+1;
+        }
+        if(neg) ret = -ret;
+        return ret;
+    }
+    public Integer(String s) {
+        value = Integer.parseInt(s);
+    }
+    public Integer() {
+        value = 0;
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+    public static int MAX_VALUE = 2147483647;
+}
diff --git a/stdlib/5.0/java/lang/Number.java b/stdlib/5.0/java/lang/Number.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf9685eafe1d7858a76e6b9c5bb976dfa9b224c3
--- /dev/null
+++ b/stdlib/5.0/java/lang/Number.java
@@ -0,0 +1,6 @@
+package java.lang;
+public abstract class Number {
+    public abstract int intValue();
+    public Number() {
+    }
+}
diff --git a/stdlib/5.0/java/lang/Object.java b/stdlib/5.0/java/lang/Object.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6cd3a264b5684f834b098760f4bee8bd345a8a9
--- /dev/null
+++ b/stdlib/5.0/java/lang/Object.java
@@ -0,0 +1,20 @@
+package java.lang;
+public class Object {
+    public Object() {
+    }
+    public boolean equals(Object other) {
+        return this == other;
+    }
+    public String toString() {
+        return "Some random object";
+    }
+    public int hashCode() {
+        return 42;
+    }
+    protected Object clone() {
+        return this;
+    }
+    public final Class getClass() {
+        return null;
+    }
+}
diff --git a/stdlib/5.0/java/lang/Short.java b/stdlib/5.0/java/lang/Short.java
new file mode 100644
index 0000000000000000000000000000000000000000..61a97a210a21985fe22f8983c87142d8291c75cf
--- /dev/null
+++ b/stdlib/5.0/java/lang/Short.java
@@ -0,0 +1,15 @@
+package java.lang;
+public final class Short extends Number {
+    public short value;
+    public Short(short i) {
+        value = i;
+    }
+    public int intValue() {
+        return (int) value;
+    }
+    public Short() {
+    }
+    public String toString() {
+        return String.valueOf(value);
+    }
+}
diff --git a/stdlib/5.0/java/lang/String.java b/stdlib/5.0/java/lang/String.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cfe123d36835aa28ab3cd31efd38f584c2b480e
--- /dev/null
+++ b/stdlib/5.0/java/lang/String.java
@@ -0,0 +1,147 @@
+package java.lang;
+import java.util.Arrays;
+
+public class String {
+    public char[] chars;
+    public int length() {
+        return chars.length;
+    }
+    public char charAt(int i) {
+        return chars[i];
+    }
+    public String() {
+        chars = new char[0];
+    }
+    public String(char[] chars) {
+        this.chars = new char[chars.length];
+        for(int i = 0; i < chars.length; i = i + 1) this.chars[i] = chars[i];
+    }
+    public String(String other) {
+        this.chars = other.chars;
+    }
+    public String concat(String s2) {
+        int i = 0;
+        char[] newchars = new char[length() + s2.length()];
+        for(i = 0; i < length(); i = i + 1)
+            newchars[i] = chars[i];
+        for(i = 0; i < s2.length(); i = i + 1)
+            newchars[i+length()] = s2.chars[i];
+        return new String(newchars);
+    }
+    public static String valueOf(char c) {
+        char[] newchars = new char[1];
+        newchars[0] = c;
+        return new String(newchars);
+    }
+    public static String valueOf(int i) {
+        char[] ret = new char[15];
+        int j = 0;
+        boolean wasneg = false;
+        if(i == -2147483648) return "-2147483648";
+        if(i<0) {
+            wasneg = true;
+            i = -i;
+        }
+        if(i == 0) {
+            ret[j] = '0';
+            j = j + 1;
+        } else {
+            while(i > 0) {
+                int d = i % 10;
+                i = i / 10;
+                ret[j] = (char) (d + '0');
+                j = j + 1;
+            }
+        }
+        if(wasneg) {
+            ret[j] = '-';
+            j = j + 1;
+        }
+        char[] ret2 = new char[j];
+        for(i = 0; i < j; i = i + 1) ret2[i] = ret[j-1-i];
+        return new String(ret2);
+    }
+    public static String valueOf(short i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(byte i) {
+        return String.valueOf((int) i);
+    }
+    public static String valueOf(boolean b) {
+        if(b) return "true"; else return "false";
+    }
+    public static String valueOf(Object o) {
+        if(o == null)  return "null"; else return o.toString();
+    }
+    public static String valueOf(String o) {
+        if(o == null)  return "null"; else return o;
+    }
+    public boolean equals(Object o) {
+        if(o == null) return false;
+        if(!(o instanceof String)) return false;
+        return Arrays.equals(chars, ((String)o).chars);
+    }
+    public String substring(int i, int j) {
+        int k = 0;
+        if(i<0) return "";
+        if(j>length()) return "";
+        if(j<i) return "";
+        char[] ret = new char[j-i];
+        for(k=i;k<j;k=k+1) ret[k-i] = charAt(k);
+        return new String(ret);
+    }
+    public String trim() {
+        int i = 0;
+        int j = 0;
+        for(i=0;i<length() && charAt(i)<=' ';i=i+1) {}
+        for(j=length()-1;j>=0 && charAt(j)<=' ';j=j-1) {}
+        if(i>j) return ""; else return substring(i,j+1);
+    }
+    public int hashCode() {
+        int h = 0;
+        for (int i = 0; i < chars.length; i = i+1) {
+            h = 31*h + chars[i];
+        }
+
+        return h;
+    }
+    public String toString() {
+        return this;
+    }
+    public int compareTo(Object other) {
+        return compareTo((String) other);
+    }
+    public int compareTo(String other) {
+        int i = 0;
+        boolean b = true;
+        while(b) {
+            if(i >= chars.length && i >= other.chars.length) return 0;
+            if(i >= chars.length) return -1;
+            if(i >= other.chars.length) return 1;
+            if(chars[i] < other.chars[i])  return -1;
+            if(chars[i] > other.chars[i])  return 1;
+            i = i + 1;
+        }
+        return 0;
+    }
+    public char[] toCharArray() {
+        char[] ret = new char[chars.length];
+        for(int i = 0; i < ret.length; i = i+1) {
+            ret[i] = chars[i];
+        }
+        return ret;
+    }
+    public int indexOf(String needle) {
+        int offset = 0;
+        int i = 0;
+        for(offset = 0; offset < length(); offset = offset + 1) {
+            boolean found = true;
+            for(i = 0; i < needle.length(); i = i + 1) {
+                if(i+offset >= length()) found = false;
+                else if(chars[i+offset] != needle.chars[i]) found = false;
+            }
+            if(found) return offset;
+        }
+        return -1;
+    }
+}
diff --git a/stdlib/5.0/java/lang/System.java b/stdlib/5.0/java/lang/System.java
new file mode 100644
index 0000000000000000000000000000000000000000..a321db885510df85c643e36eaa20c57799e1de2c
--- /dev/null
+++ b/stdlib/5.0/java/lang/System.java
@@ -0,0 +1,10 @@
+package java.lang;
+import java.io.PrintStream;
+
+public class System {
+    public static PrintStream out = new PrintStream();
+    public static void gc() {
+    }
+    public System() {
+    }
+}
diff --git a/stdlib/5.0/java/util/Arrays.java b/stdlib/5.0/java/util/Arrays.java
new file mode 100644
index 0000000000000000000000000000000000000000..e19406172869e03c67a7dfe18d244da782fffd1c
--- /dev/null
+++ b/stdlib/5.0/java/util/Arrays.java
@@ -0,0 +1,20 @@
+package java.util;
+
+public class Arrays {
+    public Arrays() {
+    }
+    public static boolean equals(boolean[] a1, boolean[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+    public static boolean equals(char[] a1, char[] a2) {
+        if(a1.length != a2.length) return false;
+        for(int i = 0; i < a1.length; i = i + 1)
+            if(a1[i] != a2[i])
+                return false;
+        return true;
+    }
+}
diff --git a/stdlib/5.0/runtime.o b/stdlib/5.0/runtime.o
new file mode 100644
index 0000000000000000000000000000000000000000..4767c7ba28f6a79c8f44b8013061d5877678f457
Binary files /dev/null and b/stdlib/5.0/runtime.o differ
diff --git a/stdlib/5.0/runtime.s b/stdlib/5.0/runtime.s
new file mode 100644
index 0000000000000000000000000000000000000000..7449aa1b0465f6295d2cb16ba36d346ed6ecf40e
--- /dev/null
+++ b/stdlib/5.0/runtime.s
@@ -0,0 +1,56 @@
+section .text
+
+; Allocates eax bytes of memory. Pointer to allocated memory returned in eax.
+    global __malloc
+__malloc:
+    push eax
+    mov eax, 45  ; sys_brk system call
+    mov ebx, 0   ; 0 bytes - query current brk
+    int 0x80
+    pop ebx
+    push eax
+    add ebx, eax ; move brk ahead by number of bytes requested
+    mov eax, 45  ; sys_brk system call
+    int 0x80
+    pop ebx
+    cmp eax, 0   ; on error, exit with code 22
+    jne ok
+    mov eax, 22
+    call __debexit
+ok:
+    mov eax, ebx
+    ret
+
+; Debugging exit: ends the process, returning the value of
+; eax as the exit code.
+    global __debexit
+__debexit:
+    mov ebx, eax
+    mov eax, 1   ; sys_exit system call
+    int 0x80
+
+; Exceptional exit: ends the process with exit code 13.
+; Call this in cases where the Joos code would throw an exception.
+    global __exception
+__exception:
+    mov eax, 1   ; sys_exit system call
+    mov ebx, 13
+    int 0x80
+
+; Implementation of java.io.OutputStream.nativeWrite method.
+; Outputs the low-order byte of eax to standard output.
+    global NATIVEjava.io.OutputStream.nativeWrite
+NATIVEjava.io.OutputStream.nativeWrite:
+    mov [char], al ; save the low order byte in memory
+    mov eax, 4     ; sys_write system call
+    mov ecx, char  ; address of bytes to write
+    mov ebx, 1     ; stdout
+    mov edx, 1     ; number of bytes to write
+    int 0x80
+    mov eax, 0     ; return 0
+    ret
+
+section .data
+
+char:
+    dd 0