diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index ba76e4063f61dd90997916bd5526997cb46a21fd..08cbe18cd4f7f2278adb4d28be3c838f9d233733 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -59,6 +59,7 @@ import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.ShowCallerOf;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.Utils;
@@ -79,7 +80,9 @@ import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -189,6 +192,32 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
                 RCaller parent = RArguments.getCall(frame);
                 frame = Utils.getCallerFrame(parent, FrameAccess.READ_ONLY);
             }
+            return findCallerFromFrame(frame);
+        } else if (call instanceof ShowCallerOf) {
+            Frame frame = Utils.getActualCurrentFrame();
+
+            boolean match = false;
+            String name = ((ShowCallerOf) call).getCallerOf();
+            Frame f = frame;
+            while (f != null && RArguments.isRFrame(f)) {
+                RCaller parent = RArguments.getCall(f);
+                if (parent.isValidCaller()) {
+                    RSyntaxElement syntaxNode = parent.getSyntaxNode();
+                    if (syntaxNode instanceof RSyntaxCall) {
+                        RSyntaxElement syntaxElement = ((RSyntaxCall) syntaxNode).getSyntaxLHS();
+                        if (syntaxElement instanceof RSyntaxLookup) {
+                            if (match) {
+                                return findCallerFromFrame(f);
+                            }
+                            if (name.equals(((RSyntaxLookup) syntaxElement).getIdentifier())) {
+                                match = true;
+                            }
+                        }
+                    }
+                }
+                f = Utils.getCallerFrame(parent, FrameAccess.READ_ONLY);
+            }
+
             return findCallerFromFrame(frame);
         } else {
             RBaseNode originalCall = checkBuiltin(call);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index f4147ee060e9e18ad5a43a21f381ddf23955f4c7..c89561bf38828d6f30571f0cd98efd44e3cbef83 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -108,10 +108,12 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentityNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspect;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspectNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropCheckException;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropClearException;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropGetException;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropTry;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropCheckExceptionNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropClearExceptionNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropGetExceptionNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropTryNodeGen;
@@ -449,6 +451,7 @@ public class BasePackage extends RBuiltinPackage {
         add(FastROptionBuiltin.class, FastROptionBuiltin::create);
         add(FastRTestsTry.class, FastRTestsTryNodeGen::create);
         add(FastRInteropTry.class, FastRInteropTryNodeGen::create);
+        add(FastRInteropCheckException.class, FastRInteropCheckExceptionNodeGen::create);
         add(FastRInteropGetException.class, FastRInteropGetExceptionNodeGen::create);
         add(FastRInteropClearException.class, FastRInteropClearExceptionNodeGen::create);
         add(FastRInspect.class, FastRInspectNodeGen::create);
@@ -461,8 +464,14 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.DoCallExternal.class, FastRInteropFactory.DoCallExternalNodeGen::create);
         add(FastRInterop.IsExternal.class, FastRInteropFactory.IsExternalNodeGen::create);
         add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
+        add(FastRInterop.GetJavaClass.class, FastRInteropFactory.GetJavaClassNodeGen::create);
         add(FastRInterop.JavaClassName.class, FastRInteropFactory.JavaClassNameNodeGen::create);
         add(FastRInterop.JavaAddToClasspath.class, FastRInteropFactory.JavaAddToClasspathNodeGen::create);
+        add(FastRInterop.JavaClasspath.class, FastRInteropFactory.JavaClasspathNodeGen::create);
+        add(FastRInterop.JavaIsIdentical.class, FastRInteropFactory.JavaIsIdenticalNodeGen::create);
+        add(FastRInterop.JavaIsAssignableFrom.class, FastRInteropFactory.JavaIsAssignableFromNodeGen::create);
+        add(FastRInterop.JavaIsInstance.class, FastRInteropFactory.JavaIsInstanceNodeGen::create);
+        add(FastRInterop.JavaAsTruffleObject.class, FastRInteropFactory.JavaAsTruffleObjectNodeGen::create);
         add(FastRInterop.IsForeignArray.class, FastRInteropFactory.IsForeignArrayNodeGen::create);
         add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create);
         add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index ce22e93b4542dbf95490f7ca5945c6ca68d4de3c..837bd534627de17d70d12b97ec38c6f6e873ad64 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -271,7 +271,7 @@ public abstract class Paste extends RBuiltinNode.Arg3 {
     private CastNode getAsCharacterNode() {
         if (asCharacterNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            asCharacterNode = insert(newCastBuilder().returnIf(nullValue(), emptyStringVector()).asStringVector().buildCastNode());
+            asCharacterNode = insert(newCastBuilder().castForeignObjects(true).returnIf(nullValue(), emptyStringVector()).asStringVector().buildCastNode());
         }
         return asCharacterNode;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java
index d70a8830550f69490e871ec0f20bfa822cbf3080..ab7318661930b15223156c2d244c968e6a3fed8d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExternalPtrPrinter.java
@@ -38,7 +38,7 @@ final class ExternalPtrPrinter extends AbstractValuePrinter<RExternalPtr> {
     @Override
     @TruffleBoundary
     protected void printValue(RExternalPtr value, PrintContext printCtx) throws IOException {
-        // like in RDeparse
+        // same like in RDeparse
         if (value.getAddr().isLong()) {
             printCtx.output().print(String.format("<pointer: %s>", Double.toHexString(value.getAddr().asAddress())));
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index adc76dc605830af8f794d21d417b2936c10c2aa2..06f77fcdc7b2bc20cd6ea85ce106a5ee3938a822 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -51,6 +51,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
@@ -59,6 +60,7 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.Source.Builder;
@@ -478,6 +480,8 @@ public class FastRInterop {
     @RBuiltin(name = "new.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "silent"}, behavior = COMPLEX)
     public abstract static class JavaClass extends RBuiltinNode.Arg2 {
 
+        private static final Object accessError = new Object();
+
         static {
             Casts casts = new Casts(JavaClass.class);
             casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
@@ -487,14 +491,81 @@ public class FastRInterop {
 
         @Specialization
         @TruffleBoundary
-        public TruffleObject javaClass(String clazz, boolean silent) {
+        public TruffleObject javaClass(TruffleObject obj, boolean silent) {
+            if (JavaInterop.isJavaObject(obj)) {
+                return JavaInterop.toJavaClass(obj);
+            }
+            throw error(RError.Message.GENERIC, "unsupported type " + obj.getClass().getName());
+        }
+
+        protected boolean isClass(Object obj) {
+            return obj != null && obj instanceof Class;
+        }
+
+        @Specialization(guards = {"isClass(clazz)", "clazz.equals(cachedClazz)"}, limit = "10")
+        public TruffleObject javaClassCached(String clazz, boolean silent,
+                        @Cached("clazz") String cachedClazz,
+                        @Cached("getJavaClass(clazz, silent)") Object result,
+                        @Cached("create()") BranchProfile interopExceptionProfile) {
+            return javaClassToTruffleObject(clazz, result, interopExceptionProfile);
+        }
+
+        @Specialization(replaces = "javaClassCached")
+        public TruffleObject javaClass(String clazz, boolean silent,
+                        @Cached("create()") BranchProfile interopExceptionProfile) {
+            Object result = getJavaClass(clazz, silent);
+            return javaClassToTruffleObject(clazz, result, interopExceptionProfile);
+        }
+
+        @TruffleBoundary
+        private TruffleObject javaClassToTruffleObject(String clazz, Object result, BranchProfile interopExceptionProfile) {
+            if (result == RNull.instance) {
+                return RNull.instance;
+            }
+            if (result instanceof Class<?>) {
+                return JavaInterop.asTruffleObject(result);
+            } else if (result == accessError) {
+                CompilerDirectives.transferToInterpreter();
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + clazz);
+            } else {
+                interopExceptionProfile.enter();
+                if (result instanceof RuntimeException) {
+                    throw RError.handleInteropException(this, (RuntimeException) result);
+                } else {
+                    assert result instanceof Throwable;
+                    throw RError.handleInteropException(this, new RuntimeException((Throwable) result));
+                }
+            }
+        }
+
+        protected static Object getJavaClass(String className, boolean silent) {
+            Class<?> clazz = getPrimitiveClass(className);
+            if (clazz != null) {
+                return clazz;
+            }
+            return loadClass(className, silent);
+        }
+
+        @TruffleBoundary
+        private static Object loadClass(String clazz, boolean silent) {
             try {
-                return JavaInterop.asTruffleObject(RContext.getInstance().loadClass(clazz.replaceAll("/", ".")));
-            } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) {
+                Class<?> result = RContext.getInstance().loadClass(clazz);
+                if (result == null) {
+                    // not found
+                    if (silent) {
+                        return RNull.instance;
+                    } else {
+                        return new ClassNotFoundException(clazz + " not found");
+                    }
+                }
+                return result;
+            } catch (SecurityException | IllegalArgumentException e) {
+                return accessError;
+            } catch (RuntimeException e) {
                 if (silent) {
                     return RNull.instance;
                 }
-                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+                return e;
             }
         }
     }
@@ -529,31 +600,57 @@ public class FastRInterop {
         }
     }
 
+    @RBuiltin(name = "java.classpath", visibility = ON, kind = PRIMITIVE, parameterNames = {}, behavior = COMPLEX)
+    public abstract static class JavaClasspath extends RBuiltinNode.Arg0 {
+
+        static {
+            Casts.noCasts(JavaClasspath.class);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public RAbstractStringVector getEntries() {
+            RContext ctx = RContext.getInstance();
+            String[] paths = ctx.getInteropClasspathEntries();
+            return RDataFactory.createStringVector(paths, true);
+        }
+    }
+
     @ImportStatic({RRuntime.class})
-    @RBuiltin(name = "java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX)
-    public abstract static class JavaClassName extends RBuiltinNode.Arg1 {
+    @RBuiltin(name = "java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj", "getClassName"}, behavior = COMPLEX)
+    public abstract static class JavaClassName extends RBuiltinNode.Arg2 {
 
         static {
-            Casts.noCasts(JavaClassName.class);
+            Casts casts = new Casts(JavaClassName.class);
+            casts.arg("getClassName").mapMissing(Predef.constant(RRuntime.LOGICAL_FALSE)).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
+                            notLogicalNA()).map(Predef.toBoolean());
         }
 
         @Specialization(guards = {"isJavaObject(obj)"})
         @TruffleBoundary
-        public Object javaClassName(TruffleObject obj) {
-            Object o = JavaInterop.asJavaObject(Object.class, obj);
-            if (o == null) {
-                return RNull.instance;
+        public Object javaClassName(Object obj, boolean getClassName) {
+            if (isJavaObject(obj)) {
+                Object o = JavaInterop.asJavaObject(Object.class, (TruffleObject) obj);
+                if (o == null) {
+                    return RNull.instance;
+                }
+                if (getClassName && o instanceof Class) {
+                    return ((Class<?>) o).getName();
+                }
+                return o.getClass().getName();
+            } else {
+                throw error(RError.Message.GENERIC, "unsupported type " + obj.getClass().getName());
             }
-            return o.getClass().getName();
         }
 
-        protected boolean isJavaObject(TruffleObject obj) {
-            return JavaInterop.isJavaObject(obj);
+        protected boolean isJavaObject(Object obj) {
+            return RRuntime.isForeignObject(obj) && JavaInterop.isJavaObject(obj);
         }
 
         @Fallback
-        public String javaClassName(@SuppressWarnings("unused") Object obj) {
-            throw error(RError.Message.GENERIC, "unsupported type");
+        public String javaClassName(@SuppressWarnings("unused") Object obj,
+                        @SuppressWarnings("unused") Object getClassName) {
+            throw error(RError.Message.GENERIC, "unsupported type " + obj.getClass().getName());
         }
     }
 
@@ -566,7 +663,6 @@ public class FastRInterop {
         }
 
         @Specialization(guards = {"isForeignObject(obj)"})
-        @TruffleBoundary
         public byte isArray(TruffleObject obj,
                         @Cached("HAS_SIZE.createNode()") Node hasSize) {
             return RRuntime.asLogical(ForeignAccess.sendHasSize(hasSize, obj));
@@ -578,6 +674,194 @@ public class FastRInterop {
         }
     }
 
+    @RBuiltin(name = ".fastr.interop.getJavaClass", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
+    public abstract static class GetJavaClass extends RBuiltinNode.Arg1 {
+
+        static {
+            Casts.noCasts(GetJavaClass.class);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public TruffleObject javaClass(TruffleObject obj) {
+            if (JavaInterop.isJavaObject(obj)) {
+                return JavaInterop.toJavaClass(obj);
+            }
+            throw error(RError.Message.GENERIC, "unsupported type " + obj.getClass().getName());
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.isIdentical", visibility = ON, kind = PRIMITIVE, parameterNames = {"x1", "x2"}, behavior = COMPLEX)
+    public abstract static class JavaIsIdentical extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts.noCasts(JavaIsIdentical.class);
+        }
+
+        @Specialization(guards = {"isJavaObject(x1)", "isJavaObject(x2)"})
+        public byte isIdentical(TruffleObject x1, TruffleObject x2) {
+            return RRuntime.asLogical(JavaInterop.asJavaObject(Object.class, x1) == JavaInterop.asJavaObject(Object.class, x2));
+        }
+
+        @Fallback
+        @TruffleBoundary
+        public byte isIdentical(@SuppressWarnings("unused") Object x1, @SuppressWarnings("unused") Object x2) {
+            throw error(RError.Message.GENERIC, String.format("unsupported types: %s, %s", x1.getClass().getName(), x2.getClass().getName()));
+        }
+
+        protected boolean isJavaObject(TruffleObject obj) {
+            return JavaInterop.isJavaObject(obj);
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.asJavaTruffleObject", visibility = ON, kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
+    public abstract static class JavaAsTruffleObject extends RBuiltinNode.Arg1 {
+
+        static {
+            Casts.noCasts(JavaAsTruffleObject.class);
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(byte b) {
+            return JavaInterop.asTruffleObject(RRuntime.fromLogical(b));
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(int i) {
+            return JavaInterop.asTruffleObject(i);
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(double d) {
+            return JavaInterop.asTruffleObject(d);
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(String s) {
+            return JavaInterop.asTruffleObject(s);
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(RInteropByte b) {
+            return JavaInterop.asTruffleObject(b.getValue());
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(RInteropChar c) {
+            return JavaInterop.asTruffleObject(c.getValue());
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(RInteropFloat f) {
+            return JavaInterop.asTruffleObject(f.getValue());
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(RInteropLong l) {
+            return JavaInterop.asTruffleObject(l.getValue());
+        }
+
+        @Specialization
+        public TruffleObject asTruffleObject(RInteropShort s) {
+            return JavaInterop.asTruffleObject(s.getValue());
+        }
+
+        @Fallback
+        @TruffleBoundary
+        public byte asTruffleObject(@SuppressWarnings("unused") Object x) {
+            throw error(RError.Message.GENERIC, String.format("unsupported type: %s", x.getClass().getName()));
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.isAssignableFrom", visibility = ON, kind = PRIMITIVE, parameterNames = {"x1", "x2"}, behavior = COMPLEX)
+    public abstract static class JavaIsAssignableFrom extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts.noCasts(JavaIsAssignableFrom.class);
+        }
+
+        @Specialization(guards = {"isJavaObject(x1)", "isJavaObject(x2)"})
+        public byte isAssignable(TruffleObject x1, TruffleObject x2) {
+            Object jo1 = JavaInterop.asJavaObject(Object.class, x1);
+            Class<?> cl1 = (jo1 instanceof Class) ? (Class<?>) jo1 : jo1.getClass();
+            Object jo2 = JavaInterop.asJavaObject(Object.class, x2);
+            Class<?> cl2 = (jo2 instanceof Class) ? (Class<?>) jo2 : jo2.getClass();
+            return RRuntime.asLogical(cl2.isAssignableFrom(cl1));
+        }
+
+        @Fallback
+        @TruffleBoundary
+        public byte isAssignable(@SuppressWarnings("unused") Object x1, @SuppressWarnings("unused") Object x2) {
+            throw error(RError.Message.GENERIC, String.format("unsupported types: %s, %s", x1.getClass().getName(), x2.getClass().getName()));
+        }
+
+        protected boolean isJavaObject(TruffleObject obj) {
+            return JavaInterop.isJavaObject(obj);
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.isInstance", visibility = ON, kind = PRIMITIVE, parameterNames = {"x1", "x2"}, behavior = COMPLEX)
+    public abstract static class JavaIsInstance extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts.noCasts(JavaIsInstance.class);
+        }
+
+        @Specialization(guards = {"isJavaObject(x1)", "isJavaObject(x2)"})
+        public byte isInstance(TruffleObject x1, TruffleObject x2) {
+            Object jo1 = JavaInterop.asJavaObject(Object.class, x1);
+            Object jo2 = JavaInterop.asJavaObject(Object.class, x2);
+            if (jo1 instanceof Class) {
+                Class<?> cl1 = (Class<?>) jo1;
+                return RRuntime.asLogical(cl1.isInstance(jo2));
+            }
+            return RRuntime.asLogical(jo1.getClass().isInstance(jo2));
+        }
+
+        @Specialization(guards = {"isJavaObject(x1)"})
+        public byte isInstance(TruffleObject x1, RInteropScalar x2,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+            Object jo1 = JavaInterop.asJavaObject(Object.class, x1);
+            if (jo1 instanceof Class) {
+                Class<?> cl1 = (Class<?>) jo1;
+                return RRuntime.asLogical(cl1.isInstance(r2Foreign.execute(x2)));
+            }
+            return RRuntime.asLogical(jo1.getClass().isInstance(x2));
+        }
+
+        @Specialization(guards = {"isJavaObject(x1)", "!isJavaObject(x2)", "!isInterop(x2)"})
+        public byte isInstance(TruffleObject x1, Object x2) {
+            Object jo1 = JavaInterop.asJavaObject(Object.class, x1);
+            if (jo1 instanceof Class) {
+                Class<?> cl1 = (Class<?>) jo1;
+                return RRuntime.asLogical(cl1.isInstance(x2));
+            }
+            return RRuntime.asLogical(jo1.getClass().isInstance(x2));
+        }
+
+        @Fallback
+        @TruffleBoundary
+        public byte isInstance(@SuppressWarnings("unused") Object x1, @SuppressWarnings("unused") Object x2) {
+            throw error(RError.Message.GENERIC, String.format("unsupported types: %s, %s", x1.getClass().getName(), x2.getClass().getName()));
+        }
+
+        protected boolean isJavaObject(Object obj) {
+            return RRuntime.isForeignObject(obj) && JavaInterop.isJavaObject((TruffleObject) obj);
+        }
+
+        protected boolean isInterop(Object obj) {
+            return obj instanceof RInteropScalar;
+        }
+
+        protected R2Foreign createR2Foreign() {
+            return R2ForeignNodeGen.create();
+        }
+    }
+
     @RBuiltin(name = "new.java.array", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "dim"}, behavior = COMPLEX)
     public abstract static class NewJavaArray extends RBuiltinNode.Arg2 {
 
@@ -604,11 +888,11 @@ public class FastRInterop {
         }
 
         private Class<?> getClazz(String className) throws RError {
-            try {
-                return classForName(className);
-            } catch (ClassNotFoundException e) {
-                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            Class<?> result = classForName(className);
+            if (result == null) {
+                throw error(RError.Message.GENERIC, "cannot access Java class %s", className);
             }
+            return result;
         }
     }
 
@@ -648,7 +932,23 @@ public class FastRInterop {
         @Specialization
         @TruffleBoundary
         public Object toArray(RAbstractIntVector vec, String className, boolean flat) {
-            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+            return toArray(vec, flat, getClazz(className), (array, i) -> {
+                if (Byte.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (byte) vec.getDataAt(i));
+                } else if (Character.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (char) vec.getDataAt(i));
+                } else if (Double.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (double) vec.getDataAt(i));
+                } else if (Float.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (float) vec.getDataAt(i));
+                } else if (Long.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (long) vec.getDataAt(i));
+                } else if (Short.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (short) vec.getDataAt(i));
+                } else {
+                    Array.set(array, i, vec.getDataAt(i));
+                }
+            });
         }
 
         @Specialization
@@ -660,7 +960,23 @@ public class FastRInterop {
         @Specialization
         @TruffleBoundary
         public Object toArray(RAbstractDoubleVector vec, String className, boolean flat) {
-            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+            return toArray(vec, flat, getClazz(className), (array, i) -> {
+                if (Byte.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (byte) vec.getDataAt(i));
+                } else if (Character.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (char) vec.getDataAt(i));
+                } else if (Float.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (float) vec.getDataAt(i));
+                } else if (Integer.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (int) vec.getDataAt(i));
+                } else if (Long.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (long) vec.getDataAt(i));
+                } else if (Short.TYPE.getName().equals(className)) {
+                    Array.set(array, i, (short) vec.getDataAt(i));
+                } else {
+                    Array.set(array, i, vec.getDataAt(i));
+                }
+            });
         }
 
         @Specialization
@@ -691,14 +1007,14 @@ public class FastRInterop {
         @TruffleBoundary
         public Object toArray(RAbstractVector vec, @SuppressWarnings("unused") RMissing className, boolean flat,
                         @Cached("createR2Foreign()") R2Foreign r2Foreign) {
-            return toArray(vec, flat, Object.class, (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAtAsObject(i))));
+            return toArray(vec, flat, Object.class, r2Foreign);
         }
 
         @Specialization(guards = "!isJavaLikeVector(vec)")
         @TruffleBoundary
         public Object toArray(RAbstractVector vec, String className, boolean flat,
                         @Cached("createR2Foreign()") R2Foreign r2Foreign) {
-            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAtAsObject(i))));
+            return toArray(vec, flat, getClazz(className), r2Foreign);
         }
 
         @Specialization
@@ -747,6 +1063,26 @@ public class FastRInterop {
             return JavaInterop.asTruffleObject(array);
         }
 
+        private Object toArray(RAbstractVector vec, boolean flat, Class<?> clazz, R2Foreign r2Foreign) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+            int[] dims = getDim(flat, vec);
+            final Object array = Array.newInstance(clazz, dims);
+            TruffleObject truffleArray = JavaInterop.asTruffleObject(array);
+
+            for (int d = 0; d < dims.length; d++) {
+                int dim = dims[d];
+                // TODO works only for flat
+                for (int i = 0; i < dim; i++) {
+                    try {
+                        Object value = r2Foreign.execute(vec.getDataAtAsObject(i));
+                        ForeignAccess.sendWrite(Message.WRITE.createNode(), truffleArray, i, value);
+                    } catch (InteropException ex) {
+                        throw error(RError.Message.GENERIC, ex.getMessage());
+                    }
+                }
+            }
+            return truffleArray;
+        }
+
         private interface VecElementToArray {
             void toArray(Object array, Integer i);
         }
@@ -781,11 +1117,11 @@ public class FastRInterop {
         }
 
         private Class<?> getClazz(String className) throws RError {
-            try {
-                return classForName(className);
-            } catch (ClassNotFoundException e) {
-                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            Class<?> result = classForName(className);
+            if (result == null) {
+                throw error(RError.Message.GENERIC, "cannot access Java class %s", className);
             }
+            return result;
         }
 
         protected boolean isJavaObject(TruffleObject obj) {
@@ -802,30 +1138,32 @@ public class FastRInterop {
     }
 
     @ImportStatic({Message.class, RRuntime.class})
-    @RBuiltin(name = ".fastr.interop.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array"}, behavior = COMPLEX)
-    public abstract static class FromForeignArray extends RBuiltinNode.Arg1 {
+    @RBuiltin(name = ".fastr.interop.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array", "recursive"}, behavior = COMPLEX)
+    public abstract static class FromForeignArray extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(FromForeignArray.class);
             casts.arg("array").castForeignObjects(false).mustNotBeMissing();
+            casts.arg("recursive").mapMissing(Predef.constant(RRuntime.LOGICAL_FALSE)).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
+                            notLogicalNA()).map(Predef.toBoolean());
         }
 
         private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
 
         @Specialization(guards = {"isForeignObject(obj)"})
         @TruffleBoundary
-        public Object fromArray(TruffleObject obj,
+        public Object fromArray(TruffleObject obj, boolean recursive,
                         @Cached("HAS_SIZE.createNode()") Node hasSize,
                         @Cached("create()") ForeignArray2R array2R) {
             if (isArrayProfile.profile(ForeignAccess.sendHasSize(hasSize, obj))) {
-                return array2R.convert(obj);
+                return array2R.convert(obj, recursive);
             } else {
                 throw error(RError.Message.GENERIC, "not a java array");
             }
         }
 
         @Fallback
-        public Object fromObject(@SuppressWarnings("unused") Object obj) {
+        public Object fromObject(@SuppressWarnings("unused") Object obj, @SuppressWarnings("unused") Object recursive) {
             throw error(RError.Message.GENERIC, "not a java array");
         }
     }
@@ -884,32 +1222,33 @@ public class FastRInterop {
         }
     }
 
-    private static Class<?> classForName(String className) throws ClassNotFoundException {
-        if (className.equals(Byte.TYPE.getName())) {
-            return Byte.TYPE;
+    private static Class<?> classForName(String className) {
+        Class<?> clazz = getPrimitiveClass(className);
+        if (clazz != null) {
+            return clazz;
         }
-        if (className.equals(Boolean.TYPE.getName())) {
+        return RContext.getInstance().loadClass(className);
+    }
+
+    private static Class<?> getPrimitiveClass(String className) {
+        if (Boolean.TYPE.getName().equals(className)) {
             return Boolean.TYPE;
-        }
-        if (className.equals(Character.TYPE.getName())) {
+        } else if (Byte.TYPE.getName().equals(className)) {
+            return Byte.TYPE;
+        } else if (Character.TYPE.getName().equals(className)) {
             return Character.TYPE;
-        }
-        if (className.equals(Double.TYPE.getName())) {
+        } else if (Double.TYPE.getName().equals(className)) {
             return Double.TYPE;
-        }
-        if (className.equals(Float.TYPE.getName())) {
+        } else if (Float.TYPE.getName().equals(className)) {
             return Float.TYPE;
-        }
-        if (className.equals(Integer.TYPE.getName())) {
+        } else if (Integer.TYPE.getName().equals(className)) {
             return Integer.TYPE;
-        }
-        if (className.equals(Long.TYPE.getName())) {
+        } else if (Long.TYPE.getName().equals(className)) {
             return Long.TYPE;
-        }
-        if (className.equals(Short.TYPE.getName())) {
+        } else if (Short.TYPE.getName().equals(className)) {
             return Short.TYPE;
         }
-        return Class.forName(className);
+        return null;
     }
 
     @RBuiltin(name = "do.call.external", visibility = ON, kind = PRIMITIVE, parameterNames = {"receiver", "what", "args"}, behavior = COMPLEX)
@@ -970,16 +1309,15 @@ public class FastRInterop {
 
         @Specialization
         public Object tryFunc(VirtualFrame frame, RFunction function, byte check) {
-            boolean isCheck = RRuntime.fromLogical(check);
             getInteropTryState().stepIn();
             try {
                 return call.call(frame, function, RArgsValuesAndNames.EMPTY);
             } catch (FastRInteropTryException e) {
-                Throwable cause = e.getCause();
                 CompilerDirectives.transferToInterpreter();
-                if (cause instanceof TruffleException) {
+                Throwable cause = e.getCause();
+                if (cause instanceof TruffleException || cause.getCause() instanceof ClassNotFoundException) {
                     cause = cause.getCause();
-                    if (isCheck) {
+                    if (RRuntime.fromLogical(check)) {
                         String causeName = cause.getClass().getName();
                         String msg = cause.getMessage();
                         msg = msg != null ? String.format("%s: %s", causeName, msg) : causeName;
@@ -998,6 +1336,40 @@ public class FastRInterop {
 
     }
 
+    @RBuiltin(name = ".fastr.interop.checkException", kind = PRIMITIVE, parameterNames = {"silent", "showCallerOf"}, behavior = COMPLEX)
+    public abstract static class FastRInteropCheckException extends RBuiltinNode.Arg2 {
+        static {
+            Casts casts = new Casts(FastRInteropCheckException.class);
+            casts.arg("silent").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst();
+            casts.arg("showCallerOf").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        }
+
+        @Specialization
+        public Object getException(VirtualFrame frame, byte silent, RMissing callerFor) {
+            return getException(frame, silent, (String) null);
+        }
+
+        @Specialization
+        public Object getException(VirtualFrame frame, byte silent, String showCallerOf) {
+            Throwable t = getInteropTryState().lastException;
+            if (t != null) {
+                CompilerDirectives.transferToInterpreter();
+                getInteropTryState().lastException = null;
+                if (!RRuntime.fromLogical(silent)) {
+                    String causeName = t.getClass().getName();
+                    String msg = t.getMessage();
+                    msg = msg != null ? String.format("%s: %s", causeName, msg) : causeName;
+                    if (showCallerOf == null) {
+                        throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, msg);
+                    } else {
+                        throw RError.error(new RError.ShowCallerOf(showCallerOf), RError.Message.GENERIC, msg);
+                    }
+                }
+            }
+            return RNull.instance;
+        }
+    }
+
     @RBuiltin(name = ".fastr.interop.getTryException", kind = PRIMITIVE, parameterNames = {"clear"}, behavior = COMPLEX)
     public abstract static class FastRInteropGetException extends RBuiltinNode.Arg1 {
         static {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
index d52436f13ffcd2a8cfbc91a5a16d5ed68538cb99..687c4fce806f0fd1f3ea91763bb59686e0962052 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.casts;
 
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 
 public final class CastForeignNode extends CastNode {
@@ -31,13 +32,20 @@ public final class CastForeignNode extends CastNode {
     @Child private ForeignArray2R foreignArray2R = ForeignArray2R.create();
 
     private final ConditionProfile isForeign = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile isInteropScalar = ConditionProfile.createBinaryProfile();
 
     @Override
     protected Object execute(Object obj) {
         if (isForeign.profile(foreignArray2R.isForeignVector(obj))) {
             return foreignArray2R.convert(obj);
+        } else if (isInteropScalar.profile(isInteropScalar(obj))) {
+            return ((RInteropScalar) obj).getRValue();
         } else {
             return obj;
         }
     }
+
+    protected boolean isInteropScalar(Object obj) {
+        return obj instanceof RInteropScalar;
+    }
 }
diff --git a/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
index 22b6b722cc2bf4bf2c7ee8830d129ea8a50f8272..0b4abc2eee6b3735f3d1183742ac54753fbfc852 100644
--- a/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
+++ b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
@@ -6,6 +6,4 @@ Date: 2017-05-18
 Author: Tomas Stupka
 Maintainer: Tomas Stupka <tomas.stupka@oracle.com>
 Description: Provides rJava R interface backed by FastR interoperability builtins.
-License: GPL-2
-Suggests: testthat
-RoxygenNote: 6.0.1
+License: GPL-2
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
index b3ee338a3a3c9097a7fd84c642938fbe94438e60..1ff4c9f1c729643a9258e633e40dccda29fd070f 100644
--- a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
+++ b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
@@ -1,27 +1,49 @@
-# Generated by roxygen2: do not edit by hand
-
-export(.jaddClassPath)
-export(.jaddLibrary)
-export(.jarray)
-export(.jbyte)
-export(.jcall)
-export(.jcast)
-export(.jchar)
-export(.jcheck)
-export(.jclear)
-export(.jevalArray)
-export(.jfield)
-export(.jfindClass)
-export(.jfloat)
-export(.jgetEx)
-export(.jinit)
-export(.jlong)
-export(.jnew)
-export(.jnull)
-export(.jpackage)
-export(.jshort)
-export(.jsimplify)
-export(.jstrVal)
-export(.jthrow)
-export(J)
-export(is.jnull)
+exportPattern("^\\.j")
+export( "J" )
+export( "%instanceof%" )
+
+export( clone )
+S3method( clone, default ) 
+export(is.jnull, .rJava.base.path)
+exportClasses(jobjRef, jarrayRef, jrectRef, jfloat, jlong, jbyte, jchar, jclassName)
+exportMethods(show, "$", "$<-", 
+	"==", "!=", "<", ">", "<=", ">=", 
+	names, new, as.character, length, head, tail, 
+	"[", "[[", "[[<-", str, "dim<-", 
+	unique, duplicated, anyDuplicated, 
+	sort, rev, 
+	min, max, range, 
+	rep, 
+	clone )
+import(methods)
+importFrom(utils,head)
+importFrom(utils,tail)
+importFrom(utils,str)
+importFrom(utils, assignInNamespace)
+
+S3method(with, jobjRef)
+S3method(with, jarrayRef)
+S3method(with, jclassName)
+
+S3method(within, jobjRef)
+S3method(within, jarrayRef)
+S3method(within, jclassName)
+
+# within requires that with.jobjRef is visible outside
+export(with.jobjRef)
+
+if( exists( ".DollarNames", asNamespace("utils") ) ) importFrom( utils, .DollarNames )
+S3method(.DollarNames, jobjRef)
+S3method(.DollarNames, jarrayRef)
+S3method(.DollarNames, jrectRef)
+S3method(.DollarNames, jclassName)
+
+S3method( as.list, jobjRef )
+S3method( as.list, jarrayRef )
+S3method( as.list, jrectRef )
+
+S3method( "$", "Throwable" )
+S3method( "$<-", "Throwable" )
+
+export( javaImport )
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/0classes.R b/com.oracle.truffle.r.pkgs/rJava/R/0classes.R
new file mode 100644
index 0000000000000000000000000000000000000000..1a877b5fa014b4688a3a5c70d20adf2cff0ee106
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/0classes.R
@@ -0,0 +1,62 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018 Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## S4 classes (jobjRef is re-defined in .First.lib to contain valid jobj)                                                                                                  
+#' java object reference
+setClass("jobjRef", representation(jobj="externalptr", jclass="character"), 
+	prototype=list(jobj=NULL, jclass="java/lang/Object"))
+
+#' rugged arrays
+setClass("jarrayRef", representation("jobjRef", jsig="character"))
+
+#' rectangular java arrays double[][] d = new double[m][n]
+setClass("jrectRef", 
+	representation("jarrayRef", dimension="integer" ) ) 
+
+
+
+# we extend array here so that we can keep dimensions
+# in the helper functions below, the storage mode is 
+# set when the objects are built
+# TODO: maybe an initialize method is needed here
+# TODO: maybe a validate method is needed here as well
+setClass("jfloat", representation("array" ) )
+setClass("jlong", representation("array" )  )
+setClass("jbyte", representation("array" )  )
+setClass("jshort", representation("array" ) )
+setClass("jchar", representation("array" )  )
+
+# there is no way to distinguish between double and float in R, so we need to mark floats specifically
+.jfloat <- function(x) {
+	storage.mode( x ) <- "double"
+	new("jfloat", x )
+}
+# the same applies to long
+.jlong <- function(x) {
+	storage.mode( x ) <- "double"
+	new("jlong", x)
+}
+# and byte
+.jbyte <- function(x) {
+	storage.mode( x ) <- "integer"
+	new("jbyte", x)
+}
+# and short
+.jshort <- function(x){
+	storage.mode( x ) <- "integer"
+	new("jshort", x)
+}
+# and char (experimental)
+.jchar <- function(x){
+	storage.mode( x ) <- "integer"
+	new("jchar", as.integer(x))
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/J.R b/com.oracle.truffle.r.pkgs/rJava/R/J.R
new file mode 100644
index 0000000000000000000000000000000000000000..59cb21061c77ce7e8f5dd8c2dc9e50979ec3297f
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/J.R
@@ -0,0 +1,52 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+setClass("jclassName", representation(name="character", jobj="jobjRef"))
+jclassName <- function(class){
+	if( is( class, "jobjRef" ) && .jinherits(class, "java/lang/Class" ) ){
+		jobj <- class
+		name <- .jcall( class, "Ljava/lang/String;", "getName", evalString = TRUE )
+	} else{
+		name <- gsub("/",".",as.character(class))
+		jobj <- .jfindClass(as.character(class))
+	}
+	new("jclassName", name=name, jobj=jobj)
+}
+
+setGeneric("new")
+setMethod("new", signature(Class="jclassName"), function(Class, ...) .J(Class@name, ...))
+
+setMethod("$", c(x="jclassName"), function(x, name) {
+	if( name == "class" ){
+		x@jobj
+	} else if (classHasField(x@jobj, name, TRUE)){
+		.jfield(x@name, , name) 
+	} else if (classHasMethod(x@jobj, name, TRUE)){
+		function(...) .jrcall(x@name, name, ...) 
+	} else if( classHasClass(x@jobj, name, FALSE) ){
+		inner.cl <- .jcall( "RJavaTools", "Ljava/lang/Class;", "getClass", x@jobj, name, FALSE ) 
+		new("jclassName", name=.jcall(inner.cl, "S", "getName"), jobj=inner.cl)
+	} else {
+		stop("no static field, method or inner class called `", name, "' in `", x@name, "'")
+	}
+})
+setMethod("$<-", c(x="jclassName"), function(x, name, value) {    
+    .jfield(x@jobj, name) <- value
+    # FASTR <<<<<
+    # Fix: return x, otherwise LHS of $<- is overriden with 
+    # the result of .jfield(x@jobj, name) <- value which is the field value
+    x
+})
+setMethod("show", c(object="jclassName"), function(object) invisible(show(paste("Java-Class-Name:",object@name))))
+setMethod("as.character", c(x="jclassName"), function(x, ...) x@name)
+
+## the magic `J'
+J<-function(class, method, ...) if (nargs() == 1L && missing(method)) jclassName(class) else .jrcall(class, method, ...)
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/arrays.R b/com.oracle.truffle.r.pkgs/rJava/R/arrays.R
new file mode 100644
index 0000000000000000000000000000000000000000..2d4b1f6108a4d73a9bfc6ba93c5c7abc6bf05269
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/arrays.R
@@ -0,0 +1,736 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+# :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1:
+ 
+# {{{ utilities to deal with arrays
+#' Indicates if a object refers to a java array
+#' 
+#' @param o object 
+#' @return TRUE if the object is a java array, FALSE if not
+#'         (including when the object is not even a java reference)
+isJavaArray <- function( o ){
+	if( ( is( o, "jobjRef" ) || is( o, "jarrayRef") || is( o, "jrectRef") ) && !is.jnull(o) ){
+		.jcall( "RJavaArrayTools", "Z", "isArray", .jcast(o) )
+	} else FALSE
+}
+._must_be_java_array <- function( o, message = "object is not a java array" ){
+	if( !isJavaArray(o ) ){
+		stop( message )
+	}
+}
+isJavaArraySignature <- function( sig ){
+	identical( substr( sig, 1, 1 ), '[' )
+}
+
+#' get the component type of a java array
+getComponentType <- function( o, check = TRUE ){
+	if( check ) ._must_be_java_array( o )
+	.jcall( .jcall( o, "Ljava/lang/Class;", "getClass" ), "Ljava/lang/Class;", "getComponentType" )
+}
+
+._jarray_simplify <- function( x ){
+	._must_be_java_array( x )
+	clname <- .jclass(x, true = TRUE )
+	
+	Array <- "java/lang/reflect/Array"
+	obj <- switch( clname, 
+		# deal with array of primitive first
+		"[I"                  = .Call(RgetIntArrayCont   , x@jobj), 
+		"[J"                  = .Call(RgetLongArrayCont  , x@jobj), 
+		"[Z"                  = .Call(RgetBoolArrayCont  , x@jobj) , 
+		"[B"                  = .Call(RgetByteArrayCont  , x@jobj) ,
+		"[D"                  = .Call(RgetDoubleArrayCont, x@jobj) ,
+		"[S"                  = .Call(RgetShortArrayCont , x@jobj) , 
+		"[C"                  = .Call(RgetCharArrayCont  , x@jobj) ,
+		"[F"                  = .Call(RgetFloatArrayCont , x@jobj) , 
+		"[Ljava.lang.String;" = .Call(RgetStringArrayCont, x@jobj),
+		
+		# otherwise, just get the object
+		x )
+	obj
+}
+# }}}
+
+# {{{ length
+#' get the length of the array
+._length_java_array <- function(x){
+	if( isJavaArray( x ) ){
+		.jcall( "java/lang/reflect/Array", "I", "getLength", .jcast( x, check = FALSE, convert.array = FALSE) ) 
+	} else{
+		stop( "the supplied object is not a java array" ) 
+	}
+}
+
+setMethod( "length", "jarrayRef", ._length_java_array )
+setMethod( "length", "jrectRef", ._length_java_array )
+
+setGeneric( "str" )
+setMethod("str", "jarrayRef", function(object, ...){
+	txt <- sprintf( "Formal class 'jarrayRef' [package \"rJava\"] with 2 slots
+  ..@ jobj  :<externalptr>
+  ..@ jclass: chr \"%s\"
+  ..@ jsig  : chr \"%s\"
+", object@jclass, object@jsig )
+    cat( txt )
+} )
+setMethod("str", "jrectRef", function(object, ...){
+	dim <- object@dimension
+	dim.txt <- if( length( dim ) == 1L ){
+		sprintf( "int %d", dim )
+	} else {
+		sprintf( "int[1:%d] %s", length(dim), paste( if( length(dim) > 6 ) c( dim[1:6], "...") else dim, collapse = " ") )
+	}
+	txt <- sprintf( "Formal class 'jrectRef' [package \"rJava\"] with 2 slots
+  ..@ jobj     :<externalptr>
+  ..@ jclass   : chr \"%s\"
+  ..@ jsig     : chr \"%s\"
+  ..@ dimension: %s
+", object@jclass, object@jsig, dim.txt )
+    cat( txt )
+} )
+# }}}
+
+# {{{ single bracket indexing : [
+
+# indexing of .jarrayRef
+# is is not quite clear what the proper result should be, because technically
+# [ should always return a jarrayRef, but it's not the most useful thing to do.
+# the code below (ab)uses drop to try to deal with that, but it's not optimal ... 
+
+# ._jctype <- function(x) if (is.jnull(x)) NA else if(is(x, "jarrayRef")) x@jsig else paste("L", x@jclass, ";", sep='')
+
+# #' index a java array
+# #' 
+# #' @param x a reference to a java array
+# #' @param i indexer (only 1D indexing supported so far)
+# #' @param drop if the result if of length 1, just return the java object instead of an array of length one
+# #' @param simplify further simplify the result
+# ._java_array_single_indexer <- function( x, i, j, drop, simplify = FALSE, silent = FALSE, ... ){
+# 	# arrays only
+# 	
+# 	if( !silent ){
+# 		if( ! missing( j ) ){
+# 			warning( "only one dimensional indexing is currently supported in i, ignoring j argument" )
+# 		}
+# 		dots <- list( ... )
+# 		if( length(dots) ){
+# 			unnamed.dots <- dots[ names(dots) == "" ]
+# 			if( length( unnamed.dots ) ){
+# 				warning( "only one dimensional indexing is currently supported in [, ignoring ... arguments" ) 
+# 			}
+# 		}
+# 	}
+# 	
+# 	# the component type of the array - maybe used to make 
+# 	# arrays with the same component type, but of length 0
+# 	component.type <- getComponentType( x, check = FALSE )
+# 	
+# 	# 'eval' the array
+# 	ja <- .jevalArray( x )
+# 	
+# 	# native type - use R subsetting and maybe remap to java 
+# 	if (!is.list(ja)) { 
+# 		# perform the subset
+# 		o <- ja[i]
+# 		
+# 		# return native type if simplify
+# 		if( simplify ){
+# 			return(o) 
+# 		}
+# 		
+# 		if( length(o) == 0L) {
+# 				# return an array of the same component type as the original array
+# 				# but of length 0
+# 				return( .jcall( "java/lang/reflect/Array", "Ljava/lang/Object;", "newInstance", component.type, 0L  ) )
+# 		} else {
+# 			# drop makes no sense here
+# 			return( .jarray( o ) )
+# 		}
+# 	}
+# 	
+# 	# the result an array of java objects
+# 	sl <- ja[i]
+# 	
+# 	if( length( sl ) == 0L ){
+# 		# TODO: make simplify influencial here
+# 		#       for example if x is int[] then we want to get integer(0)
+# 		return( .jcall( "java/lang/reflect/Array", "Ljava/lang/Object;", "newInstance", component.type, 0L  ) )
+# 	} else{
+# 		# just return the array
+# 		return( .jarray( sl ) )
+# 	}
+# }
+
+# ## this is all weird - we need to distinguish between x[i] and x[i,] yet S4 fails to do so ...
+setMethod( "[", signature( x = "jarrayRef" ), 
+	function(x, i, j, ..., drop = FALSE){
+		# the code above is not good enough
+		.NotYetImplemented()
+	} )
+# }}}
+
+# {{{ double bracket indexing : [[
+._collectIndex <- function( i, j, ...){
+	dots <- list( ... )
+	unnamed.dots <- if( length( dots ) ){
+		dots[ names(dots) == "" ]
+	}
+	
+	firstInteger <- function(.) as.integer(.)[1]
+	firstIntegerOfEach <- function(.) sapply( ., firstInteger )
+	
+	index <- c( 
+		if( !missing(i) ) firstInteger(i), 
+		if( !missing(j) ) firstInteger(j), 
+		if( !is.null(unnamed.dots) && length(unnamed.dots) ) firstIntegerOfEach( unnamed.dots )
+		)
+}
+
+# R version of RJavaArrayTools#getDimensionLength
+# it only works on the signature so should be used with caution
+getDimensionLength <- function( x, true.class = TRUE ){
+	nchar( sub( "[^[]+", "", .jclass(x, true = true.class) ) )
+}
+
+# R version of RJavaArrayTools#getObjectTypeName
+getObjectTypeName <- function( x, true.class=TRUE){
+	sub( "^[[]*(.*);?$", "\\1", .jclass(x, true = true.class) )
+}
+
+._java_array_double_indexer <- function( x, i, j, ..., evalArray = FALSE, evalString = FALSE ){
+	# initial checks
+	._must_be_java_array( x )
+	index <- ._collectIndex( i, j, ... )
+	
+	if( !length(index) || is.null(index) ){
+		# return the full object
+		x
+	} else{
+		
+		# shift one left (java style indexing starts from 0 )
+		index <- index - 1L
+		depth <- getDimensionLength( x )
+		typename <- getObjectTypeName( x )
+		
+		if( length( index) == depth ){
+			# we need to dispatch primitive 
+			if( isPrimitiveTypeName( typename ) ){ 
+				res <- switch( typename, 
+					# deal with array of primitive first
+					"I"                  =  .jcall( "RJavaArrayTools", "I", "getInt"    , .jcast(x), index ) , 
+					"J"                  =  .jcall( "RJavaArrayTools", "J", "getLong"   , .jcast(x), index ) , 
+					"Z"                  =  .jcall( "RJavaArrayTools", "Z", "getBoolean", .jcast(x), index ) , 
+					"B"                  =  .jcall( "RJavaArrayTools", "B", "getByte"   , .jcast(x), index ) ,
+					"D"                  =  .jcall( "RJavaArrayTools", "D", "getDouble" , .jcast(x), index ) ,
+					"S"                  =  .jcall( "RJavaArrayTools", "S", "getShort"  , .jcast(x), index ) , 
+					"C"                  =  .jcall( "RJavaArrayTools", "C", "getChar"   , .jcast(x), index ) ,
+					"F"                  =  .jcall( "RJavaArrayTools", "F", "getFloat"  , .jcast(x), index ), 
+					stop( "wrong primitive" ) # should never happen 
+				)
+				return( res )
+			} 
+			
+		}
+		
+		# otherwise use the Object version
+		.jcall( "RJavaArrayTools", "Ljava/lang/Object;", "get",  .jcast(x), index, 
+			evalArray = evalArray, evalString = evalString ) 
+	}
+
+}
+
+# this is the only case that makes sense: i is an integer or a numeric of length one
+# we cannot use logical indexing or indexing by name because there is no such thing in java
+setMethod( "[[", signature( x = "jarrayRef" ), 
+	function(x, i, j, ...){
+		._java_array_double_indexer( x, i, j, ... )
+	} )
+
+._java_array_double_replacer <- function( x, i, j, ..., value ){
+	# initial checks
+	._must_be_java_array( x )
+	
+	index <- ._collectIndex( i, j, ... )
+	
+	if( !length(index) || is.null(index) ){
+		# allow for x[[]] <- value
+		newArray( value , simplify = FALSE )
+	} else{
+		jvalue <- ._java_valid_object( value )
+		if( ._isPrimitiveReference( value ) ){
+			# then use a primitive version
+			.jcall( "RJavaArrayTools", "V", "set",  .jcast(x),
+				index - 1L, value )  
+		} else{
+			# use the Object version
+			.jcall( "RJavaArrayTools", "V", "set",  .jcast(x),
+				index - 1L, .jcast( jvalue ) )
+			if( isJavaArray( jvalue ) ){
+				# rectangularity might have changed
+				# we have no choice but to reset the array
+				x <- newArray( jobj = x@jobj, signature = x@jsig )
+			}
+		}
+		x
+	}
+	
+}
+
+setReplaceMethod( "[[", signature( x = "jarrayRef" ), 
+function(x, i, j, ..., value ){
+	._java_array_double_replacer( x, i, j, ..., value = value)
+} )
+# }}}
+
+# {{{ head and tail
+setGeneric( "head" )
+setMethod("head", signature( x = "jarrayRef" ), function(x, n = 6L, ... ){
+	if( !isJavaArray( x ) ){
+		stop( "not a java array" )
+	}
+	# FIXME : this only makes sense for 1d arays
+	n_objs <- length(x)
+	if( abs( n ) >= n_objs ){
+		return( x )
+	}
+	len <- if( n > 0L ) n else n_objs + n
+	x[seq_len(n), ... ]
+} )
+
+setGeneric( "tail" )
+setMethod("tail", signature( x = "jarrayRef" ), function(x, n = 6L, ... ){
+	if( !isJavaArray( x ) ){
+		stop( "not a java array" )
+	}
+	# FIXME : this only makes sense for 1d arays
+	n_objs <- length(x)
+	if( abs( n ) >= n_objs ) return(x)
+	if( n < 0L){ 
+		n <- n_objs + n
+	}
+	return( x[ seq.int( n_objs-n+1, n_objs ) , ... ] )
+} )
+# }}}
+
+# {{{ newArray - dispatch to jarrayRef or jrectRef
+#' creates a new jarrayRef or jrectRef depending on the rectangularity
+#' of the array
+#' 
+#' @param o a jobjRef object
+#' @param simplify if TRUE and the result is a rectangular array 
+#' of primitives, simplify it to an R object
+newArray <- function( o, simplify = TRUE, jobj, signature ){
+	if( !missing(jobj) ){
+		o <- new("jobjRef", jobj = jobj, jclass = signature)
+	}
+	if( !isJavaArray( o ) ){
+		stop( "o does not refer to a java array" )
+	}
+	if( inherits( o, "jrectRef" ) ){
+		# no need to go further
+		return(o)
+	}
+	
+	clazz <- tojni( .jclass( o, true = TRUE ) )
+	wrapper <- .jnew("ArrayWrapper", .jcast(o) )
+	isRect <- .jcall( wrapper, "Z", "isRectangular" )
+	if( isRect ){
+		dims <- .jcall( wrapper, "[I", "getDimensions" )
+		
+		if( !simplify ){
+			# no need to go further down, return a reference 
+			return( new( "jrectRef", jobj = o@jobj, jsig = clazz, jclass = clazz, 
+				dimension = dims ) )
+		}
+		
+		isprim <- .jcall( wrapper, "Z", "isPrimitive" )
+		typename <- .jcall( wrapper, "Ljava/lang/String;", "getObjectTypeName" )
+		isstrings <- identical( typename, "java.lang.String" )
+		
+		if( !isprim && !isstrings ){
+			# cannot simplify, return a reference
+			return( new( "jrectRef", jobj = o@jobj, jsig = clazz, jclass = clazz, 
+				dimension = dims ) )
+		}
+		
+		if( isprim || isstrings ){
+			# array of java primitives, we can translate this to R array
+			out <- structure( switch( typename , 
+				"I"                = .jcall( wrapper, "[I"                 , "flat_int" ), 
+				"Z"                = .jcall( wrapper, "[Z"                 , "flat_boolean" ),
+				"B"                = .jcall( wrapper, "[B"                 , "flat_byte" ),
+				"J"                = .jlong( .jcall( wrapper, "[J"                 , "flat_long" ) ),
+				"S"                = .jshort( .jcall( wrapper, "[T"                 , "flat_short" ) ), # [T is remapped to [S in .jcall 
+				"D"                = .jcall( wrapper, "[D"                 , "flat_double" ),
+				"C"                = .jchar( .jcall( wrapper, "[C"                 , "flat_char" ) ),
+				"F"                = .jfloat( .jcall( wrapper, "[F"                 , "flat_float" ) ), 
+				"java.lang.String" = .jcall( wrapper, "[Ljava/lang/String;", "flat_String" ), 
+				stop( sprintf("cannot simplify type : ", typename) ) # this should not happen
+				), dim = dims )
+			return( out )
+		}
+		
+	} else {
+		# not a rectangular array -> jarrayRef
+		new( "jarrayRef", jobj = o@jobj, jsig = clazz, jclass = clazz ) 
+	}
+}
+# }}}
+
+# {{{ [ indexing of rectangular arrays
+setMethod( "[", signature( x = "jrectRef" ), 
+	function(x, i, j, ..., simplify = FALSE, drop = TRUE ){
+		
+		# first we extract th data as a flat (one dimensional) R array
+		# called 'flat'
+		
+		dim <- x@dimension
+		wrapper <- .jnew( "ArrayWrapper", .jcast(x) )
+		
+		typename <- .jcall( wrapper, "Ljava/lang/String;", "getObjectTypeName" )
+		isprim   <- .jcall( wrapper, "Z", "isPrimitive" )
+		
+		flat <- switch( typename, 
+			"I"                = .jcall( wrapper, "[I"                  , "flat_int"     , evalArray = TRUE ), 
+			"Z"                = .jcall( wrapper, "[Z"                  , "flat_boolean" , evalArray = TRUE ),
+			"B"                = .jcall( wrapper, "[B"                  , "flat_byte"    , evalArray = TRUE ),
+			"J"                = .jcall( wrapper, "[J"                  , "flat_long"    , evalArray = TRUE ),
+			"S"                = .jcall( wrapper, "[T"                  , "flat_short"   , evalArray = TRUE ), # [T is remapped to [S in .jcall 
+			"D"                = .jcall( wrapper, "[D"                  , "flat_double"  , evalArray = TRUE ),
+			"C"                = .jcall( wrapper, "[C"                  , "flat_char"    , evalArray = TRUE ) ,
+			"F"                = .jcall( wrapper, "[F"                  , "flat_float"   , evalArray = TRUE ), 
+			"java.lang.String" = .jcall( wrapper, "[Ljava/lang/String;" , "flat_String"  , evalArray = TRUE ), 
+			                     .jcall( wrapper, "[Ljava/lang/Object;" , "flat_Object"  , evalArray = TRUE ) )
+			                     
+        # then we give to flat the correct dimensions
+		if( length(dim) != 1L ){
+			 dim( flat ) <- dim
+		}
+		
+		# now we construct the call to '[' on flat.
+		# this call uses all the regular R indexing 
+		call <- match.call(  call = sys.call(sys.parent()) )
+		n.args <- nargs( )
+		
+		e <- as.list( call )[ -(1:2) ]
+		names.e <- names(e)
+		if( any( have.name <- (names.e != "") ) ){
+			# we need to extract drop and simplify
+			nam <- names.e[ have.name ]
+			if( !all( nam %in% c("simplify", "drop", "i", "j" ) ) ){
+				stop( "only 'drop' and 'simplify' are allowed as named arguments, they need to be written exactly" ) 
+			}
+		}
+		
+		if( missing(i) && missing(j) && all( names.e != "" ) ){
+			# special case with no indexing at all
+			actual.call <- sprintf( "flat[  , drop = %s ]", as.character(drop) )
+		} else if( !missing(i) && missing(j) && all( names.e != "" ) ){
+			# special case where there is only one index
+			actual.call <- sprintf( "flat[ %s , drop = %s ]", deparse(i), as.character(drop) ) 
+		} else{
+			# we need to be careful about the missing's
+			# we cannot just do things like list(...) because with missings
+			# it just does not work
+			actual.call <- "flat["
+			
+			itoken <- if( missing(i ) ) " " else deparse(i)
+			jtoken <- if( missing(j ) ) " " else deparse(j)
+			
+			actual.call <- sprintf( "flat[ %s , %s", itoken, jtoken )
+			
+			iii <- 1L
+			for( a in e ){
+				if( missing(a) ){
+					actual.call <- sprintf( "%s , ", actual.call )
+				} else if( have.name[iii] ) {
+					# we put both at the end
+				} else {
+					# not missing, not named
+					actual.call <- sprintf( "%s, %s", actual.call, deparse(a) )
+				}
+				iii <- iii + 1L 
+			}
+			actual.call <- sprintf( "%s, drop = %s ]", actual.call, as.character(drop) )
+		}
+		
+		# now we eval the call 
+		subs <- eval( parse( text = actual.call ) )
+		
+		# now if we need and can simplify it, we return the subsetted array as is
+		# otherwise, we rewrap it to java
+		if( simplify && (typename == "java.lang.String" || isprim ) ) subs else .jarray( subs, dispatch = TRUE )
+
+	} )
+# }}}
+
+# {{{ dim.jrectRef 
+setMethod( "dim", signature( x = "jrectRef" ), function(x) x@dimension )
+setReplaceMethod( "dim", signature( x = "jrectRef" ), function(x, value){
+	
+	expected_prod <- prod( x@dimension )
+	
+	if( is.null( value ) ){
+		value <- expected_prod
+	} else{
+		received_prod <- prod(value)
+		if( received_prod != expected_prod ){
+			stop( sprintf("dims [product %d] do not match the length of object [%d]", received_prod, expected_prod ) ) 
+		}
+	}
+	dim <- x@dimension
+	wrapper <- .jnew( "ArrayWrapper", .jcast(x) )
+	
+	typename <- .jcall( wrapper, "Ljava/lang/String;", "getObjectTypeName" )
+	
+	flat <- structure( 
+			switch( typename, 
+			"I"                = .jcall( wrapper, "[I"                  , "flat_int"     , evalArray = TRUE ), 
+			"Z"                = .jcall( wrapper, "[Z"                  , "flat_boolean" , evalArray = TRUE ),
+			"B"                = .jcall( wrapper, "[B"                  , "flat_byte"    , evalArray = TRUE ),
+			"J"                = .jcall( wrapper, "[J"                  , "flat_long"    , evalArray = TRUE ),
+			"S"                = .jcall( wrapper, "[T"                  , "flat_short"   , evalArray = TRUE ), # [T is remapped to [S in .jcall 
+			"D"                = .jcall( wrapper, "[D"                  , "flat_double"  , evalArray = TRUE ),
+			"C"                = .jcall( wrapper, "[C"                  , "flat_char"    , evalArray = TRUE ) ,
+			"F"                = .jcall( wrapper, "[F"                  , "flat_float"   , evalArray = TRUE ), 
+			"java.lang.String" = .jcall( wrapper, "[Ljava/lang/String;" , "flat_String"  , evalArray = TRUE ), 
+			                     .jcall( wrapper, "[Ljava/lang/Object;" , "flat_Object"  , evalArray = TRUE ) ) , 
+		dim = value )
+		                     
+	.jarray(flat, dispatch = TRUE)
+	
+} )
+# }}}
+
+PRIMITIVE_TYPES <- c( "I",  "Z",  "B",  "J",  "S",  "D",  "C",  "F" )
+isPrimitiveTypeName <- function( type, include.strings = TRUE ){
+	type %in% PRIMITIVE_TYPES || ( include.strings && identical( type, "java.lang.String" ) )
+}
+PRIMITIVE_TYPES_RX <- sprintf( "^[[]+[%s]$" , paste( PRIMITIVE_TYPES, collapse = "" ) )
+isPrimitiveArraySignature <- function( x, ... ){
+	regexpr( PRIMITIVE_TYPES_RX, x, ... ) > 0
+}
+isArraySignature <- function( x ){
+	substr( x, 1, 1 ) == "["
+}
+
+# {{{ unique.jarrayRef
+setGeneric( "unique" )
+._unique_jrectRef <- function( x, incomparables = FALSE, ...){
+	
+	dim <- x@dimension
+	
+	if( length( dim ) > 1L ){
+		stop( "'unique' only implemented for 1d array so far" )
+	}
+	
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		.jarray( unique( .jevalArray( x ) ), dispatch = TRUE )
+	} else{
+		.jcall( "RJavaArrayTools", "[Ljava/lang/Object;", "unique",
+			.jcast( x, "[Ljava/lang/Object;" ), evalArray = TRUE, simplify = TRUE )
+	}
+}
+
+setMethod( "unique", "jarrayRef", function(x, incomparables = FALSE, ...){
+	.NotYetImplemented()
+} )
+setMethod( "unique", "jrectRef", ._unique_jrectRef )
+# }}}
+
+# {{{ duplicated
+setGeneric( "duplicated" )
+._duplicated_jrectRef <- function( x, incomparables = FALSE, ...){
+	
+	dim <- x@dimension
+	
+	if( length( dim ) > 1L ){
+		stop( "'duplicated' only implemented for 1d array so far" )
+	}
+	
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		duplicated( .jevalArray( x ) )
+	} else{
+		.jcall( "RJavaArrayTools", "[Z", "duplicated",
+			.jcast( x, "[Ljava/lang/Object;" ), evalArray = TRUE )
+	}
+}
+setMethod( "duplicated", "jrectRef", ._duplicated_jrectRef )
+setMethod( "duplicated", "jarrayRef", function( x, incomparables = FALSE, ...){
+	.NotYetImplemented()
+})
+# }}}
+
+# {{{ anyDuplicated
+.base.has.anyDuplicated <- exists("anyDuplicated", asNamespace("base"))
+if (!.base.has.anyDuplicated) {
+	anyDuplicated <- function(x, incomparables = FALSE, ...) UseMethod("anyDuplicated")
+}
+setGeneric( "anyDuplicated" )
+._anyduplicated_jrectRef <- function( x, incomparables = FALSE, ...){
+	
+	dim <- x@dimension
+	if( length( dim ) > 1L ){
+		stop( "'anyDuplicated' only implemented for 1d array so far" )
+	}
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		anyDuplicated( .jevalArray( x ) )
+	} else{
+		.jcall( "RJavaArrayTools", "I", "anyDuplicated",
+			.jcast( x, "[Ljava/lang/Object;" ), evalArray = TRUE ) + 1L
+	}
+}
+setMethod( "anyDuplicated", "jrectRef", ._anyduplicated_jrectRef )
+setMethod( "anyDuplicated", "jarrayRef", function( x, incomparables = FALSE, ...){
+	.NotYetImplemented()
+})
+# }}}
+
+# {{{ flat
+#' utility to flatten an array
+flat <- function(x, simplify = FALSE){
+	stop( "undefined" ) 
+}
+setGeneric( "flat")
+._flat_jrectRef <- function( x, simplify = FALSE ){
+	dim <- dim(x)
+	if( length(dim) == 1L ) {
+		if( !simplify) x else x[ simplify = TRUE ]
+	} else {
+		x[ seq_len(prod(dim)), drop = TRUE, simplify = simplify ]
+	}
+}
+setMethod( "flat", "jrectRef", ._flat_jrectRef )
+setMethod( "flat", "jarrayRef", function(x, simplify=FALSE){
+	.NotYetImplemented()
+} )
+# }}}
+
+# {{{ sort
+setGeneric( "sort" )
+._sort_jrectRef <- function( x, decreasing = FALSE, ...){
+	
+	x <- flat( x ) 
+	dim <- x@dimension
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		.jarray( sort( .jevalArray( x ), decreasing = decreasing ), dispatch = TRUE )
+	} else{
+		.jcall( "RJavaArrayTools", "[Ljava/lang/Object;", "sort",
+			.jcast( x, "[Ljava/lang/Object;" ), decreasing, evalArray = TRUE, simplify = TRUE )
+	}
+
+}
+setMethod( "sort", "jrectRef", ._sort_jrectRef )
+setMethod( "sort", "jarrayRef", function(x, decreasing=FALSE, ...){
+	.NotYetImplemented()
+})
+# }}}
+
+# {{{ rev
+setGeneric( "rev" )
+setMethod( "rev", "jrectRef", function(x){
+	x <- flat( x ) 
+	dim <- x@dimension
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		.jarray( rev( .jevalArray( x ) ), dispatch = TRUE )
+	} else{
+		.jcall( "RJavaArrayTools", "[Ljava/lang/Object;", "rev",
+			.jcast( x, "[Ljava/lang/Object;" ), evalArray = TRUE, simplify = TRUE )
+	}
+
+} )
+setMethod( "rev", "jarrayRef", function(x){
+	.NotYetImplemented()
+}) 
+# }}}
+
+# {{{ as.list
+# S4 dispatch does not work
+as.list.jarrayRef <- function(x, ... ){
+	.jevalArray( x )
+}
+as.list.jrectRef <- function( x, ...){
+	.jevalArray( x )
+}
+as.list.jobjRef <- function( x, ... ){
+	if( ! .jinstanceof( x, "java.lang.Iterable" ) ){
+ 		stop( "only objects that implements java.lang.Iterable can be converted to lists" )
+ 	}
+ 	.jcall( "RJavaArrayTools", "[Ljava/lang/Object;", 
+ 		"getIterableContent", .jcast(x, "java/lang/Iterable") , evalArray = TRUE, ... )
+}
+# }}}
+
+# {{{ min, max, range
+setMethod("min", "jrectRef", function(x, ...,na.rm=TRUE){ 
+	
+	dim <- x@dimension
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		min( x[simplify=TRUE], na.rm = na.rm )
+	} else{
+		summarizer <- .jnew( "RectangularArraySummary", .jcast(x), dim )
+		.jcall( summarizer, "Ljava/lang/Object;", "min", na.rm )
+	}
+	
+} )
+setMethod("min", "jarrayRef", function(x, ...,na.rm=TRUE){ 
+	.NotYetImplemented()
+}) 
+setMethod("max", "jrectRef", function(x, ..., na.rm=TRUE){ 
+	
+	dim <- x@dimension
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		max( x[simplify=TRUE], na.rm = na.rm )
+	} else{
+		summarizer <- .jnew( "RectangularArraySummary", .jcast(x), dim )
+		.jcall( summarizer, "Ljava/lang/Object;", "max", na.rm )
+	}
+	
+} )
+setMethod("max", "jarrayRef", function(x, ..., na.rm=TRUE){
+	.NotYetImplemented()
+} )
+setMethod("range", "jrectRef", function(x, ..., na.rm=TRUE){ 
+	
+	dim <- x@dimension
+	typename <- .jcall( "RJavaArrayTools", "Ljava/lang/String;", 
+		"getObjectTypeName", .jcast(x) )
+	if( isPrimitiveTypeName( typename, include.strings = TRUE ) ){
+		range( x[simplify=TRUE], na.rm = na.rm )
+	} else{
+		summarizer <- .jnew( "RectangularArraySummary", .jcast(x), dim )
+		.jcall( summarizer, "[Ljava/lang/Object;", "range", na.rm, evalArray = TRUE, simplify = TRUE )
+	}
+	
+} )
+setMethod("range", "jarrayRef", function(x, ..., na.rm=TRUE){ 
+	.NotYetImplemented()
+}) 
+# }}}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/call.R b/com.oracle.truffle.r.pkgs/rJava/R/call.R
new file mode 100644
index 0000000000000000000000000000000000000000..8bd0cb94b188ced9dee1728735f612835879cad5
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/call.R
@@ -0,0 +1,436 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## This file is part of the rJava package - low-level R/Java interface
+## (C)2006 Simon Urbanek <simon.urbanek@r-project.org>
+## For license terms see DESCRIPTION and/or LICENSE
+##
+## $Id$
+
+# create a new object
+.jnew <- function(class, ..., check=TRUE, silent=!check, class.loader=NULL) {
+  class <- gsub("\\.", "/", as.character(class)) # allow non-JNI specifiation
+  # TODO: should this do "S" > "java/lang/String", ... like .jcall
+  
+  if (check) .jcheck(silent=TRUE)
+  o<-.External(RcreateObject, class, ..., silent=silent, class.loader=class.loader)
+  if (check) .jcheck(silent=silent)
+  if (is.null(o)) {
+  	  if (!silent) {
+    	  stop("Failed to create object of class `",class,"'")
+      } else {
+    	  o <- .jzeroRef
+      }
+  }
+  new("jobjRef", jobj=o, jclass=class)
+}
+
+# create a new object reference manually (avoid! for backward compat only!) 
+# the problem with this is that you need a valid `jobj' which 
+# is implementation-dependent so it is undefined outside rJava internals
+# it is now used by JRI.createRJavaRef, though
+.jmkref <- function(jobj, jclass="java/lang/Object") {
+  new("jobjRef", jobj=jobj, jclass=gsub('\\.','/',as.character(jclass)))
+}
+
+# evaluates an array reference. If rawJNIRefSignature is set, then obj is not assumed to be
+# jarrayRef, but rather direct JNI reference with the corresponding signature
+.jevalArray <- function(obj, rawJNIRefSignature=NULL, silent=FALSE, simplify=FALSE) {
+  jobj<-obj
+  sig<-rawJNIRefSignature
+  if (is.null(rawJNIRefSignature)) {
+    if(!inherits(obj,"jarrayRef")) {
+      if (!inherits(obj,"jobjRef"))
+        stop("object is not a Java object reference (jobjRef/jarrayRef).")
+      cl <- gsub("\\.","/",.jclass(obj))
+      if (is.null(cl) || !isJavaArraySignature(cl) )
+        stop("object is not a Java array.")
+      sig <- cl
+    } else sig <- obj@jsig
+    jobj<-obj@jobj
+  } else if (is(obj, "jobjRef")) jobj<-obj@jobj
+  if (sig=="[I")
+    return(.Call(RgetIntArrayCont, jobj))
+  else if (sig=="[J")
+    return(.Call(RgetLongArrayCont, jobj))
+  else if (sig=="[Z")
+    return(.Call(RgetBoolArrayCont, jobj))
+  else if (sig=="[B")
+    return(.Call(RgetByteArrayCont, jobj))
+  else if (sig=="[D")
+    return(.Call(RgetDoubleArrayCont, jobj))
+  else if (sig=="[S")
+    return(.Call(RgetShortArrayCont, jobj))
+  else if (sig=="[C")
+    return(.Call(RgetCharArrayCont, jobj))
+  else if (sig=="[F")
+    return(.Call(RgetFloatArrayCont, jobj))
+  else if (sig=="[Ljava/lang/String;")
+    return(.Call(RgetStringArrayCont, jobj))
+  else if (sig=="[Ljava/lang/Double;" && simplify) {
+    obj@jclass <- sig; return(.jcall("RJavaArrayTools", "[D", "unboxDoubles", obj)) }
+  else if (sig=="[Ljava/lang/Integer;" && simplify) {
+    obj@jclass <- sig; return(.jcall("RJavaArrayTools", "[I", "unboxIntegers", obj)) }
+  else if (sig=="[Ljava/lang/Boolean;" && simplify) {
+    obj@jclass <- sig; return(as.logical(.jcall("RJavaArrayTools", "[I", "unboxBooleans", obj))) }
+  else if (substr(sig,1,2)=="[L")
+    return(lapply(.Call(RgetObjectArrayCont, jobj),
+                  function(x) new("jobjRef", jobj=x, jclass=substr(sig, 3, nchar(sig)-1)) ))
+  else if (substr(sig,1,2)=="[[") {
+    if (simplify) { # try to figure out if this is a rectangular array in which case we can do better
+      o <- newArray(simplify=TRUE, jobj=jobj, signature=sig)
+      # if o is not a reference then we were able to simplify it
+      if (!is(o, "jobjRef")) return(o)
+    }
+    # otherwise simplify has no effect
+    return(lapply(.Call(RgetObjectArrayCont, jobj),
+                  function(x) newArray(jobj=x, signature=substr(sig, 2, 999), simplify=simplify)))
+  }
+  # if we don't know how to evaluate this, issue a warning and return the jarrayRef
+  if (!silent)
+    warning(paste("I don't know how to evaluate an array with signature",sig,". Returning a reference."))
+  newArray(jobj = jobj, signature = sig, simplify = FALSE)
+}
+
+.jcall <- function(obj, returnSig="V", method, ..., evalArray=TRUE, 
+	evalString=TRUE, check=TRUE, interface="RcallMethod", 
+	simplify=FALSE, use.true.class = FALSE) {
+  if (check) .jcheck()
+  iaddr <- .env[[interface]]
+  # TODO
+  #interface <- if (is.null(iaddr)) getNativeSymbolInfo(interface, "rJava", TRUE, FALSE)$address else iaddr
+  r<-NULL
+  # S is a shortcut for Ljava/lang/String;
+  if (returnSig=="S")
+    returnSig<-"Ljava/lang/String;"
+  if (returnSig=="[S")
+    returnSig<-"[Ljava/lang/String;"
+  # original S (short) is now mapped to T so we need to re-map it (we don't really support short, though)
+  if (returnSig=="T") returnSig <- "S"
+  if (returnSig=="[T") returnSig <- "[S"
+  
+  if (inherits(obj,"jobjRef") || inherits(obj,"jarrayRef") || inherits(obj,"jrectRef") )
+    r<-.External(interface, obj@jobj, returnSig, method, ...)
+  else
+    r<-.External(interface, as.character(obj), returnSig, method, ...)
+
+  if (returnSig=="V") {
+    # FASTR <<<<<
+    # FIX check for exceptions before return; like in other cases in this function
+    if (check) {
+      .jcheck()
+    }
+    # FASTR >>>>>
+    return(invisible(NULL))
+  }  
+
+  if( use.true.class && !is.null( r ) ){
+  	  if( ! ( isPrimitiveTypeName(returnSig) || isArraySignature(returnSig) ) ){
+          # FASTR <<<<<    
+          # retrieve the clazzname via fastr interop
+
+          # avoid calling .jcall since we work on external pointers directly here
+          #clazz     <- .External(interface, r    , "Ljava/lang/Class;", "getClass")
+          #clazzname <- .External(interface, clazz, "Ljava/lang/String;", "getName")
+          #clazzname <- .External("RgetStringValue", clazzname)
+          o <- r
+          if(inherits(r, "externalptr")) {
+              o <- attr(r, "external.object")
+          }
+          clazzname <- attr(r, "external.classname")
+          if(is.null(clazzname)) {
+              # returnSig is not primitive, but we might have an unboxed primitive value              
+              # typicaly, this can happen when called from .jrcall (in cases like rJavaObject$someMethodReturningInt())
+              # and .jrcall for now always simplyfies the return value and dumps the class name anyway
+              # so lets retrieve it "just in case"
+              if (is.character(o)) {
+                  clazzname <- "java.lang.String"
+              } else if (is.integer(o)) {
+                  clazzname <- "java.lang.Integer"
+              } else if (is.double(o)) {
+                  clazzname <- "java.lang.Double"
+              } else if (is.logical(o)) {
+                  clazzname <- "java.lang.Boolean"
+              } else {
+                  clazzname <- java.class(o, getClassName = TRUE)
+              }
+          }
+          # FASTR >>>>>>
+  	  	  returnSig <- tojniSignature( clazzname ) 
+  	  }
+  }
+  
+  if (isJavaArraySignature(returnSig)) {
+      # eval or return a reference
+      r <- if (evalArray) .jevalArray(r, rawJNIRefSignature=returnSig, simplify=simplify) else newArray(jobj = r, signature = returnSig, simplify = FALSE)
+  } else if ( substr(returnSig,1,1)=="L") {
+  	  if (is.null(r)){
+  	  	  if( check ) .jcheck( silent = FALSE )
+  	  	  return(r)
+  	  }
+    
+  	if (returnSig=="Ljava/lang/String;" && evalString){
+      if( check ) .jcheck( silent = FALSE )
+  	  return(.External(RgetStringValue, r))
+    }
+    r <- new("jobjRef", jobj=r, jclass=substr(returnSig,2,nchar(returnSig)-1))
+  }
+  if (check) .jcheck()
+  if (.conv.in$.) .convert.in(r) else r
+}
+
+.jstrVal <- function(obj) {
+  # .jstrVal(.jstrVal(...)) = .jstrVal(...)
+  if (is.character(obj))
+    return(obj)
+  r<-NULL
+  if (!is(obj,"jobjRef"))
+    stop("can get value of Java objects only")
+  if (!is.null(obj@jclass) && obj@jclass=="lang/java/String")
+    r<-.External(RgetStringValue, obj@jobj)
+  else
+    r<-.External(RtoString, obj@jobj)
+  r
+}
+
+#' casts java object into new.class
+#' 
+#' @param obj a java object reference
+#' @param new.class the new class (in JNI or Java)
+#' @param check logical. If TRUE the cast if checked
+#' @param convert.array logical. If TRUE and the new class represents an array, then a jarrayRef object is made
+.jcast <- function(obj, new.class="java/lang/Object", check = FALSE, convert.array = FALSE) {
+  if (!is(obj,"jobjRef"))
+    stop("cannot cast anything but Java objects")
+  if( check && !.jinstanceof( obj, new.class) ){
+  	  stop( sprintf( "cannot cast object to '%s'", new.class ) ) 
+  }
+  
+  new.class <- gsub("\\.","/", as.character(new.class)) # allow non-JNI specifiation
+  if( convert.array && !is( obj, "jarrayRef" ) && isJavaArray( obj ) ){
+  	 r <- .jcastToArray( obj, signature = new.class)
+  } else {
+  	 r <- obj
+  	 r@jclass <- new.class
+  }
+  r
+}
+
+# makes sure that a given object is jarrayRef 
+.jcastToArray <- function(obj, signature=NULL, class="", quiet=FALSE) {
+  if (!is(obj, "jobjRef"))
+    return(.jarray(obj))
+  if (is.null(signature)) {
+  	  # TODO: factor out these two calls into a separate function
+    cl <- .jcall(obj, "Ljava/lang/Class;", "getClass")
+    cn <- .jcall(cl, "Ljava/lang/String;", "getName")
+    if ( !isJavaArraySignature(cn) ) {
+      if (quiet)
+        return(obj)
+      else
+        stop("cannot cast to array, object signature is unknown and class name is not an array")
+    }
+    signature <- cn
+  } else{
+  	  if( !isJavaArraySignature(signature) ){
+  	  	  if( quiet ) {
+  	  	  	  return( obj )
+  	  	  } else{
+  	  	  	  stop( "cannot cast to array, signature is not an array signature" )
+  	  	  }
+  	  }
+  }
+  signature <- gsub('\\.', '/', signature)
+  if (inherits(obj, "jarrayRef")) {
+    obj@jsig <- signature
+    return(obj)
+  }
+  newArray(obj, simplify=FALSE)
+}
+
+# creates a new "null" object of the specified class
+# although it sounds weird, the class is important when passed as
+# a parameter (you can even cast the result)
+.jnull <- function(class="java/lang/Object") { 
+  new("jobjRef", jobj=.jzeroRef, jclass=as.character(class))
+}
+
+.jcheck <- function(silent=FALSE) invisible(.Call(RJavaCheckExceptions, silent))
+
+.jproperty <- function(key) {
+  if (length(key)>1)
+    sapply(key, .jproperty)
+  else
+    .jcall("java/lang/System", "S", "getProperty", as.character(key)[1])
+}
+
+#' gets the dim of an array, or its length if it is just a vector
+getDim <- function(x){
+	dim <- dim(x)
+	if( is.null( dim ) ) dim <- length(x)
+	dim
+}
+
+.jarray <- function(x, contents.class = NULL, dispatch = FALSE) {
+	# this already is an array, so don't bother
+	if( isJavaArray( x ) ) return( newArray( x, simplify = FALSE) ) 
+	
+	# this is a two stage process, first we need to convert into 
+	# a flat array using the jni code
+	# TODO: but this needs to move to the internal jni world to avoid 
+	#       too many copies
+	
+	# common mistake is to not specify a list but just a single Java object
+	# but, well, people just keep doing it so we may as well support it 
+	dim <- if (inherits(x,"jobjRef")) {
+		x <- list(x)
+		1L
+	} else getDim(x)
+
+	# the jni call
+	array <- .Call(RcreateArray, x, contents.class)
+	
+	if (!dispatch) return( array )
+	
+	if( is.list( x ) ){
+		# if the input of RcreateArray was a list, we need some more care
+		# because we cannot be sure the array is rectangular so we have to 
+		# check it 
+		newArray( array, simplify = FALSE )
+	} else {
+	
+		# then we transform this to a rectangular array of the proper dimensions
+		if( length( dim ) == 1L ) {
+			# single dimension array
+			new( "jrectRef", jobj = array@jobj, jsig = array@jsig, 
+					jclass = array@jclass, dimension = dim )
+		} else {
+			builder <- .jnew( "RectangularArrayBuilder", .jcast(array), dim )
+			clazz <- .jcall( builder, "Ljava/lang/String;", "getArrayClassName" )
+			
+			# we cannot use .jcall here since it will try to simplify the array
+			# or go back to java to calculate its dimensions, ...
+			r <- .External( "RcallMethod", builder@jobj, 
+				"Ljava/lang/Object;", "getArray", PACKAGE="rJava")
+			
+			new( "jrectRef", jobj = r, dimension = dim, 
+				jclass = clazz, jsig = tojni( clazz ) ) 
+		}  
+	}
+}
+
+# works on EXTPTR or jobjRef or NULL. NULL is always silently converted to .jzeroRef
+.jidenticalRef <- function(a,b) {        
+  if (is(a,"jobjRef")) a<-a@jobj
+  if (is(b,"jobjRef")) b<-b@jobj
+  if (is.null(a)) a <- .jzeroRef
+  if (is.null(b)) b <- .jzeroRef
+  if (!inherits(a,"externalptr") || !inherits(b,"externalptr")) stop("Invalid argument to .jidenticalRef, must be a pointer or jobjRef")
+  .Call(RidenticalRef,a,b)
+}
+
+# returns TRUE only for NULL or jobjRef with jobj=0x0
+is.jnull <- function(x) {
+  (is.null(x) || (is(x,"jobjRef") && .jidenticalRef(x@jobj,.jzeroRef)))
+}
+
+# should we move this to C?
+.jclassRef <- function(x, silent=FALSE) {
+  if (is.jnull(x)) {
+    if (silent) return(NULL) else stop("null reference has no class")
+  }
+  if (!is(x, "jobjRef")) {
+    if (silent) return(NULL) else stop("invalid object")
+  }
+  cl <- NULL
+  try(cl <- .jcall(x, "Ljava/lang/Class;", "getClass", check=FALSE))
+  .jcheck(silent=TRUE)
+  if (is.jnull(cl) && !silent) stop("cannot get class object")
+  cl
+}
+
+# return class object for a given class name; silent determines whether
+# an error should be thrown on failure (FALSE) or just null reference (TRUE)
+.jfindClass <- function(cl, silent=FALSE) {
+  # FASTR TODO check all usecases, some of them might try to do e.g. newInstance, getMethods (if methods are a problem too?) etc
+  if (inherits(cl, "jclassName")) return(cl@jobj)
+  if (!is.character(cl) || length(cl)!=1)
+    stop("invalid class name")
+  cl<-gsub("/",".",cl)
+  a <- NULL
+  if (!is.jnull(.rJava.class.loader))
+    try(a <- .jcall("java/lang/Class","Ljava/lang/Class;","forName",cl,TRUE,.jcast(.rJava.class.loader,"java.lang.ClassLoader"), check=FALSE))
+  else
+    try(a <- .jcall("java/lang/Class","Ljava/lang/Class;","forName",cl,check=FALSE))
+  # this is really .jcheck but we don't want it to appear on the call stack
+  .Call(RJavaCheckExceptions, silent)
+  if (!silent && is.jnull(a)) stop("class not found")
+  a
+}
+
+# Java-side inheritance check; NULL inherits from any class, because 
+# it can be cast to any class type; cl can be a class name or a jobjRef to a class object
+.jinherits <- function(o, cl) {
+  if (is.jnull(o)) return(TRUE)
+  if (!is(o, "jobjRef")) stop("invalid object")
+  if (is.character(cl)) cl <- .jfindClass(cl) else if (inherits(cl, "jclassName")) cl <- cl@jobj
+  if (!is(cl, "jobjRef")) stop("invalid class object")  
+  ocl <- .jclassRef(o)
+  .Call(RisAssignableFrom, ocl@jobj, cl@jobj)
+}
+
+# compares two things which may be Java objects. invokes Object.equals if applicable and thus even different pointers can be equal. if one parameter is not Java object, but scalar string/int/number/boolean then a corresponding Java object is created for comparison
+# strict comparison returns FALSE if Java-reference is compared with non-reference. otherwise conversion into Java scalar object is attempted
+.jequals <- function(a, b, strict=FALSE) {
+  if (is.null(a)) a <- new("jobjRef")
+  if (is.null(b)) b <- new("jobjRef")
+  if (is(a,"jobjRef")) o <- a else
+    if (is(b,"jobjRef")) { o <- b; b <- a } else
+    return(all.equal(a,b))
+  if (!is(b,"jobjRef")) {
+    if (strict) return(FALSE)
+    if (length(b)!=1) { warning("comparison of non-scalar values is always FALSE"); return(FALSE) }
+    if (is.character(b)) b <- .jnew("java/lang/String",b) else
+    if (is.integer(b)) b <- .jnew("java/lang/Integer",b) else
+    if (is.numeric(b)) b <- .jnew("java/lang/Double",b) else
+    if (is.logical(b)) b <- .jnew("java/lang/Boolean", b) else
+    { warning("comparison of non-trivial values to Java objects is always FALSE"); return(FALSE) }
+  }
+  if (is.jnull(a))
+    is.jnull(b)
+  else
+    .jcall(o, "Z", "equals", .jcast(b, "java/lang/Object"))
+}
+
+.jfield <- function(o, sig=NULL, name, true.class=is.null(sig), convert=TRUE) {
+  if (length(sig)) {
+    if (sig=='S') sig<-"Ljava/lang/String;"
+    if (sig=='T') sig<-"S"
+    if (sig=='[S') sig<-"[Ljava/lang/String;"
+    if (sig=='[T') sig<-"[S"
+  }
+  r <- .Call(RgetField, o, sig, as.character(name), as.integer(true.class))
+  if (inherits(r, "jobjRef")) {
+    if (isJavaArraySignature(r@jclass)) {
+    	r <- if (convert) .jevalArray(r, rawJNIRefSignature=r@jclass, simplify=TRUE) else newArray(r, simplify=FALSE)
+    }
+    if (convert && inherits(r, "jobjRef")) {
+      if (r@jclass == "java/lang/String")
+        return(.External(RgetStringValue, r@jobj))
+      if (.conv.in$.) return(.convert.in(r))
+    }
+  }
+  r
+}
+
+".jfield<-" <- function(o, name, value)
+  .Call(RsetField, o, name, value)
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/comparison.R b/com.oracle.truffle.r.pkgs/rJava/R/comparison.R
new file mode 100644
index 0000000000000000000000000000000000000000..70f0447c6e68c994039aa1218eea7e6eeb11e940
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/comparison.R
@@ -0,0 +1,59 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+#' if a and b are compatable, 
+#' in the sense of the java.util.Comparable interface
+#' then the result of the compareTo method is returned
+#' otherwise an error message is generated
+.jcompare <- function(a, b) {
+  if (is.null(a)) a <- new("jobjRef")
+  if (is.null(b)) b <- new("jobjRef")
+  
+  if( isJavaArray(a) || isJavaArray(b) ){
+  	  stop( "comparison (<,>,<=,>=) is not implemented for java arrays yet" )
+  }
+  
+  if( !is(a, "jobjRef" ) ) a <- ._java_valid_object( a )
+  if( !is(b, "jobjRef" ) ) b <- ._java_valid_object( b )
+  
+  .jcall( "RJavaComparator", "I", "compare", .jcast(a), .jcast(b) )
+  
+}
+._lower <- function(e1, e2){
+	.jcompare( e1, e2 ) <= 0L
+}
+._greater <- function(e1, e2 ){
+	.jcompare( e1, e2 ) >= 0L
+}
+._strictly_lower <- function(e1, e2 ){
+	.jcompare( e1, e2 ) < 0L
+}
+._strictly_greater <- function(e1, e2 ){
+	.jcompare( e1, e2 ) > 0L
+}
+
+setMethod("<" , c(e1="jobjRef",e2="jobjRef"), ._strictly_lower )
+setMethod("<" , c(e1="jobjRef")             , ._strictly_lower )
+setMethod("<" , c(e2="jobjRef")             , ._strictly_lower )
+              
+setMethod(">" , c(e1="jobjRef",e2="jobjRef"), ._strictly_greater )
+setMethod(">" , c(e1="jobjRef")             , ._strictly_greater )
+setMethod(">" , c(e2="jobjRef")             , ._strictly_greater )
+
+setMethod("<=", c(e1="jobjRef",e2="jobjRef"), ._lower )
+setMethod("<=", c(e1="jobjRef")             , ._lower )
+setMethod("<=", c(e2="jobjRef")             , ._lower )
+                                               
+setMethod(">=", c(e1="jobjRef",e2="jobjRef"), ._greater )
+setMethod(">=", c(e1="jobjRef")             , ._greater )
+setMethod(">=", c(e2="jobjRef")             , ._greater )
+
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/completion.R b/com.oracle.truffle.r.pkgs/rJava/R/completion.R
new file mode 100644
index 0000000000000000000000000000000000000000..2e3dc1fbe65b1db20e3ff718930e687df8202f6f
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/completion.R
@@ -0,0 +1,67 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+# :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1:
+
+# S4 dispatch does not work for .DollarNames, so we'll use S3
+# {{{ bring .DollarNames from the future if necessary
+if( !exists( ".DollarNames", envir = asNamespace("utils") ) ){
+	.DollarNames <- function(x, pattern)
+    	UseMethod(".DollarNames")
+} 
+# }}}
+
+# {{{ support function to retrieve completion names from RJavaTools
+### get completion names from RJavaTools
+classNamesMethod <- function (cl, static.only = TRUE ) {
+	# TODO: return both from java instead of two java calls
+  fieldnames <- .jcall( "RJavaTools", "[Ljava/lang/String;", 
+  	"getFieldNames", cl, static.only ) 
+  methodnames <- .jcall( "RJavaTools", "[Ljava/lang/String;", 
+  	"getMethodNames", cl, static.only )
+  c(fieldnames, methodnames)
+}
+# }}}
+
+# {{{ jclassName
+._names_jclassName <- function(x){
+	c( "class", classNamesMethod(x@jobj, static.only = TRUE ) )
+}
+.DollarNames.jclassName <- function(x, pattern = "" ){
+	grep( pattern, ._names_jclassName(x), value = TRUE ) 
+}
+
+setMethod("names", c(x="jclassName"), ._names_jclassName )
+# }}}
+
+# {{{ jobjRef
+._names_jobjRef <- function(x){
+	classNamesMethod(.jcall(x, "Ljava/lang/Class;", "getClass"), static.only = FALSE )
+}
+.DollarNames.jobjRef <- function(x, pattern = "" ){
+	grep( pattern, ._names_jobjRef(x), value = TRUE )
+}
+setMethod("names", c(x="jobjRef"), ._names_jobjRef )
+# }}}
+
+# {{{ jarrayRef and jrectRef
+._names_jarrayRef <- function(x ){
+	c("length", classNamesMethod(.jcall(x, "Ljava/lang/Class;", "getClass"), static.only = FALSE ) )
+}
+.DollarNames.jarrayRef <- .DollarNames.jrectRef <- function(x, pattern = ""){
+	grep( pattern, ._names_jarrayRef(x), value = TRUE )
+}
+
+setMethod("names", c(x="jarrayRef"), ._names_jarrayRef )
+setMethod("names", c(x="jrectRef"), ._names_jarrayRef )
+
+
+# }}}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/converter.R b/com.oracle.truffle.r.pkgs/rJava/R/converter.R
new file mode 100644
index 0000000000000000000000000000000000000000..0401920e756c53fb800e99a7dd2ececd22a487a5
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/converter.R
@@ -0,0 +1,54 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+# in: Java -> R
+.conv.in <- new.env(parent=emptyenv())
+.conv.in$. <- FALSE
+# out: R -> Java
+.conv.out <- new.env(parent=emptyenv())
+.conv.out$. <- FALSE
+
+# --- internal fns
+.convert.in <- function(jobj, verify.class=TRUE) {  
+  jcl <- if (verify.class) .jclass(jobj) else gsub("/",".",jobj@jclass)
+  cv <- .conv.in[[jcl]]
+  if (!is.null(cv)) jobj else cv$fn(jobj)
+}
+
+.convert.out <- function(robj) {
+  for (cl in class(robj)) {
+    cv <- .conv.out[[cl]]
+    if (!is.null(cv)) return(cv$fn(robj))
+  }
+  robj
+}
+
+# external fns
+.jsetJConvertor <- function(java.class, fn) {
+  if (is.null(fn)) {
+    rm(list=java.class, envir=.conv.in)
+    if (!length(ls(.conv.in))) .conv.in$. <- FALSE
+  } else {
+    .conv.in$. <- TRUE
+    .conv.in[[java.class]] <- list(fn=fn)
+  }
+}
+
+.jsetRConvertor <- function(r.class, fn) {
+  if (is.null(fn)) {
+    rm(list=r.class, envir=.conv.out)
+    if (!length(ls(.conv.out))) .conv.out$. <- FALSE
+  } else {
+    .conv.out$. <- TRUE
+    .conv.out[[r.class]] <- list(fn=fn)
+  }
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/exceptions.R b/com.oracle.truffle.r.pkgs/rJava/R/exceptions.R
new file mode 100644
index 0000000000000000000000000000000000000000..454dffa101a8a5855ed4b6105736356eec1c7c64
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/exceptions.R
@@ -0,0 +1,59 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## functions for some basic exception handling
+
+# FIXME: should all these actually be deprecated or defunct
+
+## poll for an exception
+.jgetEx <- function(clear=FALSE) {
+  exo <- .Call(RpollException)
+  if (is.null(exo)) return(NULL)
+  x <- new("jobjRef", jobj=exo, jclass="java/lang/Throwable")
+  if (clear) .jclear()
+  x
+}
+
+## explicitly clear any pending exceptions
+.jclear <- function() {
+  .C(RclearException)
+  invisible(NULL)
+}
+
+## throw an exception
+.jthrow <- function(exception, message=NULL) {
+  if (is.character(exception))
+    exception <- .jnew(exception, as.character(message))
+  if (is(exception, "jobjRef"))
+    .Call(RthrowException, exception)
+  else
+    stop("Invalid exception.")
+}
+
+
+"$.Throwable" <- function( x, name ){
+	if( name %in% names(c(x)) ){
+		c(x)[[ name ]]
+	} else{
+		._jobjRef_dollar( x[["jobj"]], name )
+	}
+}
+
+"$<-.Throwable" <- function( x, name, value ){
+	if( name %in% names(x) ){
+		x[[ name ]] <- value
+	} else{
+		._jobjRef_dollargets( x[["jobj"]], name, value )
+	}
+	x
+	
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/import.R b/com.oracle.truffle.r.pkgs/rJava/R/import.R
new file mode 100644
index 0000000000000000000000000000000000000000..9f13d38e8fa14912cde500f2277cdf0e172af7ce
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/import.R
@@ -0,0 +1,156 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+IMPORTER <- ".__rjava__import"
+
+java_class_importers <- new.env()
+assign( ".namespaces", NULL, envir = java_class_importers )
+
+getImporterFromNamespace <- function( nm, create = TRUE ){
+	.namespaces <- get(".namespaces", envir = java_class_importers )
+	if( !is.null( .namespaces ) ){
+		for( item in .namespaces ){
+			if( identical( item$nm, nm ) ){
+				return( item$importer )
+			}
+		}
+	}
+	if( create ){
+		addImporterNamespace(nm)
+	}
+	
+}
+addImporterNamespace <- function( nm ){
+	importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) )
+	assign( ".namespaces",	
+		append( list( list( nm = nm, importer = importer ) ), get(".namespaces", envir = java_class_importers ) ), 
+		envir = java_class_importers )
+	importer
+}
+
+getImporterFromEnvironment <- function(env, create = TRUE){
+	if( isNamespace( env ) ){
+		getImporterFromNamespace( env )
+	} else if( exists(IMPORTER, envir = env ) ){
+		get( IMPORTER, envir = env )
+	} else if( create ){
+		addImporterNamespace(env)
+	}
+}
+
+getImporterFromGlobalEnv <- function( ){
+	if( exists( "global", envir = java_class_importers ) ){
+		get( "global", envir = java_class_importers ) 
+	} else{
+		initGlobalEnvImporter()
+	}
+}
+initGlobalEnvImporter <- function(){
+	importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) )
+	assign( "global", importer , envir = java_class_importers )
+	importer
+}
+
+import <- function( package = "java.util", env = sys.frame(sys.parent()) ){
+	
+	if( missing(env) ){
+		caller <- sys.function(-1)
+		env <- environment( caller ) 
+		if( isNamespace( env ) ){
+			importer <- getImporterFromNamespace( env )
+		}
+	} else{
+		force(env)
+	
+		if( !is.environment( env ) ){
+			stop( "env is not an environment" ) 
+		}
+		
+		if( ! exists( IMPORTER, env ) || is.jnull( get( IMPORTER, envir = env ) ) ){
+			importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) )
+			if( isNamespace(env) ){
+				unlockBinding( IMPORTER, env = env )
+				assignInNamespace( IMPORTER, importer, envir = env ) 
+			}
+			assign( IMPORTER, importer, envir = env ) 
+		} else{
+			importer <- get( IMPORTER, envir = env )
+		}
+	}
+	mustbe.importer( importer )
+	.jcall( importer, "V", "importPackage", package )
+	
+}
+
+is.importer <- function(x){
+	is( x, "jobjRef" ) && .jinherits( x, "RJavaImport" )
+}
+mustbe.importer <- function(x){
+	if( !is.importer(x) ){
+		stop( "object not a suitable java package importer" )
+	}
+}
+
+#' collect importers
+getAvailableImporters <- function( frames = TRUE, namespace = TRUE, 
+	global = TRUE, caller = sys.function(-1L) ){
+	
+	importers <- .jnew( "java/util/HashSet" )
+	
+	addImporter <- function( importer ){
+		if( is.importer( importer ) ){
+			.jcall( importers, "Z", "add", .jcast(importer) )
+		}
+	}
+	if( isTRUE( global ) ){
+		addImporter( getImporterFromGlobalEnv() )
+	}
+	
+	if( isTRUE( frames ) ){
+		frames <- sys.frames()
+		if( length(frames) > 1L ){
+			sapply( head( frames, -1L ), function(env) {
+				if( !identical( env, .GlobalEnv ) ){
+					addImporter( getImporterFromEnvironment( env ) )
+				}
+			} )
+		}
+	}
+	
+	if( isTRUE( namespace ) ){
+		force(caller)
+		env <- environment( caller ) 
+		if( isNamespace( env ) ){
+			addImporter( getImporterFromNamespace( env ) )
+		}
+	}
+	
+	importers
+}
+
+#' lookup for a class name in the available importers
+lookup <- function( name = "Object", ..., caller = sys.function(-1L) ){
+	force(caller)
+	importers <- getAvailableImporters(..., caller = caller)
+	.jcall( "RJavaImport", "Ljava/lang/Class;", "lookup", 
+		name, .jcast( importers, "java/util/Set" )  )
+}
+
+
+javaImport <- function( packages = "java.lang" ){
+    # FASTR TODO
+    stop("javaImport not yet implemented")
+        # importer <- .jnew( "RJavaImport", .jcast( .rJava.class.loader, "java/lang/ClassLoader" ) )
+	# .jcall( importer, "V", "importPackage", packages )
+	# .Call( "newRJavaLookupTable" , importer, 
+	#	PACKAGE = "rJava" )
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/instanceof.R b/com.oracle.truffle.r.pkgs/rJava/R/instanceof.R
new file mode 100644
index 0000000000000000000000000000000000000000..81b66760317a9152dd0d5ae8b2b6cc2e84536062
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/instanceof.R
@@ -0,0 +1,36 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+`%instanceof%` <- .jinstanceof <- function( o, cl ){
+	
+	if( !inherits( o, "jobjRef" ) ){
+		stop( "o is not a java object" )
+	}
+	
+	# first get the class object that represents cl
+	if( inherits( cl, "jobjRef" ) ){
+		if( .jclass( cl ) == "java.lang.Class" ){
+			clazz <- cl
+		} else {
+			clazz <- .jcall( cl, "Ljava/lang/Class;", "getClass" ) 
+		}
+	} else if( inherits( cl, "jclassName" ) ) {
+		clazz <- cl@jobj
+	} else if( inherits( cl, "character" ) ){
+		clazz <- .jfindClass(cl)
+	} else {
+		return(FALSE)
+	}
+	
+	# then find out if o is an instance of the class
+	.jcall( clazz , "Z", "isInstance", .jcast(o, "java/lang/Object" ) )
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/jfirst.R b/com.oracle.truffle.r.pkgs/rJava/R/jfirst.R
new file mode 100644
index 0000000000000000000000000000000000000000..a43a273fb9394c62ec5597ae0b40ae508b910fbf
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/jfirst.R
@@ -0,0 +1,749 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+# this part is common to all platforms and must be invoked
+# from .First.lib after library.dynam
+
+# actual namespace environment of this package
+.env <- environment()
+
+# variables in the rJava environment that will be initialized *after* the package is loaded
+# they need to be pre-created at load time and populated later by .jinit
+.delayed.export.variables <- c(".jniInitialized", ".jclassObject", ".jclassString", ".jclassClass",
+                               ".jclass.int", ".jclass.double", ".jclass.float", ".jclass.boolean",
+                               ".jclass.void", ".jinit.merge.error")
+# variables that are delayed but not exported are added here
+.delayed.variables <- c(.delayed.export.variables, ".rJava.class.loader")
+
+.jfirst <- function(libname, pkgname) {
+  # FASTR - no more C entry points
+  .registerFastrFunctions()
+  # register all C entry points
+  # addr <- getNativeSymbolInfo(.register.addr, pkgname)
+  # for (name in .register.addr)
+  #    .env[[name]] <- addr[[name]]$address
+  
+  # previously set in C
+  assign(".rJava_initialized", FALSE, .env)  
+  
+  assign(".rJava.base.path", paste(libname, pkgname, sep=.Platform$file.sep), .env)
+  assign(".jzeroRef", .createZeroRef(), .env)
+
+  for (x in .delayed.variables) assign(x, NULL, .env)
+  assign(".jniInitialized", FALSE, .env)
+
+  # FASTR - no JVM params
+  # # default JVM initialization parameters
+  # if (is.null(getOption("java.parameters")))
+  #   options("java.parameters"="-Xmx512m")
+
+  # assign(".rJava.debug", T, .env)  
+
+  ## S4 classes update - all classes are created earlier in classes.R, but jobjRef's prototype is only valid after the dylib is loaded
+  setClass("jobjRef", representation(jobj="externalptr", jclass="character"), prototype=list(jobj=.jzeroRef, jclass="java/lang/Object"), where=.env, validity=.jobjRef.validity)
+}
+
+# FASTR <<<<<
+
+.registerFastrFunctions <- function() {
+  # .C
+  .fastr.register.functions("rJava", .env, 0, 
+        list(RclearException=.RclearException))
+  # .External  
+  .fastr.register.functions("rJava", .env, 3, 
+        list(RcreateObject = .RcreateObject, 
+             RgetStringValue = .RgetStringValue, 
+             RinitJVM = .RinitJVM, 
+             RtoString = .RtoString, 
+             RcallMethod = .RcallMethod))
+  # .Call
+  .fastr.register.functions("rJava", .env, 1, 
+        list(RJavaCheckExceptions = .RJavaCheckExceptions,
+            RpollException = .RpollException,
+            RthrowException = .RthrowException,                                               
+            RidenticalRef = .RidenticalRef,
+            RisAssignableFrom = .RisAssignableFrom,
+            RJava_checkJVM = .RJava_checkJVM,
+            RJava_needs_init = .RJava_needs_init,
+            initRJavaTools = .initRJavaTools,            
+            RJava_set_memprof = .RJava_set_memprof,
+            RgetStringArrayCont = .RgetStringArrayCont,
+            RgetIntArrayCont = .RgetIntArrayCont,                 
+            RgetBoolArrayCont = .RgetBoolArrayCont,
+            RgetCharArrayCont = .RgetCharArrayCont,
+            RgetShortArrayCont = .RgetShortArrayCont,
+            RgetByteArrayCont = .RgetByteArrayCont,
+            RgetDoubleArrayCont = .RgetDoubleArrayCont,
+            RgetFloatArrayCont = .RgetFloatArrayCont,
+            RgetLongArrayCont = .RgetLongArrayCont,
+            RgetObjectArrayCont = .RgetObjectArrayCont,
+            RcreateArray = .RcreateArray,
+            RgetField = .RgetField,
+            RsetField = .RsetField))
+}
+
+.createZeroRef <- function() {
+    zr <- methods:::.newExternalptr()    
+    attr(zr, ".rJava.zeroRef") <- T
+    zr
+}
+
+.jobjRef.validity <- function(object) { 
+    object # force args
+
+    o <- attr(object@jobj, "external.object", exact=TRUE)
+    if(is.null(o)) {
+        zr <- attr(object@jobj, ".rJava.zeroRef", exact=TRUE)
+        if(is.null(zr)) {
+            return(FALSE)
+        }
+    } else if(!is.external(o)) {
+        # truffle unboxes first and fastr then converts primitive types into equivalent R values
+        # and the external.object attr in such a case isn't a truffle object 
+        # in e.g. .jnew and .jcall rJava knows and stores the return value class name in the jclass slot,
+        # but it is only the externalptr, that is passed into functions like RcallMethod 
+        # and we might need the class name for calls like getClass or isInstance
+        attr(object@jobj, "external.classname") <- object@jclass
+    }
+    return(TRUE)
+}
+
+# TODO issues:
+# - bytes converted to int
+# - chars converted to int
+
+.dispatchOverrides <- function(orig, .NAME, ...) {
+    if(is.character(.NAME)) {        
+        fun <- switch(.NAME, 
+            "RJavaCheckExceptions" = .RJavaCheckExceptions,
+            "RpollException" = .RpollException,
+            "RthrowException" = .RthrowException,
+            "RclearException" = .RclearException,                        
+            "RcallMethod" = .RcallMethod,
+            "RidenticalRef" = .RidenticalRef,
+            "RisAssignableFrom" = .RisAssignableFrom,
+            "RinitJVM" = .RinitJVM,
+            "RJava_checkJVM" = .RJava_checkJVM,
+            "RJava_needs_init" = .RJava_needs_init,
+            "initRJavaTools" = .initRJavaTools,            
+            "RJava_set_memprof" = .RJava_set_memprof,
+            "RgetStringValue" = .RgetStringValue,
+            "RcreateObject" = .RcreateObject,            
+            "RgetStringArrayCont" = .RgetStringArrayCont,
+            "RgetIntArrayCont" = .RgetIntArrayCont,                 
+            "RgetBoolArrayCont" = .RgetBoolArrayCont,
+            "RgetCharArrayCont" = .RgetCharArrayCont,
+            "RgetShortArrayCont" = .RgetShortArrayCont,
+            "RgetByteArrayCont" = .RgetByteArrayCont,
+            "RgetDoubleArrayCont" = .RgetDoubleArrayCont,
+            "RgetFloatArrayCont" = .RgetFloatArrayCont,
+            "RgetLongArrayCont" = .RgetLongArrayCont,
+            "RgetObjectArrayCont" = .RgetObjectArrayCont,
+            "RcreateArray" = .RcreateArray,
+            "RgetField" = .RgetField,
+            "RsetField" = .RsetField,
+            "RtoString" = .RtoString,
+            function(...) orig(.NAME, ...)
+        )        
+        fun(...)
+    } else {
+        orig(.NAME, ...)
+    }
+}
+
+.RJavaCheckExceptions <- function(silent) {
+    silent # force args
+
+    .fastr.interop.checkException(silent, ".jcheck")
+}
+
+.RpollException <- function() {    
+    e <- .fastr.interop.getTryException(FALSE)
+    if(is.null(e)) {
+        return(NULL)        
+    }
+    .fromJ(e)
+}
+
+.RclearException <- function() {    
+    .fastr.interop.clearTryException()
+}
+
+.RthrowException <- function(silent) {    
+    # TODO do we need this? not used directly from rJava code
+}
+
+.RidenticalRef <- function(x1, x2) {
+    x1; x2 # force args
+
+    if(!inherits(x1, "externalptr") || !inherits(x2, "externalptr")) {
+        return(NULL)
+    }
+    o1 <- attr(x1, "external.object", exact=TRUE)
+    o2 <- attr(x2, "external.object", exact=TRUE)
+    if(!(is.external(o1) && is.external(o2))) {
+        return(identical(o1, o2))
+    }
+    if(!is.external(o1) || !is.external(o2)) {
+        return(NULL)
+    }
+    .fastr.interop.isIdentical(o1, o2)
+}
+
+.RisAssignableFrom <- function(cl1, cl2) {
+    cl1; cl2 # force args
+
+    if(!inherits(cl1, "externalptr") || !inherits(cl2, "externalptr")) {
+        stop("invalid type")
+    }
+    # should be already ensured that both args are class extpointer-s
+    .fastr.interop.isAssignableFrom(attr(cl1, "external.object", exact=TRUE), attr(cl2, "external.object", exact=TRUE))  
+}
+
+.RcallMethod <- function(obj, returnSig, method, ...) {
+    obj; returnSig; method # force args
+
+    if(is.null(obj)) {
+        stop("RcallMethod: call on a NULL object")
+    }
+
+    o <- NULL
+    clnam <- NULL
+    if(inherits(obj, "externalptr")) {
+        o <- attr(obj, "external.object", exact=TRUE)
+    } else if(is.character(obj) && length(obj) == 1) {
+        clnam <- obj
+    } else {
+        stop("RcallMethod: invalid object parameter")
+    }
+    if(is.null(o) && is.null(clnam)) {
+        stop("RcallMethod: attempt to call a method of a NULL object.")
+    }
+  
+    # <<<<<< j.l.Class HACKs <<<<<<
+    # truffle provides no access to j.l.Class methods
+    if (method == "forName") {
+        if (!is.null(clnam) && clnam %in% c("java/lang/Class", "java.lang.Class")) {
+            res <- .fastr.interop.try(function() { new.java.class(list(...)[[1]]) }, FALSE)            
+            return(.fromJ(res))
+        }
+    } else if (method == "getName" && !is.null(o)) {
+        if (java.class(o) %in% c("java/lang/Class", "java.lang.Class")) {
+            res <- java.class(o, T)
+            return(.fromJ(res))
+        }           
+    } else if (method == "isInstance") {
+        if (!is.external(o)) {
+            o <- new.java.class(attr(obj, "external.classname", exact=TRUE))
+        }
+        o2 <- .toJ(list(...)[[1]])
+        res <- .fastr.interop.isInstance(o, o2)
+        return(.fromJ(res))        
+    } else if (method == "getClass") {
+        if(is.external(o)) {            
+            res <- .fastr.interop.getJavaClass(o)
+            return(.fromJ(res))
+        } else {
+            extClName <- attr(obj, "external.classname", exact=TRUE)
+            if(!is.null(extClName)) {
+                res <- new.java.class(extClName)  
+                return(.fromJ(res))
+            }                        
+        }
+    } 
+    # >>>>>> j.l.Class HACKs >>>>>>
+    
+    if (!is.null(o) && !is.external(o)) {        
+        o <- .asTruffleObject(o, attr(obj, "external.classname", exact=TRUE))
+    } 
+
+    if(!is.character(returnSig) || length(returnSig) != 1) {
+        stop("RcallMethod: invalid return signature parameter")
+    }
+
+    if(!is.character(method) || length(method) != 1) {
+        stop("RcallMethod: invalid method name")
+    }
+
+    # if((!is.null(o) && !(method %in% names(o))) ||        
+    #    (!is.null(cls) && !(method %in% names(cls))) ) {
+    #     stop(paste0("method ", method, " with signature ", returnSig, " not found"))
+    # }
+
+    if(is.null(o)) { 
+        cls <- NULL
+        if (!is.null(clnam)) {
+            cls <- .fastr.interop.try(function() { new.java.class(clnam) }, FALSE)
+        } 
+        if (is.null(cls)) {
+            stop("RcallMethod: cannot determine object class")
+        }
+
+        extMethod <- function(...) cls[method](...)
+    } else {
+        extMethod <- function(...) o[method](...)
+    }
+
+    args <- .ellipsisToJ(...)
+    res <- .fastr.interop.try(function() { do.call(extMethod, args) }, FALSE)
+    if(is.null(res)) {
+        return(NULL)
+    }
+
+    if(substr(returnSig, 1, 1) %in% c("L", "[")) {        
+        .fromJ(res, toExtPointer=TRUE)
+    } else {
+        .fromJ(res, toExtPointer=FALSE)    
+    }
+}
+
+.RgetField <- function(obj, sig, name, trueclass) {
+    obj; sig; name; trueclass # force args
+
+    if(is.null(obj)) {
+        return(NULL)
+    }
+
+    if (!is.character(name) || length(name) != 1) {
+        stop("invalid field name")
+    }
+
+    if (!is.null(sig) && (!is.character(sig) || length(sig) != 1)) {
+      stop("invalid signature parameter")
+    }
+    
+    if(.IS_JOBJREF(obj)) {
+        obj <- obj@jobj
+    }
+    clnam <- NULL
+    externalClassName <- NULL
+    o <- NULL
+    if(inherits(obj, "externalptr")) {
+        o <- .toJ(obj)
+        externalClassName <- attr(obj, "external.classname", exact=TRUE)
+    } else if(is.character(obj) && length(obj) == 1) {
+        clnam <- obj
+    } else {
+        stop("invalid object parameter")
+    }
+    if (is.null(o) && is.null(clnam)) {
+        stop("cannot access a field of a NULL object")
+    }       
+        
+    if(!is.null(o)) {
+        if(!is.external(o)) {
+            o <- .asTruffleObject(o, externalClassName)
+        }
+        res <- o[name]
+    } else {
+        cls <- new.java.class(clnam)
+        if (is.null(cls)) {
+            stop("cannot determine object class")
+        }
+        res <- cls[name]
+    }    
+    if(is.null(res)) {
+        return(.jnull())
+    }
+    if(!is.external(res)) {
+        # TODO there are cases when the passed signature is NULL - e.g. rJavaObject$someField 
+        # with truffle we have no way to defferenciate if the unboxed return value relates to an Object or primitive field
+        # but the original field.c RgetField implementation checks the return type and 
+        # if field not primitive an "jobjRef" S4 object is returned.
+        # rjava:
+        # > rJavaObject$fieldIntegerObject
+        # [1] "Java-Object{2147483647}"
+        # vs fastr:
+        # > rJavaObject$fieldIntegerObject
+        # [1] 2147483647
+        # Note that his is not the case in rjava with method calls:
+        # > rJavaObject$methodIntegerObject()
+        # [1] 2147483647
+        return(res)
+    }
+    
+    # as opposed to RcallMethod, we have to return a S4 objects at this place
+    if(trueclass) {
+        clsname <- java.class(res)
+    } else {
+        clsname <- .signatureToClassName(sig)
+    }
+    res <- .fromJ(res)
+    return(new("jobjRef", jobj=res, jclass=clsname))
+}
+
+.RsetField <- function(ref, name, value) {
+    ref; name; value # force args
+
+    obj <- ref
+    if (is.null(obj)) {
+        stop("cannot set a field of a NULL object")
+    }
+
+    if (!is.character(name) && length(name) != 1) {
+        stop("invalid field name")
+    }
+    
+    if(.IS_JOBJREF(obj)) {
+        obj <- obj@jobj
+    }
+    clnam <- NULL
+    o <- NULL
+    if(inherits(obj, "externalptr")) {
+        o <- .toJ(obj)
+    } else if(is.character(obj) && length(obj) == 1) {
+        clnam <- obj
+    } else {
+        stop("invalid object parameter")
+    }
+    if (is.null(o) && is.null(clnam)) {
+        stop("cannot set a field of a NULL object")
+    }
+
+    value <- .toJ(value)
+    if(!is.null(o)) {
+        o[name] <- value
+    } else {
+        cls <- new.java.class(clnam)
+        cls[name] <- value
+    }
+    ref
+}    
+
+.RcreateObject <-function(class, ..., silent, class.loader) {
+    class; silent; class.loader # force args
+
+    if(!is.character(class) || length(class) != 1) {
+        stop("RcreateObject: invalid class name")
+    }
+
+    co <- .fastr.interop.try(function() { new.java.class(class, silent) }, FALSE)
+    if(is.null(co)) {
+        return(NULL)
+    }
+    args <- .ellipsisToJ(co, ...)
+    res <- .fastr.interop.try(function() { do.call(new.external, args) }, FALSE)
+
+    # create an external pointer even for java.lang.String & co    
+    .fromJ(res, toExtPointer=TRUE)
+}
+
+.RgetStringArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.character)
+}
+
+.RgetIntArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.integer)
+}
+
+.RgetBoolArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.logical)
+}
+
+.RgetCharArrayCont <- function(obj) {
+    obj # force args
+
+    # TODO as.integer might cause trouble?
+    .getArrayCont(obj, as.integer)
+}
+
+.RgetShortArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.integer)
+}
+
+.RgetByteArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.raw)
+}
+
+.RgetDoubleArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.double)
+}
+
+.RgetFloatArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.double)
+}
+
+.RgetLongArrayCont <- function(obj) {
+    obj # force args
+
+    .getArrayCont(obj, as.double)
+}
+
+.RgetObjectArrayCont <- function(obj) {
+    obj # force args
+
+    if (is.null(obj)) {
+        return(obj)
+    }
+
+    if(!(inherits(obj, "externalptr"))) {
+        error("invalid object parameter")
+    }
+    obj <- attr(obj, "external.object", exact=TRUE)
+    # we rely on this being called only if obj is an external array
+    obj <- .fastr.interop.fromArray(obj)
+    lapply(obj, function(e) {.fromJ(e, toExtPointer=TRUE)})
+}
+
+.getArrayCont <- function(obj, toVectorFun) {
+    obj; toVectorFun # force args
+
+    if(is.null(obj)) {
+        return(obj)
+    } else if(!(inherits(obj, "externalptr"))) {
+        stop("invalid object parameter")
+    }
+    obj <- attr(obj, "external.object", exact=TRUE)
+    if(is.null(obj)) {
+        stop("invalid object parameter") 
+    }
+
+    if(missing(toVectorFun)) {
+        res <- as.vector(obj)
+    } else {
+       res <- toVectorFun(obj)    
+    }
+    res
+}
+
+.RcreateArray <- function(ar, cl) {
+    ar; cl # force args
+
+    if(is.null(ar)) {
+        return(NULL)
+    }
+
+    type <- typeof(ar)
+    if(type %in% c("integer", "double", "character", "logical", "raw")) {
+        ar <- .vectorToJArray(ar)
+        sig <- java.class(ar)
+        return(new("jarrayRef", jobj=.fromJ(ar), jclass=sig, jsig=sig))
+    } else if(is.list(ar)) {
+
+        lapply(ar, function(e) {
+            if(!is.null(e) && !.IS_JOBJREF(e)) {
+                stop("Cannot create a Java array from a list that contains anything other than Java object references.")
+            }
+        })
+        
+        if(length(cl) > 0) {
+            clsName <- cl[1]            
+        } else {
+            clsName <- "java.lang.Object"    
+        }
+        ar <- .listToJ(ar)
+        ar <- as.java.array(ar, clsName)
+        sig <- java.class(ar)
+        return(new("jarrayRef", jobj=.fromJ(ar), jclass=sig, jsig=sig))
+    } 
+    stop("Unsupported type to create Java array from.")
+}
+
+.RtoString <- function(obj) {
+    obj # force args
+
+    if(is.null(obj)) {
+        return(obj)
+    }
+    
+    if(!inherits(obj, "externalptr")) {
+        stop("RtoString: invalid object parameter")
+    }
+    
+    if(!is.null(attr(obj, "external.object", exact=TRUE))) {
+        obj <- .toJ(obj)
+        if(is.external(obj)) {
+            if(java.class(obj) == "java.lang.Class") {
+                res <- paste0("class ", java.class(obj, T))
+            } else {
+                res <- obj["toString"]()
+            }        
+        } else {
+            res <- obj
+        }
+    } else {
+        stop("RtoString: invalid object parameter")        
+    } 
+    res
+}
+
+
+.RgetStringValue <- function(obj) {
+    obj # force args
+
+    if (inherits(obj, "externalptr")) {
+        attr(obj, "external.object", exact=TRUE)
+    } else {
+        obj
+    }
+}
+
+.RinitJVM <- function(...) {    
+    .rJava_initialized <- TRUE
+}
+
+.RJava_needs_init <- function(...) {
+    !.rJava_initialized
+}
+
+.RJava_set_memprof <- function(...) {
+    stop("memory profiling not enabled")
+}        
+
+.RJava_checkJVM <- function(...) {
+    # do nothing
+}
+
+.initRJavaTools <- function(...) {
+    # do nothing
+}
+
+.fromJ <- function(x, toExtPointer=FALSE) {
+    x; toExtPointer # force args
+
+    if(is.null(x)) {
+        return(.jzeroRef)
+    } else {        
+        if(toExtPointer || is.external(x)) {
+            ep <- methods:::.newExternalptr() 
+            attr(ep, "external.object") <- x            
+            ep
+        } else {
+            x
+        }    
+    }
+}
+
+.ellipsisToJ <- function(...) {
+    lapply(list(...), function(x) .toJ(x))
+}
+
+.listToJ <- function(l) {
+    l # force args
+
+    lapply(l, function(x) .toJ(x))
+}
+
+.toJ <- function(x) {
+    x # force args
+
+    if (is(x, "jobjRef")) {
+        x <- x@jobj
+    } else if (is(x, "jclassName")) {
+        x <- x@jobj@jobj
+    }
+    if(inherits(x, "externalptr")) {
+        if(.jidenticalRef(x, .jzeroRef)) {
+            x <- NULL
+        } else {
+            xo <- attr(x, "external.object", exact=TRUE)
+            if (is.null(xo)) {
+                stop(paste0("missing 'external' attribute on: ", x))
+            }
+            if (is.external(xo)) {
+                return(xo)
+            } else {                
+                return(.asTruffleObject(xo, attr(x, "external.classname", exact=TRUE)))
+            }
+        }
+    }
+    if(length(x) > 1) {
+        .vectorToJArray(x)
+    } else {
+        if (inherits(x, "jbyte")) {
+            x <- as.external.byte(x)    
+        } else if (inherits(x, "jchar")) {
+            x <- as.external.char(x)
+        } else if (inherits(x, "jfloat")) {
+            x <- as.external.float(x)
+        } else if (inherits(x, "jlong")) {
+            x <- as.external.long(x)
+        } else if (inherits(x, "jshort")) {
+            x <- as.external.short(x)        
+        }
+        x
+    }
+}
+
+.vectorToJArray <- function(x) {
+    x # force args
+
+    switch(class(x),
+        "jbyte" = as.java.array(x, "byte"),
+        "jchar" = as.java.array(x, "char"),
+        "jfloat" = as.java.array(x, "float"),
+        "jlong" = as.java.array(x, "long"),
+        "jshort" = as.java.array(x, "short"),
+        as.java.array(x)
+    )
+}
+
+.asTruffleObject <- function(x, className=NULL) {
+    x; className # force args
+
+    if(!is.null(className)) {
+        x <- switch(gsub("/", ".", className),
+            "java.lang.Byte" = as.external.byte(x),
+            "java.lang.Character" = as.external.char(x),
+            "java.lang.Float" = as.external.float(x),
+            "java.lang.Long" = as.external.long(x),
+            "java.lang.Short" = as.external.short(x),        
+            x
+        )        
+    }
+    .fastr.interop.asJavaTruffleObject(x)
+}
+
+.signatureToClassName <- function(sig) {
+    sig # force args
+
+    if(startsWith(sig, "L")) {
+        if(endsWith(sig, ";")) {
+            substr(sig, 2, nchar(sig) - 1)
+        } else {
+            substr(sig, 2, nchar(sig))
+        }    
+    } else {
+        sig
+    }
+}
+
+.IS_JOBJREF <- function(obj) {
+    obj # force args
+
+    inherits(obj, "jobjRef") || inherits(obj, "jarrayRef") || inherits(obj,"jrectRef")
+}
+
+.IS_JARRAYREF <- function(obj) { 
+    obj # force args
+
+    inherits(obj, "jobjRef") || inherits(obj, "jarrayRef") || inherits(obj, "jrectRef") 
+}
+
+.IS_JRECTREF <- function(obj) { 
+    obj # force args
+
+    inherits(obj,"jrectRef")
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/jinit.R b/com.oracle.truffle.r.pkgs/rJava/R/jinit.R
new file mode 100644
index 0000000000000000000000000000000000000000..aa63fb778581a79f8461b3298a459a475144fa2e
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/jinit.R
@@ -0,0 +1,261 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## This file is part of the rJava package - low-level R/Java interface
+## (C)2006 Simon Urbanek <simon.urbanek@r-project.org>
+## For license terms see DESCRIPTION and/or LICENSE
+##
+## $Id$
+
+.check.JVM <- function() 
+    .Call(RJava_checkJVM)
+.need.init <- function()
+    .Call(RJava_needs_init)
+
+## initialization
+.jinit <- function(classpath=NULL, parameters=getOption("java.parameters"), ..., silent=FALSE, force.init=FALSE) {
+  running.classpath <- character()
+  if (!.need.init()) {
+    running.classpath <- .jclassPath()
+    if (!force.init) {
+      if (length(classpath)) {
+        cpc <- unique(unlist(strsplit(classpath, .Platform$path.sep)))
+        if (length(cpc)) .jaddClassPath(cpc)
+      }
+      return(0)
+    }
+  }
+
+  ## determine path separator
+  path.sep <- .Platform$path.sep
+
+  if (!is.null(classpath)) {
+    classpath <- as.character(classpath)
+    if (length(classpath))
+      classpath <- paste(classpath,collapse=path.sep)
+  }
+  
+  # merge CLASSPATH environment variable if present
+  cp<-Sys.getenv("CLASSPATH")
+  if (!is.null(cp)) {
+    if (is.null(classpath))
+      classpath<-cp
+    else
+      classpath<-paste(classpath,cp,sep=path.sep)
+  }
+  
+  # set rJava/java/boot for boostrap (so we can get RJavaClassLoader)
+  boot.classpath <- file.path(.rJava.base.path,"java","boot")
+
+  # if running in a sub-arch, append -Dr.arch in case someone gets the idea to start JRI
+  if (is.character(.Platform$r_arch) && nzchar(.Platform$r_arch) && length(grep("-Dr.arch", parameters, fixed=TRUE)) == 0L)
+    parameters <- c(paste("-Dr.arch=/", .Platform$r_arch, sep=''), as.character(parameters))
+
+  ## unfortunately Sys/setlocale()/Sys.getlocale() have incompatible interfaces so there
+  ## is no good way to get/set locales -- so we have to hack around it ...
+  locale.list <- c("LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", "LC_PAPER", "LC_MEASUREMENT")
+  locales <- sapply(locale.list, Sys.getlocale)
+  loc.sig <- Sys.getlocale()
+
+  #cat(">> init CLASSPATH =",classpath,"\n")
+  #cat(">> boot class path: ", boot.classpath,"\n")
+  # call the corresponding C routine to initialize JVM
+  xr <- .External(RinitJVM, boot.classpath, parameters)
+
+  ## we have to re-set the locales right away
+  suppressWarnings(try(if (!identical(Sys.getlocale(), loc.sig)) for (i in names(locales)) try(Sys.setlocale(i, locales[i]), silent=TRUE),
+      silent=TRUE))
+
+  if (xr==-1) stop("Unable to initialize JVM.")
+  if (xr==-2) stop("Another VM is already running and rJava was unable to attach to that VM.")
+  # we'll handle xr==1 later because we need fully initialized rJava for that
+
+  # this should remove any lingering .jclass objects from the global env
+  # left there by previous versions of rJava
+  pj <- grep("^\\.jclass",ls(1,all.names=TRUE),value=TRUE)
+  if (length(pj)>0) { 
+    rm(list=pj,pos=1)
+    if (exists(".jniInitialized",1)) rm(list=".jniInitialized",pos=1)
+    if (!silent) warning("rJava found hidden Java objects in your workspace. Internal objects from previous versions of rJava were deleted. Please note that Java objects cannot be saved in the workspace.")
+  }
+
+  ##--- HACK-WARNING: we're operating directly on the namespace environment
+  ##                  this could be dangerous.
+  for (x in .delayed.variables) unlockBinding(x, .env)
+  assign(".jniInitialized", TRUE, .env)
+  # get cached class objects for reflection
+  assign(".jclassObject", .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Object"), .env)
+  assign(".jclassClass", .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Class"), .env)
+  assign(".jclassString", .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.String"), .env)
+
+  # copied from bellow, need the RJavaTools to invoke $getField("TYPE") instead of not working .jcall
+  .Call( initRJavaTools)   
+  .jaddClassPath(file.path(.rJava.base.path,"java"))
+  # FASTR <<<<<
+  # ic <- .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Integer")
+  # # TODO .jcall does not work because in RcallMethod we do javaObejct[getField]("TYPE") and truffle does not allow it?
+  # # on the other hand ic$getField() is routed via the reflective RJavaTools.invokeMethod()
+  # #f<-.jcall(ic,"Ljava/lang/reflect/Field;","getField", "TYPE")
+  # f <- ic$getField("TYPE")
+  # assign(".jclass.int", .jcast(.jcall(f,"Ljava/lang/Object;","get",.jcast(ic,"java/lang/Object")),"java/lang/Class"), .env)
+  # ic <- .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Double")
+  # # f<-.jcall(ic,"Ljava/lang/reflect/Field;","getField", "TYPE")
+  # f <- ic$getField("TYPE")
+  # assign(".jclass.double", .jcast(.jcall(f,"Ljava/lang/Object;","get",.jcast(ic,"java/lang/Object")),"java/lang/Class"), .env)
+  # ic <- .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Float")
+  # # f<-.jcall(ic,"Ljava/lang/reflect/Field;","getField", "TYPE")
+  # f <- ic$getField("TYPE")
+  # assign(".jclass.float", .jcast(.jcall(f,"Ljava/lang/Object;","get",.jcast(ic,"java/lang/Object")),"java/lang/Class"), .env)
+  # ic <- .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Boolean")
+  # # f<-.jcall(ic,"Ljava/lang/reflect/Field;","getField", "TYPE")
+  # f <- ic$getField("TYPE")
+  # assign(".jclass.boolean", .jcast(.jcall(f,"Ljava/lang/Object;","get",.jcast(ic,"java/lang/Object")),"java/lang/Class"), .env)
+  # ic <- .jcall("java/lang/Class","Ljava/lang/Class;","forName","java.lang.Void")
+  # # f<-.jcall(ic,"Ljava/lang/reflect/Field;","getField", "TYPE")
+  # f <- ic$getField("TYPE")
+  # assign(".jclass.void", .jcast(.jcall(f,"Ljava/lang/Object;","get",.jcast(ic,"java/lang/Object")),"java/lang/Class"), .env)
+
+  ## if NOAWT is set, set AWT to headless
+  #if (nzchar(Sys.getenv("NOAWT"))) .jcall("java/lang/System","S","setProperty","java.awt.headless","true")
+
+  #lib <- "libs"
+  #if (nchar(.Platform$r_arch)) lib <- file.path("libs", .Platform$r_arch)
+
+  # TODO classloader stuff, ignore for now, maybe forever
+  # rjcl <- NULL
+  # if (xr==1) { # && nchar(classpath)>0) {
+  #   # ok, so we're attached to some other JVM - now we need to make sure that
+  #   # we can load our class loader. If we can't then we have to use our bad hack
+  #   # to be able to squeeze our loader in
+
+  #   # first, see if this is actually JRIBootstrap so we have a loader already
+  #   rjcl <- .Call(RJava_primary_class_loader)
+  #   if (is.null(rjcl) || .jidenticalRef(rjcl,.jzeroRef)) rjcl <- NULL
+  #   else rjcl <- new("jobjRef", jobj=rjcl, jclass="RJavaClassLoader")
+  #   if (is.jnull(rjcl))
+  #     rjcl <- .jnew("RJavaClassLoader", .rJava.base.path,
+  #                                     file.path(.rJava.base.path, lib), check=FALSE)
+  #   .jcheck(silent=TRUE)
+  #   if (is.jnull(rjcl)) {
+  #     ## it's a hack, so we run it in try(..) in case BadThings(TM) happen ...
+  #     cpr <- try(.jmergeClassPath(boot.classpath), silent=TRUE)
+  #     if (inherits(cpr, "try-error")) {
+  #       .jcheck(silent=TRUE)
+  #       if (!silent) warning("Another VM is running already and the VM did not allow me to append paths to the class path.")
+  #       assign(".jinit.merge.error", cpr, .env)
+  #     }
+  #     if (length(parameters)>0 && any(parameters!=getOption("java.parameters")) && !silent)
+  #       warning("Cannot set VM parameters, because VM is running already.")
+  #   }
+  # }
+
+  # if (is.jnull(rjcl))
+  #   rjcl <- .jnew("RJavaClassLoader", .rJava.base.path,
+  #                 file.path(.rJava.base.path, lib), check=FALSE )
+
+  # if (!is.jnull(rjcl)) {
+  #   ## init class loader
+  #   assign(".rJava.class.loader", rjcl, .env)
+
+  #   ##-- set the class for native code
+  #   .Call(RJava_set_class_loader, .env$.rJava.class.loader@jobj)
+
+  #   ## now it's time to add any additional class paths
+    cpc <- unique(strsplit(classpath, .Platform$path.sep)[[1]])
+    if (length(cpc)) .jaddClassPath(cpc)
+  # } else stop("Unable to create a Java class loader.")
+  # FASTR >>>>>  
+  ##.Call(RJava_new_class_loader, .rJava.base.path, file.path(.rJava.base.path, lib))
+
+  ## lock namespace bindings
+  for (x in .delayed.variables) lockBinding(x, .env)
+  
+  ## now we need to update the attached namespace (package env)  as well
+  m <- match(paste("package", getNamespaceName(.env), sep = ":"), search())[1]
+  if (!is.na(m)) { ## only is it is attached
+    pe <- as.environment(m)
+    for (x in .delayed.export.variables) {
+      unlockBinding(x, pe)
+      pe[[x]] <- .env[[x]]
+      lockBinding(x, pe)
+    }
+  }
+  
+  # FIXME: is this the best place or should this be done 
+  #        internally right after the RJavaClassLoader is instanciated
+  # init the cached RJavaTools class in the jni side
+  .Call( "initRJavaTools", PACKAGE = "rJava" ) 
+  
+  # not yet
+  # import( c( "java.lang", "java.util") )
+  
+  invisible(xr)
+}
+
+# FIXME: this is not always true: osgi, eclipse etc use a different
+#        class loader strategy, we should add some sort of hook to let people
+#        define how they want this to be done
+.jmergeClassPath <- function(cp) {
+  ccp <- .jcall("java/lang/System","S","getProperty","java.class.path")
+  ccpc <- strsplit(ccp, .Platform$path.sep)[[1]]
+  cpc <- strsplit(cp, .Platform$path.sep)[[1]]
+  rcp <- unique(cpc[!(cpc %in% ccpc)])
+  if (length(rcp) > 0) {
+    # the loader requires directories to include trailing slash
+    # Windows: need / or \ ? (untested)
+    dirs <- which(file.info(rcp)$isdir)
+    for (i in dirs)
+      if (substr(rcp[i],nchar(rcp[i]),nchar(rcp[i]))!=.Platform$file.sep)
+        rcp[i]<-paste(rcp[i], .Platform$file.sep, sep='')
+
+    ## this is a hack, really, that exploits the fact that the system class loader
+    ## is in fact a subclass of URLClassLoader and it also subverts protection
+    ## of the addURL class using reflection - yes, bad hack, but we use it
+    ## only if the boot class path doesn't contain our own class loader so
+    ## we cannot replace the system loader with our own (this will happen when we
+    ## need to attach to an existing VM)
+    ## The original discussion and code for this hack was at:
+    ## http://forum.java.sun.com/thread.jspa?threadID=300557&start=15&tstart=0
+
+    ## it should probably be run in try(..) because chances are that it will
+    ## break if Sun changes something...
+    cl <- .jcall("java/lang/ClassLoader", "Ljava/lang/ClassLoader;", "getSystemClassLoader")
+    urlc <- .jcall("java/lang/Class", "Ljava/lang/Class;", "forName", "java.net.URL")
+    clc <- .jcall("java/lang/Class", "Ljava/lang/Class;", "forName", "java.net.URLClassLoader")
+    ar <- .jcall("java/lang/reflect/Array", "Ljava/lang/Object;",
+                         "newInstance", .jclassClass, 1:1)
+    .jcall("java/lang/reflect/Array", "V", "set",
+                  .jcast(ar, "java/lang/Object"), 0:0,
+                  .jcast(urlc, "java/lang/Object"))
+    m<-.jcall(clc, "Ljava/lang/reflect/Method;", "getDeclaredMethod", "addURL", .jcast(ar,"[Ljava/lang/Class;"))
+    .jcall(m, "V", "setAccessible", TRUE)
+
+    ar <- .jcall("java/lang/reflect/Array", "Ljava/lang/Object;",
+                 "newInstance", .jclassObject, 1:1)
+    
+    for (fn in rcp) {
+      f <- .jnew("java/io/File", fn)
+      url <- .jcall(f, "Ljava/net/URL;", "toURL")
+      .jcall("java/lang/reflect/Array", "V", "set",
+             .jcast(ar, "java/lang/Object"), 0:0,
+             .jcast(url, "java/lang/Object"))
+      .jcall(m, "Ljava/lang/Object;", "invoke",
+             .jcast(cl, "java/lang/Object"), .jcast(ar, "[Ljava/lang/Object;"))
+    }
+
+    # also adjust the java.class.path property to not confuse others
+    if (length(ccp)>1 || (length(ccp)==1 && nchar(ccp[1])>0))
+      rcp <- c(ccp, rcp)
+    acp <- paste(rcp, collapse=.Platform$path.sep)
+    .jcall("java/lang/System","S","setProperty","java.class.path",as.character(acp))
+  } # if #rcp>0
+  invisible(.jcall("java/lang/System","S","getProperty","java.class.path"))
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/loader.R b/com.oracle.truffle.r.pkgs/rJava/R/loader.R
new file mode 100644
index 0000000000000000000000000000000000000000..07603a50130abd7acaf9e5d90d3e84cfe0a91d10
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/loader.R
@@ -0,0 +1,85 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+.jaddClassPath <- function(path) {
+    if (!length(path)) return(invisible(NULL))
+    # FASTR <<<<<
+    # if (!is.jnull(.rJava.class.loader))
+    #    invisible(.jcall(.rJava.class.loader,"V","addClassPath",as.character(path)))
+    # else {
+    #    cpr <- try(.jmergeClassPath(paste(path,collapse=.Platform$path.sep)), silent=TRUE)
+    #    invisible(!inherits(cpr, "try-error"))
+    #}
+    invisible(java.addToClasspath(path))
+    # FASTR >>>>>
+}
+
+.jclassPath <- function() {
+    # FASTR <<<<<
+    # if (is.jnull(.rJava.class.loader)) {
+    #     cp <- .jcall("java/lang/System", "S", "getProperty", "java.class.path")
+    #     unlist(strsplit(cp, .Platform$path.sep))
+    # } else {
+    #     .jcall(.rJava.class.loader,"[Ljava/lang/String;","getClassPath")
+    # }
+    java.classpath()
+    # FASTR >>>>>
+}
+
+.jaddLibrary <- function(name, path) {
+    # FASTR TODO 
+    stop(".jaddLibrary overriden but not yet implemented")
+    # if (!is.jnull(.rJava.class.loader))
+    #     invisible(.jcall(.rJava.class.loader, "V", "addRLibrary", as.character(name)[1], as.character(path)[1]))
+}
+
+.jrmLibrary <- function(name) {
+  ## FIXME: unimplemented
+}
+
+.jclassLoader <- function() {
+    # FASTR TODO 
+    stop(".jclassLoader overriden but not yet implemented")
+    #.rJava.class.loader
+}
+
+.jpackage <- function(name, jars='*', morePaths='', nativeLibrary=FALSE, lib.loc=NULL) {
+  if (!.jniInitialized) .jinit()
+  classes <- system.file("java", package=name, lib.loc=lib.loc)
+  if (nchar(classes)) {
+    .jaddClassPath(classes)
+    if (length(jars)) {
+      if (length(jars)==1 && jars=='*') {
+        jars <- grep(".*\\.jar",list.files(classes,full.names=TRUE),TRUE,value=TRUE)
+        if (length(jars)) .jaddClassPath(jars)
+      } else .jaddClassPath(paste(classes,jars,sep=.Platform$file.sep))
+    }
+  }  
+  if (any(nchar(morePaths))) {
+    cl <- as.character(morePaths)
+    cl <- cl[nchar(cl)>0]
+    .jaddClassPath(cl)
+  }
+  if (is.logical(nativeLibrary)) {
+    if (nativeLibrary) {
+      libs <- "libs"
+      if (nchar(.Platform$r_arch)) lib <- file.path("libs", .Platform$r_arch)
+      lib <- system.file(libs, paste(name, .Platform$dynlib.ext, sep=''), package=name, lib.loc=lib.loc)
+      if (nchar(lib))
+        .jaddLibrary(name, lib)
+      else
+        warning("Native library for `",name,"' could not be found.")
+    }
+  } else {
+    .jaddLibrary(name, nativeLibrary)
+  }
+  invisible(TRUE)
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/memprof.R b/com.oracle.truffle.r.pkgs/rJava/R/memprof.R
new file mode 100644
index 0000000000000000000000000000000000000000..f90745301bf078c9a542a7c4f846e398436a92ed
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/memprof.R
@@ -0,0 +1,15 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+.jmemprof <- function(file = "-") {
+  if (is.null(file)) file <- ""
+  invisible(.Call(RJava_set_memprof, as.character(file)))
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/methods.R b/com.oracle.truffle.r.pkgs/rJava/R/methods.R
new file mode 100644
index 0000000000000000000000000000000000000000..75435d009d420cf8911c47472e24b4b3e9a1b7e6
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/methods.R
@@ -0,0 +1,38 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## methods for jobjRef class
+##
+## additional methods ($ and $<-) are defined in reflection.R
+
+# show method
+# FIXME: this should show the class of the object instead of Java-Object
+setMethod("show", c(object="jobjRef"), function(object) {
+  if (is.jnull(object)) show("Java-Object<null>") else show(paste("Java-Object{", .jstrVal(object), "}", sep=''))
+  invisible(NULL)
+})
+
+setMethod("show", c(object="jarrayRef"), function(object) {
+  show(paste("Java-Array-Object",object@jsig,":", .jstrVal(object), sep=''))
+  invisible(NULL)
+})
+
+# map R comparison operators to .jequals
+setMethod("==", c(e1="jobjRef",e2="jobjRef"), function(e1,e2) .jequals(e1,e2))
+setMethod("==", c(e1="jobjRef"), function(e1,e2) .jequals(e1,e2))
+setMethod("==", c(e2="jobjRef"), function(e1,e2) .jequals(e1,e2))
+
+setMethod("!=", c(e1="jobjRef",e2="jobjRef"), function(e1,e2) !.jequals(e1,e2))
+setMethod("!=", c(e1="jobjRef"), function(e1,e2) !.jequals(e1,e2))
+setMethod("!=", c(e2="jobjRef"), function(e1,e2) !.jequals(e1,e2))
+
+# other operators such as <,> are defined in comparison.R
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/options.R b/com.oracle.truffle.r.pkgs/rJava/R/options.R
new file mode 100644
index 0000000000000000000000000000000000000000..e28823c0c975d6365f52b6d2072427343e9a5020
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/options.R
@@ -0,0 +1,22 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+.joptions <- function(...) {
+  l <- list(...)
+  if (length(l)==0) return(list())
+  if ("jni.cache" %in% names(l)) {
+    v <- l[["jni.cache"]]
+    if (!is.logical(v) || length(v)!=1)
+      stop("jni.cache must be a logical vector of length 1")
+    .C(RuseJNICache,v)
+    invisible(NULL)
+  }
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/reflection.R b/com.oracle.truffle.r.pkgs/rJava/R/reflection.R
new file mode 100644
index 0000000000000000000000000000000000000000..bee29283b150d874576e8e20f0ac7e77c2e177f4
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/reflection.R
@@ -0,0 +1,290 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+### reflection functions - convenience function relying on the low-level
+### functions .jcall/.jnew and friends
+
+### reflection tools (inofficial so far, because it returns strings
+### instead of the reflection objects - it's useful for quick checks,
+### though)
+.jmethods <- function(o, name=NULL, as.obj=FALSE) {
+  cl <- if (is(o, "jobjRef")) .jcall(o, "Ljava/lang/Class;", "getClass") else if (is(o, "jclassName")) o@jobj else .jfindClass(as.character(o))
+  ms<-.jcall(cl,"[Ljava/lang/reflect/Method;","getMethods")
+  if (isTRUE(as.obj)) return(ms)
+  ss<-unlist(lapply(ms,function(x) .jcall(x,"S","toString")))
+  if (!is.null(name))
+    grep(paste("\\.",name,"\\(",sep=''),ss,value=TRUE)
+  else
+    ss
+}
+
+.jconstructors <- function(o, as.obj=FALSE) {
+  cl <- if (is(o, "jobjRef")) .jcall(o, "Ljava/lang/Class;", "getClass") else if (is(o, "jclassName")) o@jobj else .jfindClass(as.character(o))
+  cs<-.jcall(cl,"[Ljava/lang/reflect/Constructor;","getConstructors")
+  if (isTRUE(as.obj)) return(cs)
+  unlist(lapply(cs,function(x) .jcall(x,"S","toString")))
+}
+
+### this list maps R class names to Java class names for which the constructor does the necessary conversion (for use in .jrcall)
+.class.to.jclass <-    c(character= "java/lang/String",
+                         jbyte    = "java/lang/Byte",
+                         integer  = "java/lang/Integer",
+                         numeric  = "java/lang/Double",
+                         logical  = "java/lang/Boolean",
+                         jlong    = "java/lang/Long",
+                         jchar    = "java/lang/Character",
+                         jshort   = "java/lang/Short",
+                         jfloat   = "java/lang/Float")
+
+### Java classes that have a corresponding primitive type and thus a corresponding TYPE field to use with scalars
+.primitive.classes = c("java/lang/Byte", "java/lang/Integer", "java/lang/Double", "java/lang/Boolean",
+                       "java/lang/Long", "java/lang/Character", "java/lang/Short", "java/lang/Float")
+
+### creates a valid java object
+### if a is already a java object reference, all is good
+### otherwise some primitive conversion occurs
+# this is used for internal purposes only, in particular 
+# it does not dispatch arrays to jrectRef
+._java_valid_object <- function(a) {
+  if (is(a, "jobjRef")) a 
+  else if (is.null(a)) .jnull() else {
+    cm <- match(class(a)[1], names(.class.to.jclass))
+    if (!any(is.na(cm))) { 
+    	if (length(a) == 1) { 
+    		y <- .jnew(.class.to.jclass[cm], a)
+    		if (.class.to.jclass[cm] %in% .primitive.classes) attr(y, "primitive") <- TRUE
+    		y 
+    	} else .jarray(a, dispatch = FALSE)
+    } else {
+      stop("Sorry, parameter type `", cm ,"' is ambiguous or not supported.")
+    }
+  }
+}
+
+### creates a list of valid java parameters, used in both .J and .jrcall
+._java_valid_objects_list <- function( ... )
+  lapply(list(...), ._java_valid_object )
+
+
+### returns a list of Class objects
+### this is used in both .J and .jrcall
+._isPrimitiveReference <- function(x) 
+  isTRUE(attr(x, "primitive"))
+
+._java_class <- function( x ){
+  if (is.jnull(x)) { if (is(x,"jobjRef")) .jfindClass(x@jclass) else .jclassObject } else {
+    if (._isPrimitiveReference(x)) .jfield(x, "Ljava/lang/Class;", "TYPE") else .jcall(x, "Ljava/lang/Class;", "getClass")
+  }
+}
+._java_class_list <- function( objects_list )
+	lapply(objects_list, ._java_class )
+                       
+### reflected call - this high-level call uses reflection to call a method
+### it is much less efficient than .jcall but doesn't require return type
+### specification or exact matching of parameter types
+.jrcall <- function(o, method, ..., simplify=TRUE) {
+  if (!is.character(method) | length(method) != 1)
+    stop("Invalid method name - must be exactly one character string.")
+  # FASTR <<<<<
+  # bypassing invokeMethod reflection call
+  
+  # if (inherits(o, "jobjRef") || inherits(o, "jarrayRef"))
+  #   cl <- .jcall(o, "Ljava/lang/Class;", "getClass")
+  # else
+  #   cl <- .jfindClass(o)
+  # if (is.null(cl))
+  #   stop("Cannot find class of the object.")
+  
+  # # p is a list of parameters that are formed solely by valid Java objects
+  # p <- ._java_valid_objects_list(...)
+  
+  # # list of classes
+  # pc <- ._java_class_list( p )
+  
+  # # invoke the method directly from the RJavaTools class
+  # # ( this throws the actual exception instead of an InvocationTargetException ) 
+  # j_p  <- .jarray(p, "java/lang/Object" , dispatch = FALSE )
+  # j_pc <- .jarray(pc, "java/lang/Class" , dispatch = FALSE )
+
+  # r <- .jcall( "RJavaTools", "Ljava/lang/Object;", "invokeMethod",
+  # 	cl, .jcast(if(inherits(o,"jobjRef") || inherits(o, "jarrayRef")) o else cl, "java/lang/Object"), 
+  # 	.jnew( "java/lang/String", method), 
+  # 	j_p, j_pc, use.true.class = TRUE, evalString = simplify, evalArray = FALSE )
+  
+  r <- .jcall( o, "Ljava/lang/Object;", method, ..., use.true.class = TRUE, evalString = simplify, evalArray = FALSE )
+  # FASTR >>>>>
+
+  # null is returned when the return type of the method is void
+  # TODO[romain]: not sure how to distinguish when the result is null but the 
+  #       return type is not null
+  if( is.jnull( r ) || is.null(r) ){ 
+  	return( invisible( NULL ) )
+  }
+  
+  # simplify if needed and return the object
+  if( is(r, "jarrayRef" ) && simplify ){
+  	._jarray_simplify( r )
+  } else if (simplify){
+  	  .jsimplify(r) 
+  } else  {
+  	  r
+  }
+}
+
+### reflected construction of java objects
+### This uses reflection to call a suitable constructor based 
+### on the classes of the ... it does not require exact match between 
+### the objects and the constructor parameters
+### This is to .jnew what .jrcall is to .jcall
+.J <- function(class, ...) {
+  # allow non-JNI specifiation
+  class <- gsub("\\.","/",class) 
+  
+  # p is a list of parameters that are formed solely by valid Java objects
+  p <- ._java_valid_objects_list(...)
+  
+  # list of classes
+  pc <- ._java_class_list( p )
+
+  # use RJavaTools to find create the object
+  o <- .jcall("RJavaTools", "Ljava/lang/Object;", 
+  	"newInstance", .jfindClass(class), 
+  	.jarray(p,"java/lang/Object", dispatch = FALSE ), 
+  	.jarray(pc,"java/lang/Class", dispatch = FALSE ), 
+  	evalString = FALSE, evalArray = FALSE, use.true.class = TRUE )
+  
+  o
+}
+
+## make sure Java's -2147483648 
+.iNA <- function(o, convert=TRUE) if(convert && is.na(o)) -2147483648.0 else o
+
+### simplify non-scalar reference to a scalar object if possible
+.jsimplify <- function(o, promote=FALSE) {
+  if (!inherits(o, "jobjRef") && !inherits(o, "jarrayRef"))
+    return(o)
+  cn <- .jclass(o, true=TRUE)
+  if (cn == "java.lang.Boolean") .jcall(o, "Z", "booleanValue") else
+  if (cn == "java.lang.Integer" || cn == "java.lang.Short" || cn == "java.lang.Character" || cn == "java.lang.Byte") .iNA(.jcall(o, "I", "intValue"), promote) else
+  if (cn == "java.lang.Number" || cn == "java.lang.Double" || cn == "java.lang.Long" || cn == "java.lang.Float") .jcall(o, "D", "doubleValue") else
+  if (cn == "java.lang.String") .jstrVal(.jcast(o, "java/lang/String")) else
+  o
+}
+
+#! ### get the value of a field (static class fields are not supported yet)
+#! .jrfield <- function(o, name, simplify=TRUE, true.class=TRUE) {
+#!   if (!inherits(o, "jobjRef") && !inherits(o, "jarrayRef") && !is.character(o))
+#!     stop("Object must be a Java reference or class name.")
+#!   if (is.character(o)) {
+#!     cl <- .jfindClass(o)
+#!     .jcheck(silent=TRUE)
+#!     if (is.null(cl))
+#!       stop("class not found")
+#!     o <- .jnull()
+#!   } else {
+#!     cl <- .jcall(o, "Ljava/lang/Class;", "getClass")
+#!     o <- .jcast(o, "java/lang/Object")
+#!   }
+#!   f <- .jcall(cl, "Ljava/lang/reflect/Field;", "getField", name)
+#!   r <- .jcall(f,"Ljava/lang/Object;","get",o)
+#!   if (simplify) r <- .jsimplify(r)
+#!   if (true.class && (inherits(r, "jobjRef") || inherits(r, "jarrayRef"))) {
+#!     cl <- .jcall(r, "Ljava/lang/Class;", "getClass")
+#!     cn <- .jcall(cl, "Ljava/lang/String;", "getName")
+#!     if (substr(cn,1,1) != '[')
+#!       r@jclass <- gsub("\\.","/",cn)
+#!   }
+#!   r
+#! }
+
+### list the fields of a class or object
+.jfields <- function(o, name=NULL, as.obj=FALSE) {
+  cl <- if (is(o, "jobjRef")) .jcall(o, "Ljava/lang/Class;", "getClass") else if (is(o, "jclassName")) o@jobj else .jfindClass(as.character(o))
+  f <- .jcall(cl, "[Ljava/lang/reflect/Field;", "getFields")
+  if (isTRUE(as.obj)) return(f)
+  fl <- unlist(lapply(f, function(x) .jcall(x, "S", "toString")))
+  if (!is.null(name)) grep(paste("\\.",name,"$",sep=''), fl) else fl
+}
+
+._must_be_character_of_length_one <- function(name){
+	if( !is.character(name) || length(name) != 1L ){
+		stop( "'name' must be a character vector of length one" )
+	}
+}
+### checks if the java object x has a field called name
+hasField <- function( x, name ){
+	._must_be_character_of_length_one(name)
+	.jcall("RJavaTools", "Z", "hasField", .jcast( x, "java/lang/Object" ), name)
+}
+
+hasJavaMethod <- function( x, name ){
+	._must_be_character_of_length_one(name)
+	.jcall("RJavaTools", "Z", "hasMethod", .jcast( x, "java/lang/Object" ), name)
+}
+
+hasClass <- function( x, name){
+	._must_be_character_of_length_one(name)
+	.jcall("RJavaTools", "Z", "hasClass", .jcast( x, "java/lang/Object" ), name)
+}
+
+### the following ones are needed for the static version of $
+classHasField <- function(x, name, static=FALSE) {
+	if (is(x, "jclassName")) x <- x@jobj else if (!is(x, "jobjRef")) x <- .jfindClass(as.character(x))
+	._must_be_character_of_length_one(name)
+	.jcall("RJavaTools", "Z", "classHasField", x, name, static)
+}
+
+classHasMethod <- function(x, name, static=FALSE) {
+	if (is(x, "jclassName")) x <- x@jobj else if (!is(x, "jobjRef")) x <- .jfindClass(as.character(x))
+	._must_be_character_of_length_one(name)
+	.jcall("RJavaTools", "Z", "classHasMethod", x, name, static)
+}
+
+classHasClass <- function(x, name, static=FALSE) {
+	if (is(x, "jclassName")) x <- x@jobj else if (!is(x, "jobjRef")) x <- .jfindClass(as.character(x))
+	._must_be_character_of_length_one(name)
+	.jcall("RJavaTools", "Z", "classHasClass", x, name, static)
+}
+
+### syntactic sugar to allow object$field and object$methods(...)
+### first attempts to find a field of that name and then a method
+._jobjRef_dollar <- function(x, name) {
+	if (hasField(x, name) ){
+		.jfield(x, , name)
+	} else if( hasJavaMethod( x, name ) ) {
+		function(...) .jrcall(x, name, ...)
+	} else if( hasClass(x, name) ) {
+		cl <- .jcall( x, "Ljava/lang/Class;", "getClass" )
+		inner.cl <- .jcall( "RJavaTools", "Ljava/lang/Class;", "getClass", cl, name, FALSE ) 
+		new("jclassName", name=.jcall(inner.cl, "S", "getName"), jobj=inner.cl)
+	} else if( is.character(name) && length(name) == 1L && name == "length" && isJavaArray(x) ){
+		length( x )
+	} else {
+		stop( sprintf( "no field, method or inner class called '%s' ", name ) ) 
+	}
+}
+setMethod("$", c(x="jobjRef"), ._jobjRef_dollar )
+
+### support for object$field<-...
+._jobjRef_dollargets <- function(x, name, value) {
+	if( hasField( x, name ) ){
+		.jfield(x, name) <- value
+	}
+	x
+}
+setMethod("$<-", c(x="jobjRef"), ._jobjRef_dollargets )
+
+# get a class name for an object
+.jclass <- function(o, true=TRUE) {
+  if (true) .jcall(.jcall(o, "Ljava/lang/Class;", "getClass"), "S", "getName")
+  else if( inherits( o, "jarrayRef" ) ) o@jsig else o@jclass
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rep.R b/com.oracle.truffle.r.pkgs/rJava/R/rep.R
new file mode 100644
index 0000000000000000000000000000000000000000..11491ea3ca89e3f3a741e5097467033100e5c3f7
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/rep.R
@@ -0,0 +1,41 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+# :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1:
+
+# {{{ rep
+setGeneric("rep")
+setMethod( "rep", "jobjRef", function( x, times = 1L, ... ){
+	.jcall( "RJavaArrayTools", "[Ljava/lang/Object;", "rep", 
+		.jcast(x), as.integer(times), evalArray = FALSE )
+} )
+setMethod( "rep", "jarrayRef", function(x, times = 1L, ...){
+	.NotYetImplemented()
+} )
+setMethod( "rep", "jrectRef", function(x, times = 1L, ...){
+	.NotYetImplemented()
+} )
+# }}}
+
+# {{{ clone 
+clone <- function( x, ... ){
+	UseMethod( "clone" )
+}
+clone.default <- function( x, ... ){
+	.NotYetImplemented()
+}
+setGeneric( "clone" )
+setMethod( "clone", "jobjRef", function(x, ...){
+	.jcall( "RJavaArrayTools", "Ljava/lang/Object;", "cloneObject", .jcast( x ) ) 
+} )
+setMethod( "clone", "jarrayRef", function(x, ...){ .NotYetImplemented( ) } )
+setMethod( "clone", "jrectRef", function(x, ...){ .NotYetImplemented( ) } )
+# }}}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rj.R b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
deleted file mode 100644
index 238d2d9a91884db9100cbf45a2f956a9cac61a68..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.pkgs/rJava/R/rj.R
+++ /dev/null
@@ -1,392 +0,0 @@
-##
- # This material is distributed under the GNU General Public License
- # Version 2. You may review the terms of this license at
- # http://www.gnu.org/licenses/gpl-2.0.html
- #
- # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
- # Copyright (c) 2017, Oracle and/or its affiliates
- #
- # All rights reserved.
-##
-
-#' @export
-.jnew <- function (class, ..., check = TRUE, silent = !check) {
-    class <- gsub("/", ".", as.character(class))
-    co <- new.java.class(class)
-    args <- .ellipsisToJObj(co, ...)
-    o <- .fastr.interop.try(function() { do.call(new.external, args) }, check)
-    new("jobjRef", jobj=o, jclass=class)
-}
-
-
-#' @export
-.jcall <- function (obj, returnSig = "V", method, ..., evalArray = TRUE, 
-    evalString = TRUE, check = TRUE, interface = "RcallMethod", 
-    simplify = FALSE, use.true.class = FALSE) {
-    obj <- .toJObj(obj)    
-
-    if (is.character(obj)) {
-        obj <- gsub("/", ".", as.character(obj))
-        obj <- new.java.class(obj)
-    }
-
-    args <- .ellipsisToJObj(...)
-    extMethod <- function(...) {obj[method](...)}
-    r <- .fastr.interop.try(function() { do.call(extMethod, args) }, check)
-    
-    if (is.null(r) && returnSig == "V") {
-        return(invisible(NULL))
-    }
-
-    .toS4(r)
-}
-
-#' @export
-.jfield <- function (obj, sig = NULL, name, true.class = is.null(sig), convert = TRUE) {
-    if (isS4(obj)) {
-        obj <- obj@jobj
-    }
-    if (is.character(obj)) {
-        co <- new.java.class(obj)
-        r <- co[name]
-    } else {
-        r <- obj[name]
-    }
-    .toS4(r)  
-}
-
-#' @export
-.jarray <- function (x, contents.class = NULL, dispatch = FALSE) {
-    as.java.array(x, ,TRUE)
-}
-
-#' @export
-.jevalArray <- function (x, contents.class = NULL, dispatch = FALSE) {
-    .fastr.interop.fromArray(x)
-}
-
-#' @export
-.jbyte <- function (x) {
-    storage.mode( x ) <- "integer"
-    new("jbyte", x)
-}
-
-#' @export
-.jchar <- function (x) {
-    storage.mode( x ) <- "character"
-    new("jchar", x)
-}
-
-#' @export
-.jshort <- function (x) {
-    storage.mode( x ) <- "integer"
-    new("jshort", x)
-}
-
-#' @export
-.jlong <- function (x) {
-    storage.mode( x ) <- "double"
-    new("jlong", x)
-}
-
-#' @export
-.jfloat <- function (x) {    
-    storage.mode( x ) <- "double"
-    new("jfloat", x )
-}
-
-#' @export
-J <- function (class, method, ...) {         
-    if (nargs() == 1L && missing(method)) {
-        if(inherits(class, "jclassName")) {
-            return(class)
-        } else if(is.character(class)) {
-            className <- class
-            jobj <- .jfindClass(class)
-        } else {            
-            className <- as.character(class)
-            jobj <- .jfindClass(className)
-        }
-        new("jclassName", name=className, jobj=jobj)
-    } else {
-        # .jrcall(class, method, ...)
-        .jcall(class, , method, ...)
-    }
-}
-
-#' @export
-.jpackage <- function (name, jars='*', morePaths='', nativeLibrary=FALSE, lib.loc=NULL) {
-    classes <- system.file("java", package = name, lib.loc = lib.loc)
-    if (nchar(classes)) {
-        .jaddClassPath(classes)
-        if (length(jars)) {
-            if (length(jars) == 1 && jars == "*") {
-                jars <- grep(".*\\.jar", list.files(classes, 
-                  full.names = TRUE), TRUE, value = TRUE)
-                if (length(jars)) 
-                  .jaddClassPath(jars)
-            }
-            else .jaddClassPath(paste(classes, jars, sep = .Platform$file.sep))
-        }
-    }
-    if (any(nchar(morePaths))) {
-        cl <- as.character(morePaths)
-        cl <- cl[nchar(cl) > 0]
-        .jaddClassPath(cl)
-    }
-    if (is.logical(nativeLibrary)) {
-        if (nativeLibrary) {
-            libs <- "libs"
-            if (nchar(.Platform$r_arch)) 
-                lib <- file.path("libs", .Platform$r_arch)
-            lib <- system.file(libs, paste(name, .Platform$dynlib.ext, 
-                sep = ""), package = name, lib.loc = lib.loc)
-            if (nchar(lib)) 
-                .jaddLibrary(name, lib)
-            else warning("Native library for `", name, "' could not be found.")
-        }
-    }
-    else {
-        .jaddLibrary(name, nativeLibrary)
-    }
-    invisible(TRUE)
-}
-
-#' @export
-.jaddClassPath <- function (path) {
-    java.addToClasspath(path)
-}
-
-#' @export
-.jfindClass <- function (cl, silent = FALSE) {
-    if (inherits(cl, "jclassName")) return(cl@jobj)
-    if (!is.character(cl) || length(cl)!=1) {
-        stop("invalid class name")
-    }
-
-    cl <- gsub("/", ".", as.character(cl))
-    javaClass <- new.java.class(cl)
-    cls <- new('jobjRef', jobj=javaClass, jclass='java.lang.Class', stringValue=paste0("class ", cl))
-    .jcheck(silent)
-    if (!silent && is.jnull(cls)) stop("class not found")
-    cls
-}
-
-.toS4 <- function(obj) {
-    res <- obj
-    if (is.external(obj)) {        
-        if (is.external.array(obj)) {
-            res <- as.vector(obj)
-        } else {
-            res <- new("jobjRef", jobj=obj, jclass=java.class(obj))
-        }        
-    } 
-    res
-}
-
-.ellipsisToJObj <- function(...) {
-    lapply(list(...), function(x) .toJObj(x))
-}
-
-.toJObj <- function(x) {
-    if (is(x, "jobjRef")) {
-        x@jobj
-    } else if (is(x, "jclassName")) {
-        x@jobj@jobj
-    } else if (is(x, "jbyte")) {
-        as.external.byte(x)    
-    } else if (is(x, "jchar")) {
-        as.external.char(x)    
-    } else if (is(x, "jfloat")) {
-        as.external.float(x)
-    } else if (is(x, "jlong")) {
-        as.external.long(x)
-    } else if (is(x, "jshort")) {
-        as.external.short(x)        
-    } else {
-        x
-    } 
-}
-
-#' @export
-.jgetEx <- function (clear = FALSE) {
-    interopEx <- .fastr.interop.getTryException(clear)
-    if (is.null(interopEx))
-        return(NULL)
-    new("jobjRef", jobj = interopEx, jclass = "java/lang/Throwable")
-}
-
-#' @export
-.jclear <- function () {
-     invisible(.fastr.interop.clearTryException())
-}
-
-#' @export
-.jinit <- function (classpath = NULL, parameters = getOption("java.parameters"), ..., silent = FALSE, force.init = FALSE) {
-    if (!is.null(classpath)) java.addToClasspath(classpath)
-}
-
-#' @export
-.jnull <- function (class = "java/lang/Object") {
-    new("jobjRef", jobj=NULL, jclass=class)
-}
-
-#' @export
-is.jnull <- function (x) {
-    is.null(x) || is.external.null(x) || (is(x,"jobjRef") && is.null(x@jobj))
-}
-
-#' @export
-.jaddLibrary <- function (name, path) {
-    cat(paste0("********************************************************\n",
-           "*** WARNING!!!\n",
-           "*** .jaddLibrary is not yet implemented.\n",
-           "*** Please ensure that all native libraries from:\n",
-           "*** ", path, "\n",
-           "*** are set on LD_LIBRARY_PATH or java.library.path\n",
-           "********************************************************\n"))
-}
-
-#' @export
-.jcast <- function(obj, new.class="java/lang/Object", check = FALSE, convert.array = FALSE) {
-  if (!is(obj,"jobjRef"))
-    stop("cannot cast anything but Java objects")
-  # TODO implement checks  
-  # if( check && !.jinstanceof( obj, new.class) ){
-  #     stop( sprintf( "cannot cast object to '%s'", new.class ) ) 
-  # }
-  
-  new.class <- gsub("\\.","/", as.character(new.class)) # allow non-JNI specifiation
-  # if( convert.array && !is( obj, "jarrayRef" ) && isJavaArray( obj ) ){
-  #    r <- .jcastToArray( obj, signature = new.class)
-  # } else {
-     r <- obj
-     r@jclass <- new.class
-  # }
-  r
-}
-
-#' @export
-.jstrVal <- function (obj) {
-    if (is.character(obj)) {
-        return(obj)
-    }    
-    r <- NULL
-    if (!is(obj, "jobjRef")) {
-        stop("can get value of Java objects only")
-    }
-    if(!is.null(obj@stringValue)) {
-        obj@stringValue
-    } else {
-        obj@jobj["toString"]()
-    }
-}
-
-.isJavaArray <- function(o){
-    is.external.array(o) && java.class(o) != NULL
-}
-
-#
-# S4
-#
-
-setClass("truffle.object", representation(jobj="ANY"))
-setClassUnion("TruffleObjectOrNull",members=c("truffle.object", "NULL"))
-setClassUnion("characterOrNull",members=c("character", "NULL"))
-
-#
-# jobjRef
-#
-setClass("jobjRef", representation(jobj="TruffleObjectOrNull", jclass="character", stringValue="characterOrNull"), prototype=list(jobj=NULL, jclass="java/lang/Object", stringValue=NULL))
-
-setMethod("$", c(x="jobjRef"), function(x, name) {
-    if(name %in% names(x@jobj)) {        
-        if(is.external.executable(x@jobj[name])) {
-            function(...) { .jcall(x, , name, ...) }    
-        } else {
-            .jfield(x, , name)                
-        }
-    } else if( is.character(name) && length(name) == 1L && name == "length" && is.external.array(x) ) {
-        length( x@obj )
-    } else {
-        stop(sprintf( "no field, method or inner class called '%s' ", name)) 
-    }
-})
-
-setMethod("$<-", c(x="jobjRef"), function(x, name, value) {
-    if(name %in% names(x@jobj)) {
-        if(!is.external.executable(x@jobj[name])) {
-            value <- .toJObj(value)
-            x@jobj[name] <- value
-        }
-    }
-    x
-})
-
-setMethod("show", c(object="jobjRef"), function(object) {
-    if (is.jnull(object)) {
-        show("Java-Object<null>") 
-    } else {
-        show(paste("Java-Object{", .jstrVal(object), "}", sep=''))
-    }
-    invisible(NULL)
-})
-
-#
-# jclassName
-#
-
-setClass("jclassName", representation(name="character", jobj="jobjRef"))
-setMethod("show", c(object="jclassName"), function(object) {
-    invisible(show(paste("Java-Class-Name:", object@name)))
-})
-setMethod("as.character", c(x="jclassName"), function(x, ...) x@name)
-setMethod("$", c(x="jclassName"), function(x, name) {
-    if(name == "class") {
-        x@jobj
-    } 
-    obj <- x@jobj@jobj
-    if(name %in% names(obj)) {
-        if(is.external.executable(obj[name])) {
-            function(...) { .jcall(obj, , name, ...) }    
-        } else {
-            .jfield(obj, , name)
-        }
-    } else {
-        stop("no static field, method or inner class called `", name, "' in `", x@name, "'")
-    } 
-})
-setMethod("$<-", c(x="jclassName"), function(x, name, value) {
-    value <- .toJObj(value)
-    x@jobj@jobj[name] <- value
-    x
-})
-
-# TODO makes CMD INSTALL complain
-# setGeneric("new")
-# setMethod("new", signature(Class="jclassName"), function(Class, ...) .jnew(Class, ...))
-
-setClass("jfloat", representation("array"))
-setClass("jlong", representation("array"))
-setClass("jbyte", representation("array"))
-setClass("jshort", representation("array"))
-setClass("jchar", representation("array"))
-
-#
-# noop stubs
-#
-
-#' @export
-.jsimplify <- function (x) {
-    x
-}
-
-#' @export
-.jcheck <- function(silent = FALSE) {
-    FALSE
-}
-
-#' @export
-.jthrow <- function (exception, message = NULL) {
-    # do nothing
-}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/serialize.R b/com.oracle.truffle.r.pkgs/rJava/R/serialize.R
new file mode 100644
index 0000000000000000000000000000000000000000..cb0ef7655508b6caff5f8e16dcbf7f7cdd7f15e1
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/serialize.R
@@ -0,0 +1,40 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## Java serialization/unserialization
+
+.jserialize <- function(o) {
+  if (!is(o, "jobjRef"))
+    stop("can serialize Java objects only")
+  .jcall("RJavaClassLoader","[B","toByte",.jcast(o, "java.lang.Object"))
+}
+
+.junserialize <- function(data) {
+  if (!is.raw(data))
+    stop("can de-serialize raw vectors only")
+  o <- .jcall("RJavaClassLoader","Ljava/lang/Object;","toObjectPL",.jarray(data, dispatch = FALSE))
+  if (!is.jnull(o)) {
+    cl<-try(.jclass(o), silent=TRUE)
+    if (all(class(cl) == "character"))
+      o@jclass <- gsub("\\.","/",cl)
+  }
+  o
+}
+
+.jcache <- function(o, update=TRUE) {
+  if (!is(o, "jobjRef"))
+    stop("o must be a Java object")
+  if (!is.null(update) && (!is.logical(update) || length(update) != 1))
+    stop("update must be TRUE, FALSE of NULL")
+  what <- update
+  if (isTRUE(what)) what <- .jserialize(o)
+  invisible(.Call(javaObjectCache, o@jobj, what))
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/tools.R b/com.oracle.truffle.r.pkgs/rJava/R/tools.R
new file mode 100644
index 0000000000000000000000000000000000000000..197ff8a40e9d381ac5a450f6eacc8ff1fd607a98
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/tools.R
@@ -0,0 +1,40 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+#' converts a java class name to jni notation
+tojni <- function( cl = "java.lang.Object" ){
+	gsub( "[.]", "/", cl )
+}
+
+tojniSignature <- function( cl ){
+	sig <- tojni( cl )
+
+        # TODO FASTR how comes that sig %in% c("boolean", "byte", "char", "double", "float", "int", "long", "short")
+	if( isPrimitiveTypeName(sig) || isPrimitiveArraySignature(sig) || sig %in% c("boolean", "byte", "char", "double", "float", "int", "long", "short")){
+		return( sig ) 
+	}
+	
+	n <- nchar( sig )
+	last <- substr( sig, n, n )
+	add.semi <- last != ";"
+	
+	first <- substr( sig, 1, 1 )
+	add.L <- ! first %in% c("L", "[" )
+	
+	sig <- if( !add.L && !add.semi) sig else sprintf( "%s%s%s", if( add.L ) "L" else "", sig, if( add.semi ) ";" else "" )
+	sig
+}
+
+#' converts jni notation to java notation
+tojava <- function( cl = "java/lang/Object" ){
+	gsub( "/", ".", cl )
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/with.R b/com.oracle.truffle.r.pkgs/rJava/R/with.R
new file mode 100644
index 0000000000000000000000000000000000000000..6fc68e76821ee16c374fd20de71e2a165a89c040
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/with.R
@@ -0,0 +1,186 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2010 Romain Francois <francoisromain@free.fr>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+## Author: Romain Francois <francoisromain@free.fr>
+
+._populate_with_fields_and_methods <- function( env, fields, methods, classes, data, only.static = FALSE ){
+	object <- if( only.static ) .jnull() else .jcast( data )
+	
+	# fields 
+	if( !is.jnull(fields) ) {
+		lapply( fields, function(x ){
+  		  n <- .jcall( x, "S", "getName" )
+  		  type <- .jcall( .jcall( x, "Ljava/lang/Class;", "getType"), "Ljava/lang/String;" , "getName" )
+  		  suffix <- switch( type, 
+  		  	"boolean" = "Boolean", 
+  		  	"byte" = "Byte", 
+  		  	"char" = "Char",
+  		  	"double" = "Double", 
+  		  	"float" = "Float", 
+  		  	"int" = "Int", 
+  		  	"long" = "Long", 
+  		  	"short" = "Short",
+  		  	"" )
+  		  target <- switch( type,
+  		  	"boolean" = "Z", 
+  		  	"byte" = "B", 
+  		  	"char" = "C",
+  		  	"double" = "D", 
+  		  	"float" = "F", 
+  		  	"int" = "I", 
+  		  	"long" = "L", 
+  		  	"short" = "S",
+  		  	"Ljava/lang/Object;" )
+  		  set_method <- sprintf( "set%s", suffix)
+  		  get_method <- sprintf( "get%s", suffix )
+  		  	
+  		  makeActiveBinding( n, function(v){
+  		    if( missing(v) ){
+  		      ## get
+  		      .jcall( x, target, get_method, object )
+  		    } else {
+  		      ## set
+  		      .jcall( x, "V", set_method , object, v )
+  		    }
+  		  }, env )
+  		} )
+  	}
+  	
+  	# methods
+  	if( !is.jnull(methods) ){
+  		done.this <- NULL
+  		lapply( methods, function(m){
+  			n <- .jcall( m, "S", "getName" )
+  			if( n %in% done.this ) return()
+  		  fallback <- tryCatch( match.fun( n ), error = function(e) NULL )
+  		  assign( n, function(...) {
+  		    tryCatch( .jrcall( if(only.static) data@name else data , n, ...), error = function(e){
+  		      if( !is.null(fallback) && inherits(fallback, "function") ){
+  		        fallback( ... )
+  		      }
+  		    } )
+  		  }, env )
+  		  done.this <<- c( done.this, n )
+  		} )
+  	}
+  	
+  	# classes
+  	if( !is.jnull( classes ) ){
+  		lapply( classes, function( cl ){
+  			name <- .jcall( cl, "S", "getSimpleName" )
+  			assign( name, new("jclassName", name=.jcall(cl, "S", "getName"), jobj=cl), env )
+  		} )
+  	}
+}
+grabDots <- function( env, ...){
+  dots <- list(...)
+  if( length( dots ) ){
+  	dots.names <- names(dots)
+  	sapply( dots.names, function( name ){
+  		if( name != "" ){
+  			assign( name, dots[[ name ]], env )
+  		}
+  	} )
+  	
+  }
+}
+
+with.jobjRef <- function( data, expr, ...){
+  env <- new.env( parent = parent.frame() )
+  clazz <- .jcall( data, "Ljava/lang/Class;", "getClass")
+  
+  fields  <- .jcall( clazz, "[Ljava/lang/reflect/Field;", "getFields" )
+  methods <- .jcall( clazz, "[Ljava/lang/reflect/Method;", "getMethods" )
+  classes <- .jcall( clazz, "[Ljava/lang/Class;" , "getClasses" )
+  ._populate_with_fields_and_methods( env, fields, methods, classes, data, only.static = FALSE )
+
+  assign( "this", data, env )
+
+  grabDots( env, ... )
+  
+  eval( substitute( expr ), env )
+}
+
+within.jobjRef <- function(data, expr, ... ){
+  call <- match.call()
+  call[[1]] <- as.name("with.jobjRef")
+  eval( call, parent.frame() )
+  data
+}
+
+with.jarrayRef <- function( data, expr, ...){
+  env <- new.env( parent = environment() )
+  clazz <- .jcall( data, "Ljava/lang/Class;", "getClass")
+  
+  fields  <- .jcall( clazz, "[Ljava/lang/reflect/Field;", "getFields" )
+  methods <- .jcall( clazz, "[Ljava/lang/reflect/Method;", "getMethods" )
+  classes <- .jcall( clazz, "[Ljava/lang/Class;" , "getClasses" )
+  ._populate_with_fields_and_methods( env, fields, methods, classes, data, only.static = FALSE )
+
+  assign( "this", data, env )
+
+  # add "length" pseudo field
+  makeActiveBinding( "length", function(v){
+  	if( missing( v ) ){
+  		._length_java_array( data )
+  	} else{
+  		stop( "cannot modify length of java array" ) 
+  	}
+  }, env )
+  
+  grabDots( env, ... )
+  
+  eval( substitute( expr ), env )
+}
+
+within.jarrayRef <- function(data, expr, ... ){
+  call <- match.call()
+  call[[1]] <- as.name("with.jarrayRef")
+  eval( call, parent.frame() )
+  data
+}
+
+with.jclassName <- function( data, expr, ... ){
+	env <- new.env( parent = environment() )
+	clazz <- data@jobj
+	
+	static_fields  <- .jcall( "RJavaTools", "[Ljava/lang/reflect/Field;",  "getStaticFields",  clazz )
+	static_methods <- .jcall( "RJavaTools", "[Ljava/lang/reflect/Method;",  "getStaticMethods",  clazz )
+	static_classes <- .jcall( clazz, "[Ljava/lang/Class;",  "getClasses" )
+	
+	._populate_with_fields_and_methods( env, static_fields, 
+		static_methods, static_classes, data, only.static = TRUE )
+	
+	grabDots( env, ... )
+	eval( substitute( expr ), env )
+}
+
+within.jclassName <- function(data, expr, ... ){
+  call <- match.call()
+  call[[1]] <- as.name("with.jclassName")
+  eval( call, parent.frame() )
+  data
+}
+
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/zzz.R b/com.oracle.truffle.r.pkgs/rJava/R/zzz.R
new file mode 100644
index 0000000000000000000000000000000000000000..c71da4a48727b3c5db780d13d2499e7dd7519910
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/zzz.R
@@ -0,0 +1,33 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+.onLoad <- function(libname, pkgname) {
+  # FASTR <<<<<
+  #Sys.setenv("LD_LIBRARY_PATH"=paste(Sys.getenv("LD_LIBRARY_PATH"),"@JAVA_LD@",sep=':'))
+  ## On OS X with Oracle Java we may need to work around Oracle bug:
+  ## https://bugs.openjdk.java.net/browse/JDK-7131356
+  #if (length(grep("^darwin", R.version$os)) && file.exists("/usr/libexec/java_home")) {
+  #   jh <- Sys.getenv("JAVA_HOME")
+  #   if (!nzchar(jh)) jh <- system("/usr/libexec/java_home", intern=TRUE)[1L]
+  #   if (file.exists(file.path(jh, "jre/lib"))) jh <- file.path(jh, "jre")
+  #   if (file.exists(jli <- file.path(jh, "lib/jli/libjli.dylib"))) {
+  #     dyn.load(jli, FALSE)
+  #     dlp <- Sys.getenv("DYLD_LIBRARY_PATH")
+  #     if (nzchar(dlp)) dlp <- paste0(":", dlp)
+  #     if (file.exists(file.path(jh, "lib/server/libjvm.dylib")))
+  #       Sys.setenv(DYLD_LIBRARY_PATH=paste0(file.path(jh, "lib/server"), dlp))
+  #   }
+  #}
+  #library.dynam("rJava", pkgname, libname)
+  # FASTR >>>>>
+  # pass on to the system-independent part
+  .jfirst(libname, pkgname)
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/Exceptions.Rd b/com.oracle.truffle.r.pkgs/rJava/man/Exceptions.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..e0907a2146f080b834e543fda365ea66d731de5f
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/Exceptions.Rd
@@ -0,0 +1,55 @@
+\name{Exceptions}
+\alias{Exceptions}
+\alias{$.Throwable}
+\alias{$<-.Throwable}
+\title{Exception handling}
+\description{R handling of java exception}
+\usage{
+	\S3method{$}{Throwable}(x, name )
+	\S3method{$}{Throwable}(x, name ) <- value
+}
+\arguments{
+	\item{x}{condition}
+	\item{name}{...}
+	\item{value}{...}
+}
+\details{
+	Java exceptions are mapped to R conditions that are relayed by the
+	\code{\link{stop}} function. 
+	
+	The R condition contains the actual exception object as the 
+	\code{jobj} item.
+	
+	The class name of the R condition is made of a vector 
+	of simple java class names, the class names without their package
+	path. This allows the R code to use direct handlers similar to 
+	direct exception handlers in java. See the example below. 
+}
+\examples{
+\dontshow{.jinit()}
+
+Integer <- J("java.lang.Integer")
+tryCatch( Integer$parseInt( "10.." ), NumberFormatException = function(e){
+	e$jobj$printStackTrace() 
+} )
+
+# the dollar method is also implemented for Throwable conditions, 
+# so that syntactic sugar can be used on condition objects
+# however, in the example below e is __not__ a jobjRef object reference
+tryCatch( Integer$parseInt( "10.." ), NumberFormatException = function(e){
+	e$printStackTrace() 
+} )
+
+
+\dontshow{
+tryCatch( Integer$parseInt( "10.." ), NumberFormatException = function(e){
+	classes <- class( e )
+	stopifnot( "NumberFormatException" \%in\% classes )
+	stopifnot( "Exception" \%in\% classes )
+	stopifnot( "Object" \%in\% classes )
+	stopifnot( "error" \%in\% classes )
+	stopifnot( "condition" \%in\% classes )
+} )
+}
+
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/J.Rd b/com.oracle.truffle.r.pkgs/rJava/man/J.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..fa5a3e2b16bc100f19d107089996323c85277161
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/J.Rd
@@ -0,0 +1,76 @@
+\name{J}
+\alias{J}
+\title{
+High level API for accessing Java
+}
+\description{
+\code{J} creates a Java class reference or calls a Java method
+}
+\usage{
+J(class, method, ...)
+}
+\arguments{
+  \item{class}{
+    java object reference or fully qualified class name in JNI
+    notation (e.g "java/lang/String" ) or standard java notation (e.g
+    "java.lang.String")
+  }
+  \item{method}{
+    if present then \code{J} results in a method call, otherwise it
+    just creates a class name reference.
+  }
+  \item{\dots}{
+    optional parameters that will be passed to the method (if the
+    \code{method} argument is present)
+  }
+}
+\details{
+\code{J} is the high-level access to Java.
+
+If the \code{method} argument is missing then \code{code} must be a
+class name and \code{J} creates a class name reference that can be
+used either in a call to \code{new} to create a new Java object
+(e.g. \code{new(J("java.lang.String"), "foo")}) or with \code{$}
+operator to call a static method
+(e.g. \code{J("java.lang.Double")$parseDouble("10.2")}.)
+
+If the \code{method} argument is present then it must be a string
+vector of length one which defines the method to be called on the
+object.
+}
+\value{
+  If \code{method} is missing the the returned value is an object of
+  the class \code{jclassName}. Otherwise the value is the result of
+  the method invocation. In the latter case Java exceptions may be
+  thrown and the function doesn't return.
+}
+\note{
+\code{J} is a high-level API which is slower than \code{\link{.jnew}}
+or \code{\link{.jcall}} since it has to use reflection to find the
+most suitable method.
+}
+\seealso{
+\code{\link{.jcall}}, \code{\link{.jnew}}
+}
+\examples{
+\dontshow{.jinit()}
+
+if (!nzchar(Sys.getenv("NOAWT"))) {
+  f <- new(J("java.awt.Frame"), "Hello")
+  f$setVisible(TRUE)
+}
+
+J("java.lang.Double")$parseDouble("10.2")
+J("java.lang.Double", "parseDouble", "10.2" )
+
+Double <- J("java.lang.Double")
+Double$parseDouble( "10.2")
+
+# String[] strings = new String[]{ "string", "array" } ;
+  strings <- .jarray( c("string", "array") )
+# this uses the JList( Object[] ) constructor 
+# even though the "strings" parameter is a String[] 
+  l <- new( J("javax.swing.JList"), strings)
+
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/accessOp.Rd b/com.oracle.truffle.r.pkgs/rJava/man/accessOp.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..a51155d8c857dab587a9321b0825cb8319dbd47a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/accessOp.Rd
@@ -0,0 +1,83 @@
+\name{JavaAccess}
+\alias{$,jobjRef-method}
+\alias{$,jclassName-method}
+\alias{$<-,jobjRef-method}
+\alias{$<-,jclassName-method}
+\alias{names,jobjRef-method}
+\alias{names,jclassName-method}
+\alias{names,jarrayRef-method}
+\alias{names,jrectRef-method}
+\alias{.DollarNames.jobjRef}
+\alias{.DollarNames.jclassName}
+\alias{.DollarNames.jarrayRef}
+\alias{.DollarNames.jrectRef}
+
+\title{
+  Field/method operator for Java objects
+}
+\description{
+  The \code{$} operator for \code{jobjRef} Java object references provides convenience access to object attributes and calling Java methods.
+}
+\usage{
+	\S3method{.DollarNames}{jobjRef}   (x, pattern = "" )
+	\S3method{.DollarNames}{jarrayRef} (x, pattern = "" )
+	\S3method{.DollarNames}{jrectRef}  (x, pattern = "" )
+	\S3method{.DollarNames}{jclassName}(x, pattern = "" )
+}
+\arguments{
+	\item{x}{object to complete}
+	\item{pattern}{pattern}
+}
+\section{Methods}{
+  \describe{
+    \item{\code{$}}{\code{signature(x = "jobjRef")}: ... }
+    \item{\code{$}}{\code{signature(x = "jclassName")}: ... }
+    \item{\code{$<-}}{\code{signature(x = "jobjRef")}: ... }
+    \item{\code{$<-}}{\code{signature(x = "jclassName")}: ... }
+    \item{\code{names}}{\code{signature(x = "jobjRef")}: ... }
+    \item{\code{names}}{\code{signature(x = "jarrayRef")}: ... }
+    \item{\code{names}}{\code{signature(x = "jrectRef")}: ... }
+    \item{\code{names}}{\code{signature(x = "jclassName")}: ... }
+	 }
+}
+\details{
+  rJava provies two levels of API: low-level JNI-API in the form of \code{\link{.jcall}} function and high-level reflection API based on the \code{$} operator. The former is very fast, but inflexible. The latter is a convenient way to use Java-like programming at the cost of performance. The reflection API is build around the \code{$} operator on \code{\link{jobjRef-class}} objects that allows to access Java attributes and call object methods.
+
+ \code{$} returns either the value of the attribute or calls a method, depending on which name matches first.
+
+ \code{$<-} assigns a value to the corresponding Java attribute.
+
+ \code{names} and \code{.DollarNames} returns all fields and methods associated with the object. 
+ Method names are followed by \code{(} or \code{()} depending on arity. 
+ This use of names is mainly useful for code completion, it is not intended to be used programmatically.
+
+ This is just a convenience API. Internally all calls are mapped into \code{\link{.jcall}} calls, therefore the calling conventions and returning objects use the same rules. For time-critical Java calls \code{\link{.jcall}} should be used directly.
+}
+\seealso{
+  \code{\link{J}}, \code{\link{.jcall}}, \code{\link{.jnew}}, \code{\link{jobjRef-class}}
+}
+\examples{
+\dontshow{.jinit()}
+
+v <- new(J("java.lang.String"), "Hello World!")
+v$length()
+v$indexOf("World")
+names(v)
+
+\dontshow{
+stopifnot( v$length() == 12L )
+stopifnot( v$indexOf("World") == 6L ) 
+}
+
+J("java.lang.String")$valueOf(10)
+
+Double <- J("java.lang.Double")
+# the class pseudo field - instance of Class for the associated class
+# similar to java Double.class
+Double$class 
+\dontshow{
+	stopifnot( Double$class$getName() == "java.lang.Double" )
+}
+
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/aslist.Rd b/com.oracle.truffle.r.pkgs/rJava/man/aslist.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..a23e34e4abf2fba7c3136f5d3bdf3d1c4145dad2
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/aslist.Rd
@@ -0,0 +1,59 @@
+\name{aslist}
+\alias{as.list.jobjRef}
+\alias{as.list.jarrayRef}
+\alias{as.list.jrectRef}
+\title{
+Converts java objects or arrays to R lists
+}
+\description{
+	\code{as.list} is implemented for java objects and java arrays
+	to facilitate using \code{lapply} calls over elements of a java array
+	or items of an Iterator associated with an Iterable object
+	
+	For java array references, \code{as.list} is mapped to
+	\code{\link{.jevalArray}}
+	
+	For java objects that implement the Iterable interface, 
+	the list is created by iterating over the associated iterator
+}
+\usage{
+\S3method{as.list}{jobjRef}(x, ...)
+\S3method{as.list}{jarrayRef}(x, ...)
+}
+\arguments{
+  \item{x}{java array or Iterable java object}
+  \item{\dots}{ignored}
+}
+\value{
+An R list, or vector.
+}
+\note{
+The function is not intended to be called directly. It is implemented
+so that java arrays or Iterable java objects can be used as the first 
+argument of \code{\link{lapply}}
+}
+\seealso{
+	\code{\link{.jevalArray}}, \code{\link{lapply}}
+}
+\examples{
+\dontshow{.jinit()}
+  # lapplying over a java array
+  a <- .jarray( list( 
+	.jnew( "java/awt/Point", 10L, 10L ), 
+	.jnew( "java/awt/Point", 30L, 30L )
+  ) )
+  lapply( a, function(point){ 
+	with(point, { 
+		(x + y ) ^ 2
+	} )
+  } )
+
+# lapply over a Vector (implements Iterable)
+v <- .jnew("java/util/Vector")
+v$add( "foo" )
+v$add( .jnew("java/lang/Double", 10.2 ) )
+sapply( v, function(item) item$getClass()$getName() )
+
+}
+\keyword{ programming }
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/clone.Rd b/com.oracle.truffle.r.pkgs/rJava/man/clone.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..5a43481617fee868da07054f5921b2d276b9c0b6
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/clone.Rd
@@ -0,0 +1,51 @@
+\name{clone}
+\alias{clone}
+\alias{clone,jobjRef-method}
+\alias{clone,jarrayRef-method}
+\alias{clone,jrectRef-method}
+
+\title{
+Object cloner
+}
+\description{
+Generic function to clone objects
+}
+\usage{
+clone(x, ...)
+}
+\section{Methods}{
+  \describe{
+    \item{clone}{\code{signature(x = "jobjRef")}: clone a java object reference (must implement Cloneable) }
+    \item{clone}{\code{signature(x = "jarrayRef")}: clone a java rugged array (not yet implemented) }
+    \item{clone}{\code{signature(x = "jrectRef")}: clone a java rectangular array (not yet implemented) }
+  }
+}
+
+\arguments{
+  \item{x}{An object to clone}
+  \item{\dots}{Further arguments, ignored}
+}
+\value{
+A clone of the object
+}
+\section{Warning}{
+	The implementation of clone for java object references uses
+	the clone method of the Object class. The reading of its description
+	in the java help page is \emph{strongly} recommended. 
+}
+
+\examples{
+\dontshow{.jinit()}
+
+  p1 <- .jnew("java/awt/Point" )
+  p2 <- clone( p1 )
+  p2$move( 10L, 10L )
+  p1$getX() 
+
+  # check that p1 and p2 are not references to the same java object
+  stopifnot( p1$getX() == 0 )
+  stopifnot( p2$getX() == 10 )
+
+}
+\keyword{ programming }
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/instanceof.Rd b/com.oracle.truffle.r.pkgs/rJava/man/instanceof.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..39fd12efa70e2f84abd0e65ff58b1997848bfa91
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/instanceof.Rd
@@ -0,0 +1,61 @@
+\name{.jinstanceof}
+\Rdversion{1.1}
+\alias{\%instanceof\%}
+\alias{.jinstanceof}
+\title{
+Is a java object an instance of a given java class
+}
+\description{
+Is a java object an instance of a given java class
+}
+\usage{
+o \%instanceof\% cl
+.jinstanceof( o, cl )
+}
+\arguments{
+  \item{o}{java object reference}
+  \item{cl}{java class. This can be a character vector of length one
+  giving the name of the class, or another java object, or an instance
+  of the Class class, or a object of class \code{jclassName}.}
+}
+\value{
+TRUE if o is an instance of cl
+}
+\author{
+Romain Francois <francoisromain@free.fr>
+}
+\examples{
+\dontshow{
+.jinit()
+}
+Double <- J("java.lang.Double")
+d <- new( Double, "10.2" )
+
+# character
+d \%instanceof\% "java.lang.Double"
+d \%instanceof\% "java.lang.Number"
+
+# jclassName
+d \%instanceof\% Double
+
+# instance of Class
+Double.class <- Double@jobj
+d \%instanceof\% Double.class
+
+# other object
+other.double <- new( Double, 10.2 )
+d \%instanceof\% other.double
+
+\dontshow{
+% simple unit tests
+stopifnot( d \%instanceof\% "java.lang.Double" )
+stopifnot( d \%instanceof\% "java.lang.Number" )
+stopifnot( d \%instanceof\% "java.lang.Object" )
+stopifnot( d \%instanceof\% Double.class )
+stopifnot( d \%instanceof\% other.double )
+stopifnot( d \%instanceof\% Double )
+}
+
+}
+\keyword{ interface }
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jarray.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jarray.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..ac531b4930fc19bb02eca57713534738b50bf6a1
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jarray.Rd
@@ -0,0 +1,100 @@
+\name{jarray}
+\alias{.jarray}
+\alias{.jevalArray}
+\title{
+  Java array handling functions
+}
+\description{
+  \code{.jarray} takes a vector (or a list of Java references) as its
+  argument, creates a Java array containing the elements of the vector
+  (or list) and returns a reference to such newly created array.
+
+  \code{.jevalArray} takes a reference to a Java array and returns its
+  contents (if possible).
+}
+\usage{
+.jarray(x, contents.class = NULL, dispatch = FALSE)
+.jevalArray(obj, rawJNIRefSignature = NULL, silent = FALSE, simplify = FALSE)
+}
+\arguments{
+  \item{x}{vector or a list of Java references}
+  \item{contents.class}{common class of the contained objects, see
+    details}
+  \item{obj}{Java object reference to an array that is to be evaluated}
+  \item{rawJNIRefSignature}{JNI signature that whould be used for
+    conversion. If set to \code{NULL}, the signature is detected
+    automatically.}
+  \item{silent}{if set to true, warnings are suppressed}
+  \item{dispatch}{logical. If \code{TRUE} the code attemps to dispatch
+  to either a \code{jarrayRef} object for rugged arrays and
+  \code{jrectRef} objects for rectangular arrays, creating possibly a
+  multi-dimensional object in Java (e.g., when used with a matrix).}
+  \item{simplify}{if set to \code{TRUE} more than two-dimensional arrays
+  are converted to native obejcts (e.g., matrices) if their type and
+  size matches (essentially the inverse for objects created with
+  \code{dispatch=TRUE}).}
+}
+\value{
+  \code{.jarray} returns a Java array reference (\code{jarrayRef} or \code{jrectRef}) to an
+  array created with the supplied contents.
+
+  \code{.jevalArray} returns the contents of the array object.
+}
+\details{
+  \code{.jarray}: The input can be either a vector of some sort (such as
+  numeric, integer, logical, ...) or a list of Java references. The
+  contents is pushed to the Java side and a corresponding array is
+  created. The type of the array depends on the input vector type. For
+  example numeric vector creates \code{double[]} array, integer vector
+  creates \code{int[]} array, character vector \code{String[]} array and
+  so on. If \code{x} is a list, it must contain Java references only (or
+  \code{NULL}s which will be treated as \code{NULL} references).
+
+  The \code{contents.class} parameter is used only if \code{x} is a list
+  of Java object references and it can specify the class that will be
+  used for all objects in the array. If set to \code{NULL} no assumption
+  is made and \code{java/lang/Object} will be used. Use with care and
+  only if you know what you're doing - you can always use
+  \code{\link{.jcast}} to cast the entire array to another type even if
+  you use a more general object type. One typical use is to construct
+  multi-dimensional arrays which mandates passing the array type as
+  \code{contents.class}.
+
+  The result is a reference to the newly created array.
+
+  The inverse function which fetches the elements of an array reference
+  is \code{.jevalArray}.
+
+  \code{.jevalArray} currently supports only a subset of all possible
+  array types. Recursive arrays are handled by returning a list of
+  references which can then be evaluated separately. The only exception
+  is \code{simplify=TRUE} in which case \code{.jevalArray} arrempts to
+  convert multi-dimensional arrays into native R type if there is a
+  such. This only works for rectangular arrays of the same basic type
+  (i.e. the length and type of each referenced array is the same -
+  sometimes matrices are represented that way in Java).
+}
+\examples{
+\dontshow{.jinit()}
+a <- .jarray(1:10)
+print(a)
+.jevalArray(a)
+b <- .jarray(c("hello","world"))
+print(b)
+c <- .jarray(list(a,b))
+print(c)
+# simple .jevalArray will return a list of references
+print(l <- .jevalArray(c))
+# to convert it back, use lapply
+lapply(l, .jevalArray)
+
+# two-dimensional array resulting in int[2][10]
+d <- .jarray(list(a,a),"[I")
+print(d)
+# use dispatch to convert a matrix to [[D
+e <- .jarray(matrix(1:12/2, 3), dispatch=TRUE)
+print(e)
+# simplify it back to a matrix
+.jevalArray(e, simplify=TRUE)
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jarrayRef-class.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jarrayRef-class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..e39e4d5917f0ffff8687af7d2f5d1d566ea31263
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jarrayRef-class.Rd
@@ -0,0 +1,65 @@
+\name{jarrayRef-class}
+\docType{class}
+\alias{jarrayRef-class}
+\alias{[,jarrayRef-method}
+\alias{[[,jarrayRef-method}
+\alias{[[<-,jarrayRef-method}
+\alias{head,jarrayRef-method}
+\alias{tail,jarrayRef-method}
+\alias{length,jarrayRef-method}
+\alias{str,jarrayRef-method}
+\alias{unique,jarrayRef-method}
+\alias{duplicated,jarrayRef-method}
+\alias{anyDuplicated,jarrayRef-method}
+\alias{sort,jarrayRef-method}
+\alias{rev,jarrayRef-method}
+\alias{min,jarrayRef-method}
+\alias{max,jarrayRef-method}
+\alias{range,jarrayRef-method}
+
+\title{Class "jarrayRef" Reference to an array Java object }
+\description{ This class is a subclass of \link{jobjRef-class} 
+and represents a reference to an array Java object. }
+\section{Objects from the Class}{
+Objects cannot be created directly, but only as the return
+value of \code{\link{.jcall}} function.
+}
+\section{Slots}{
+  \describe{
+    \item{\code{jsig}:}{JNI signature of the array type}
+    \item{\code{jobj}:}{Internal identifier of the object}
+    \item{\code{jclass}:}{Inherited from \code{jobjRef}, but unspecified}
+  }
+}
+\section{Methods}{
+  \describe{
+  	  \item{[}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{[[}{\code{signature(x = "jarrayRef")}: R indexing of java arrays }
+    \item{[[<-}{\code{signature(x = "jarrayRef")}: replacement method }
+    \item{\code{head}}{\code{signature(x = "jarrayRef")}: head of the java array }
+    \item{\code{tail}}{\code{signature(x = "jarrayRef")}: tail of the java array }
+    \item{length}{\code{signature(object = "jarrayRef")}: Number of java objects in the java array }
+    \item{str}{\code{signature(object = "jarrayRef")}: ... }
+    \item{unique}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{duplicated}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{anyDuplicated}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{sort}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{rev}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{min}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{max}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+    \item{range}{\code{signature(x = "jarrayRef")}: \emph{not yet implemented} }
+  }
+}
+\section{Extends}{
+Class \code{"\linkS4class{jobjRef}"}, directly.
+}
+\author{ Simon Urbanek }
+\seealso{
+  \code{\link{.jcall}} or \code{\linkS4class{jobjRef}}
+  \code{\linkS4class{jrectRef}} for rectangular arrays
+}
+% need to find examples of rugged arrays
+% \examples{
+% \dontshow{.jinit()}
+% }
+\keyword{classes}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/java-tools.Rd b/com.oracle.truffle.r.pkgs/rJava/man/java-tools.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..925c883c03ede1f7c4337420209c4a7c41d62c58
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/java-tools.Rd
@@ -0,0 +1,22 @@
+\name{java-tools}
+\alias{java-tools}
+\title{java tools used internally in rJava}
+\description{java tools used internally in rJava}
+\examples{
+\dontshow{
+# running the java unit tests from the R examples
+.jinit()
+J("RJavaTools_Test")$runtests()
+J("RJavaArrayTools_Test")$runtests()
+J("ArrayWrapper_Test")$runtests()
+J("RectangularArrayBuilder_Test")$runtests()
+
+
+  p <- .jnew( "java/awt/Point" )
+  classes <- .Call( "RgetSimpleClassNames", p@jobj, TRUE, PACKAGE = "rJava" )
+  stopifnot( all( c( "Point", "Point2D", "Object", "error", "condition" ) \%in\% classes ) )
+  classes <- .Call( "RgetSimpleClassNames", p@jobj, FALSE, PACKAGE = "rJava" )
+  stopifnot( all( c( "Point", "Point2D", "Object" )  \%in\% classes ) )
+
+}
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/javaImport.Rd b/com.oracle.truffle.r.pkgs/rJava/man/javaImport.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..cdee86972a7771499e17cf1749d35c3b616c2027
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/javaImport.Rd
@@ -0,0 +1,56 @@
+\name{javaImport}
+\alias{javaImport}
+\title{
+Attach mechanism for java packages
+}
+\description{
+The \code{javaImport} function creates an item on R's
+search that maps names to class names references found in 
+one or several "imported" java packages.
+}
+\usage{
+javaImport(packages = "java.lang")
+}
+\arguments{
+  \item{packages}{character vector containing java package paths}
+}
+\value{
+An external pointer to a java specific \code{UserDefinedDatabase} object
+}
+\references{
+	\emph{User-Defined Tables in the R Search Path}. Duncan Temple Lang. December 4, 2001
+	\url{http://www.omegahat.org/RObjectTables/}
+}
+\author{
+Romain Francois <francoisromain@free.fr>
+}
+\note{
+Currently the list of objects in the imported package is populated
+as new objects are found, \emph{not} at creation time.
+}
+\section{Warning}{
+This feature is experimental. Use with caution, and don't forget to
+detach.
+}
+\seealso{
+\code{\link{attach}}
+}
+\examples{
+\dontrun{
+	attach( javaImport( "java.util" ), pos = 2 , name = "java:java.util" )
+	
+	# now we can just do something like this 
+	v <- new( Vector )
+	v$add( "foobar" )
+	ls( pos = 2 )
+	
+	# or this
+	m <- new( HashMap )
+	m$put( "foo", "bar" )
+	ls( pos = 2 )
+	
+	# or even this :
+	Collections$EMPTY_MAP
+}
+}
+\keyword{ programming }
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jcall.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jcall.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..b8e801b97c8f25eceb1799f6dac1a96624ef2cfc
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jcall.Rd
@@ -0,0 +1,110 @@
+\name{jcall}
+\alias{.jcall}
+\title{
+  Call a Java method
+}
+\description{
+  \code{.jcall} calls a Java method with the supplied arguments.
+}
+\usage{
+.jcall(obj, returnSig = "V", method, ..., evalArray = TRUE, 
+    evalString = TRUE, check = TRUE, interface = "RcallMethod", 
+    simplify = FALSE, use.true.class = FALSE)
+}
+\arguments{
+  \item{obj}{Java object (\code{jobjRef} as returned by
+    \code{\link{.jcall}} or \code{\link{.jnew}}) or fully qualified
+    class name in JNI notation (e.g. \code{"java/lang/String"}).}
+  \item{returnSig}{Return signature in JNI notation (e.g. "V" for void,
+    "[I" for \code{int[]} etc.). For convenience additional type
+    \code{"S"} is supported and expanded to
+    \code{"Ljava/lang/String;"}, re-mapping \code{"T"} to represent the
+    type \code{short}.}
+  \item{method}{The name of the method to be called}
+  \item{...}{
+    Any parametes that will be passed to the Java method. The parameter
+    types are determined automatically and/or taken from the
+    \code{jobjRef} object. All named parameters are discarded.}
+  \item{evalArray}{This flag determines whether the array return value
+    is evaluated (\code{TRUE}) or passed back as Java object reference
+    (\code{FALSE}).}
+  \item{simplify}{If \code{evalArray} is \code{TRUE} then this argument
+    is passed to \code{\link{.jevalArray}()}.}
+  \item{evalString}{This flag determines whether string result is returned
+    as characters or as Java object reference.}
+  \item{check}{If set to \code{TRUE} then checks for exceptions are
+    performed before and after the call using
+    \code{\link{.jcheck}(silent=FALSE)}. This is usually the desired
+    behavior, because all calls fail until an expection is cleared.}
+  \item{interface}{This option is experimental and specifies the
+    interface used for calling the Java method; the current
+    implementation supports two interfaces:
+    \itemize{
+      \item{\code{"RcallMethod"}}{the default interface.}
+      \item{\code{"RcallSyncMethod"}}{synchronized call of a
+	method. This has simmilar effect as using \code{synchronize} in
+	Java.}
+    }
+  }
+  \item{use.true.class}{logical. If set to \code{TRUE}, the true class
+  of the returned object will be used instead of the declared signature. 
+  \code{TRUE} allows for example to grab the actual class of an object when 
+  the return type is an interface, or allows to grab an array when the 
+  declared type is Object and the returned object is an array. Use \code{FALSE} 
+  for efficiency when you are sure about the return type. }
+}
+\value{
+  Returns the result of the method.
+}
+\details{
+  \code{.jcall} requires exact match of argument and return types. For
+  higher efficiency \code{.jcall} doesn't perform any lookup in the
+  reflection tables. This means that passing subclasses of the classes
+  present in the method definition requires explicit casting using
+  \code{\link{.jcast}}. Passing \code{null} arguments also needs a
+  proper class specification with \code{\link{.jnull}}.
+
+  Java types \code{long} and \code{float} have no corresponding types in
+  R and therefore any such parameters must be flagged as such using
+  \code{\link{.jfloat}} and \code{\link{.jlong}} functions respectively.
+
+  Java also distinguishes scalar and array types whereas R doesn't have
+  the concept of a scalar. In R a scalar is basically a vector (called
+  array in Java-speak) of the length 1. Therefore passing vectors of the
+  length 1 is ambiguous. \code{.jcall} assumes that any vector of the
+  length 1 that corresponds to a native Java type is a scalar. All other
+  vectors are passed as arrays. Therefore it is important to use
+  \code{\link{.jarray}} if an arbitrary vector (including those of the
+  length 1) is to be passed as an array parameter.
+
+  \emph{Important note about encoding of character vectors:}
+  Java interface always works with strings in UTF-8 encoding, therefore
+  the safest way is to run R in a UTF-8 locale. If that is not
+  possible for some reason, rJava can be used in non-UTF-8 locales,
+  but care must be taken. Since R 2.7.0 it is possible to associate
+  encoding with strings and rJava will flag all strings it produces
+  with the appropriate UTF-8 tag. R will then perform corresponding
+  appropriate conversions where possible (at a cost of speed and
+  memory usage), but 3rd party code may not (e.g. older
+  packages). Also rJava relies on correct encoding flags for strings
+  passed to it and will attempt to perform conversions where
+  necessary. If some 3rd party code produces strings incorreclty
+  flagged, all bets are off.
+
+  Finally, for performance reasons class, method and field names as
+  well as signatures are not always converted and should not contain
+  non-ASCII characters.
+}
+\seealso{
+  \code{\link{.jnew}}, \code{\link{.jcast}}, \code{\link{.jnull}},
+  \code{\link{.jarray}}
+}
+\examples{
+\dontshow{.jinit()}
+.jcall("java/lang/System","S","getProperty","os.name")
+if (!nzchar(Sys.getenv("NOAWT"))) {
+  f <- .jnew("java/awt/Frame","Hello")
+  .jcall(f,,"setVisible",TRUE)
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jcast.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jcast.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..513038061931fb887f0688e2fa01bc0e69a52b10
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jcast.Rd
@@ -0,0 +1,45 @@
+\name{jcast}
+\alias{.jcast}
+\title{
+  Cast a Java object to another class
+}
+\description{
+  \code{.jcast} returns a Java object reference cast to another Java class.
+}
+\usage{
+.jcast(obj, new.class = "java/lang/Object", check = FALSE, convert.array = FALSE)
+}
+\arguments{
+  \item{obj}{a Java object reference}
+  \item{new.class}{fully qualified class name in JNI notation
+    (e.g. \code{"java/lang/String"}). }
+  \item{check}{logical. If \code{TRUE}, it is checked that the object 
+effectively is an instance of the new class. See \code{\link{\%instanceof\%}}.
+Using FALSE (the default) for this argument, rJava does not perform type check and this 
+will cause an error on the first use if the cast is illegal.}
+\item{convert.array}{logical. If \code{TRUE} and the object is an array, 
+it is converted into a \code{jarrayRef} reference. }
+}
+\value{
+  Returns a Java object reference (\code{jobjRef}) to the object
+  \code{obj}, changing the object class.
+}
+\details{
+  This function is necessary if a argument of \code{\link{.jcall}} or
+  \code{\link{.jnew}} is defined as the superclass of the object to be
+  passed (see \code{\link{.jcall}}). The original object is not modified.
+  
+  The default values for the arguments \code{check} and \code{convert.array}
+  is \code{FALSE} in order to guarantee backwards compatibility, 
+  but it is recommended to set the arguments to \code{TRUE}
+}
+\seealso{
+  \code{\link{.jcall}}
+}
+\examples{
+\dontrun{
+v <- .jnew("java/util/Vector")
+.jcall("java/lang/System","I","identityHashCode",.jcast(v, "java/lang/Object"))
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jcastToArray.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jcastToArray.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..d3543bddd7ae071b9a0ad05e3124a223cb0a70e7
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jcastToArray.Rd
@@ -0,0 +1,69 @@
+\name{jcastToArray}
+\alias{.jcastToArray}
+\title{
+  Ensures that a given object is an array reference
+}
+\description{
+  \code{.jcastToArray} takes a Java object reference of any kind and
+  returns Java array reference if the given object is a reference to an
+  array.
+}
+\usage{
+.jcastToArray(obj, signature=NULL, class="", quiet=FALSE)
+}
+\arguments{
+  \item{obj}{Java object reference to cast or a scalar vector}
+  \item{signature}{array signature in JNI notation (e.g. \code{"[I"} for
+    an array of integers). If set to \code{NULL} (the default),
+    the signature is automatically determined from the object's class.}
+  \item{class}{force the result to pose as a particular Java
+    class. This has the same effect as using \code{\link{.jcast}} on the
+    result and is provided for convenience only.}
+  \item{quiet}{if set to \code{TRUE}, no failures are reported and the
+    original object is returned unmodified.}
+}
+\value{
+  Returns a Java array reference (\code{jarrayRef}) on success. If
+  \code{quiet} is \code{TRUE} then the result can also be the original
+  object in the case of failure.
+}
+\details{
+  Sometimes a result of a method is by definition of the class
+  \code{java.lang.Object}, but the acutal referenced object may be an
+  array. In that case the method returns a Java object reference instead
+  of an array reference. In order to obtain an array reference, it is
+  necessary to cast such an object to an array reference - this is done
+  using the above \code{.jcastToArray} function.
+
+  The input is an object reference that points to an array. Ususally the
+  signature should be left at \code{NULL} such that it is determined
+  from the object's class. This is also a check, because if the object's
+  class is not an array, then the functions fails either with an error
+  (when \code{quiet=FALSE}) or by returing the original object (when
+  \code{quiet=TRUE}). If the signature is set to anything else, it is
+  not verified and the array reference is always created, even if it may
+  be invalid and unusable.
+
+  For convenience \code{.jcastToArray} also accepts non-references in
+  which case it simply calls \code{\link{.jarray}}, ignoring all other
+  parameters.
+}
+\examples{
+\dontrun{
+a <- .jarray(1:10)
+print(a)
+# let's create an array containing the array
+aa <- .jarray(list(a))
+print(aa)
+ba <- .jevalArray(aa)[[1]]
+# it is NOT the inverse, because .jarray works on a list of objects
+print(ba)
+# so we need to cast the object into an array
+b <- .jcastToArray(ba)
+# only now a and b are the same array reference
+print(b)
+# for convenience .jcastToArray behaves like .jarray for non-references
+print(.jcastToArray(1:10/2))
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jcheck.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jcheck.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..d9f6efcaf38bf050f1c24a73925d75a0d00ae550
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jcheck.Rd
@@ -0,0 +1,96 @@
+\name{jcheck}
+\alias{.jcheck}
+\alias{.jthrow}
+\alias{.jclear}
+\alias{.jgetEx}
+\title{
+  Java exception handling
+}
+\description{
+  \code{.jcheck} checks the Java VM for any pending exceptions and
+  clears them.
+
+  \code{.jthrow} throws a Java exception.
+
+  \code{.jgetEx} polls for any pending expections and returns the exception object.
+
+  \code{.jclear} clears a pending exception.
+}
+\usage{
+.jcheck(silent = FALSE)
+
+.jthrow(exception, message = NULL)
+.jgetEx(clear = FALSE)
+.jclear()
+}
+\arguments{
+  \item{silent}{If set to \code{FALSE} then Java is instructed to print
+    the exception on \code{stderr}. Note that Windows Rgui doesn't show
+    \code{stderr} so it will not appear there (as of rJava 0.5-1 some
+    errors that the JVM prints using the vfprintf callback are passed
+    to R. However, some parts are printed using \code{System.err} in
+    which case the ususal redirection using the \code{System} class
+    can be used by the user).}
+  \item{exception}{is either a class name of an exception to create or a
+    throwable object reference that is to be thrown.}
+  \item{message}{if \code{exception} is a class name then this parameter
+    specifies the string to be used as the message of the exception. This
+    parameter is ignored if \code{exception} is a reference.}
+  \item{clear}{if set to \code{TRUE} then the returned exception is also
+  cleared, otherwise the throwable is returned without clearing the
+  cause.}
+}
+\value{
+  \code{.jcheck} returns \code{TRUE} if an exception occurred or
+  \code{FALSE} otherwise.
+
+  \code{.jgetEx} returns \code{NULL} if there are no pending exceptions
+  or an object of the class "java.lang.Throwable" representing the
+  current exception.
+}
+\details{
+  Please note that some functions (such as \code{\link{.jnew}} or
+  \code{\link{.jcall}}) call \code{.jcheck} implicitly unless
+  instructed to not do so. If you want to handle Java exceptions, you
+  should make sure that those function don't clear the exception you may
+  want to catch.
+  
+  The exception handling is still as a very low-level and experimental,
+  because it requires polling of exceptions. A more elaboate system
+  using constructs similar to \code{try} ... \code{catch} is planned for
+  next major version of \code{rJava}.
+
+  \emph{Warning:} When requesting exceptions to not be cleared
+  automatically, please note that the \code{show} method (which is
+  called by \code{print}) has a side-effect of making a Java call to get
+  the string representation of a Java object. This implies that it will
+  be impeded by any pending exceptions. Therefore exceptions obtained
+  through \code{.jgetEx} can be stored, but should not be printed
+  (or otherwise used in Java calls) until after the exception is
+  cleared. In general, all Java calls will fail (possibly silently)
+  until the exception is cleared.
+}
+\seealso{
+  \code{\link{.jcall}}, \code{\link{.jnew}}
+}
+\examples{
+\donttest{
+# we try to create a bogus object and
+# instruct .jnew to not clear the exception
+# this will raise an exception
+v <- .jnew("foo/bar", check=FALSE)
+
+# you can poll for the exception, but don't try to print it
+# (see details above)
+if (!is.null(e<-.jgetEx())) print("Java exception was raised")
+
+# expect TRUE result here because the exception was still not cleared
+print(.jcheck(silent=TRUE))
+# next invocation will be FALSE because the exception is now cleared
+print(.jcheck(silent=TRUE))
+
+# now you can print the actual expection (even after it was cleared)
+print(e)
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jclassName.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jclassName.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..c7263d027d15e9effbd166370f22f44b855ebe22
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jclassName.Rd
@@ -0,0 +1,41 @@
+\name{jclassName-class}
+\docType{class}
+\alias{jclassName-class}
+\alias{as.character,jclassName-method}
+
+\title{Class "jclassName" - a representation of a Java class name }
+\description{ This class holds a name of a class in Java. }
+\section{Objects from the Class}{
+Objects of this class should *not* be created directly. Instead, the
+function \code{\link{J}} should be used to create new objects of this class.
+}
+\section{Slots}{
+  \describe{
+    \item{\code{name}:}{Name of the class (in source code notation)}
+    \item{\code{jobj}:}{Object representing the class in Java}
+  }
+}
+\section{Methods}{
+  The objects of class \code{jclassName} are used indirectly to be able
+  to create new Java objects via \code{new} such as
+  \code{new(J("java.lang.String"), "foo")} or to use the \code{$}
+  convenience operator on static classes, such as
+  \code{J("java.lang.Double")$parseDouble("10.2")}.
+
+  \describe{
+    \item{\code{as.character}}{\code{signature(x = "jclassName")}:
+      returns the class name as a string vector of length one.
+    }
+  }
+}
+%\references{ ~put references to the literature/web site here ~ }
+\author{ Simon Urbanek }
+%\note{ ~~further notes~~ }
+% ~Make other sections like Warning with \section{Warning }{....} ~
+\seealso{
+  \code{\link{J}}, \code{\link{new}}
+}
+%\examples{
+%##---- Should be DIRECTLY executable !! ----
+%}
+\keyword{classes}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jequals.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jequals.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..e49d8bbbd7cc90bd6bf64e4062c5f0ff1e6288f2
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jequals.Rd
@@ -0,0 +1,162 @@
+\name{jequals}
+\alias{.jequals}
+\alias{.jcompare}
+\alias{!=,ANY,jobjRef-method}
+\alias{!=,jobjRef,jobjRef-method}
+\alias{!=,jobjRef,ANY-method}
+\alias{==,ANY,jobjRef-method}
+\alias{==,jobjRef,jobjRef-method}
+\alias{==,jobjRef,ANY-method}
+\alias{<,ANY,jobjRef-method}
+\alias{<,jobjRef,jobjRef-method}
+\alias{<,jobjRef,ANY-method}
+\alias{>,ANY,jobjRef-method}
+\alias{>,jobjRef,jobjRef-method}
+\alias{>,jobjRef,ANY-method}
+\alias{<=,ANY,jobjRef-method}
+\alias{<=,jobjRef,jobjRef-method}
+\alias{<=,jobjRef,ANY-method}
+\alias{>=,ANY,jobjRef-method}
+\alias{>=,jobjRef,jobjRef-method}
+\alias{>=,jobjRef,ANY-method}
+
+\title{
+  Comparing Java References
+}
+\description{
+  \code{.jequals} function can be used to determine whether two objects
+  are equal. In addition, it allows mixed comparison of non-Java object
+  for convenience, unless strict comparison is desired.
+
+  The binary operators \code{==} and \code{!=} are mapped to
+  (non-strict) call to \code{.jequals} for convenience.
+  
+  \code{.jcompare} compares two objects in the sense of the 
+  \code{java.lang.Comparable} interface. 
+  
+  The binary operators \code{<}, \code{>}, \code{<=}, \code{>=} are mapped 
+  to calls to \code{.jcompare} for convenience
+}
+\usage{
+.jequals(a, b, strict = FALSE)
+.jcompare( a, b )
+}
+\arguments{
+  \item{a}{first object}
+  \item{b}{second object}
+  \item{strict}{when set to \code{TRUE} then non-references save for
+    \code{NULL} are always treated as different, see details.}
+}
+\value{
+ \code{.jequals} returns \code{TRUE} if both object 
+ 	are considered equal, \code{FALSE} otherwise.
+ 	
+ \code{.jcompare} returns the result of the \code{compareTo} java method
+ of the object a applied to b
+}
+\section{Methods}{
+  \describe{
+    \item{!=}{\code{signature(e1 = "ANY", e2 = "jobjRef")}: ... }
+    \item{!=}{\code{signature(e1 = "jobjRef", e2 = "jobjRef")}: ... }
+    \item{!=}{\code{signature(e1 = "jobjRef", e2 = "ANY")}: ... }
+    \item{==}{\code{signature(e1 = "ANY", e2 = "jobjRef")}: ... }
+    \item{==}{\code{signature(e1 = "jobjRef", e2 = "jobjRef")}: ... }
+    \item{==}{\code{signature(e1 = "jobjRef", e2 = "ANY")}: ... }
+    \item{<}{\code{signature(e1 = "ANY", e2 = "jobjRef")}: ... }
+    \item{<}{\code{signature(e1 = "jobjRef", e2 = "jobjRef")}: ... }
+    \item{<}{\code{signature(e1 = "jobjRef", e2 = "ANY")}: ... }
+    \item{>}{\code{signature(e1 = "ANY", e2 = "jobjRef")}: ... }
+    \item{>}{\code{signature(e1 = "jobjRef", e2 = "jobjRef")}: ... }
+    \item{>}{\code{signature(e1 = "jobjRef", e2 = "ANY")}: ... }
+    \item{>=}{\code{signature(e1 = "ANY", e2 = "jobjRef")}: ... }
+    \item{>=}{\code{signature(e1 = "jobjRef", e2 = "jobjRef")}: ... }
+    \item{>=}{\code{signature(e1 = "jobjRef", e2 = "ANY")}: ... }
+    \item{<=}{\code{signature(e1 = "ANY", e2 = "jobjRef")}: ... }
+    \item{<=}{\code{signature(e1 = "jobjRef", e2 = "jobjRef")}: ... }
+    \item{<=}{\code{signature(e1 = "jobjRef", e2 = "ANY")}: ... }
+
+	 }
+}
+\details{
+	\code{.jequals} compares two Java objects by calling \code{equals}
+  method of one of the objects and passing the other object as its
+  argument. This allows Java objects to define the `equality' in
+  object-dependent way.
+
+  In addition, \code{.jequals} allows the comparison of Java object to
+  other scalar R objects. This is done by creating a temporary Java
+  object that corresponds to the R object and using it for a call to the
+  \code{equals} method. If such conversion is not possible a warning is
+  produced and the result it \code{FALSE}. The automatic conversion
+  will be avoided if \code{strict} parameter is set to \code{TRUE}.
+
+  \code{NULL} values in \code{a} or \code{b} are replaced by Java
+  \code{null}-references and thus \code{.jequals(NULL,NULL)} is \code{TRUE}.
+
+  If neither \code{a} and \code{b} are Java objects (with the exception
+  of both being \code{NULL}) then the result is identical to that of
+  \code{all.equal(a,b)}.
+  
+  Neither comparison operators nor \code{.jequals} supports vectors and
+  returns \code{FALSE} in that case. A warning is also issued unless
+  strict comparison was requested.
+}
+\note{
+  Don't use \code{x == NULL} to check for
+  \code{null}-references, because \code{x} could be \code{NULL} and thus
+  the result would be an empty vector. Use \code{\link{is.jnull}}
+  instead.
+  (In theory \code{is.jnull} and \code{x == .jnull()} are the the same,
+  but \code{is.jnull} is more efficient.)
+}
+\seealso{
+  \code{\link{is.jnull}}
+}
+\examples{
+\dontshow{.jinit()}
+s <- .jnew("java/lang/String", "foo")
+.jequals(s, "foo") # TRUE
+.jequals(s, "foo", strict=TRUE) # FALSE - "foo" is not a Java object
+t <- s
+.jequals(s, t, strict=TRUE) # TRUE
+
+s=="foo" # TRUE
+
+\dontshow{ 
+	stopifnot( 
+		.jequals(s, "foo"), 
+		!.jequals(s, "foo", strict=TRUE), 
+		.jequals(s, t, strict=TRUE), 
+		s == "foo"
+	)
+}
+
+Double <- J("java.lang.Double")
+d1 <- new( Double, 0.0 ) 
+d2 <- new( Double, 1.0 )
+d3 <- new( Double, 0.0 )
+
+d1 < d2
+d1 <= d3
+d1 >= d3
+d1 > d2
+
+# cannot compare a Double and a String
+try( d1 < "foo" )
+
+# but can compare a Double and an Integer
+d1 < 10L
+
+\dontshow{
+	stopifnot( 
+		d1 < d2       ,
+		d1 <= d3      ,
+		d1 >= d3      ,
+		! (d1 > d2 )  , 
+		inherits( try( d1 < "foo", silent = TRUE ), "try-error" ), 
+		d1 < 10L )
+}
+
+
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jfield.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jfield.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..46438c89f771a973561afcf9912d41ddbfefed55
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jfield.Rd
@@ -0,0 +1,57 @@
+\name{jfield}
+\alias{.jfield}
+\alias{.jfield<-}
+\title{
+  Obtains the value of a field 
+}
+\description{
+  \code{.jfield} returns the value of the specified field on an object.
+}
+\usage{
+.jfield(o, sig = NULL, name, true.class = is.null(sig), convert = TRUE)
+`.jfield<-`(o, name, value)
+}
+\arguments{
+  \item{o}{Class name or object (Java reference) whose field is to be
+    accessed. Static fields are supported both by specifying the class
+    name or using an instance.}
+  \item{sig}{signature (JNI type) of the field. If set to \code{NULL}
+    rJava attempts to determine the signature using reflection. For
+    efficiency it is recommended to specify the signature, because
+    the reflection lookup is quite expensive.}
+  \item{name}{name of the field to access}
+  \item{true.class}{by default the class of the resulting object matches
+    the siganture of the field. Setting this flag to \code{TRUE} causes
+    \code{.jfield} to use true class name of the resulting object
+    instead. (this flag has no effect on scalar fields)}
+  \item{convert}{when set to \code{TRUE} all references are converted to
+    native types (where possible). Otherwise Java references are
+    returned directly.}
+  \item{value}{value to assign into the field. The field signature is
+    determined from the value in the same way that parameter signatures
+    are determined in \code{\link{.jcall}} - be sure to cast the value
+    as necessary, no automatic conversion is done.}
+}
+\value{
+  \code{.jfield}: contents of the field, \code{.jfield<-}: modified object.
+}
+\details{
+  The detection of a field signature in \code{.jfield} using reflection
+  is considerably expensive (more than 3 additional method calls have to
+  be performed), therefore it is recommended for time-critical code to
+  specify the field signature beforehand.
+
+  NOTE: The sequence of arguments in \code{.jfield} has been changed
+  since rJava 0.5 to be more consistent and match the sequence in
+  \code{.jcall}. Also \code{.jsimplify} is no longer needed as primitive
+  types are obtained directly.
+}
+\seealso{
+  \code{\link{.jcall}}
+}
+\examples{
+\dontrun{
+.jfield("java/lang/Boolean",, "TYPE")
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jfloat-class.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jfloat-class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f7eb877cc4e5e5fefc57ff01a417ffa9c4b06bb9
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jfloat-class.Rd
@@ -0,0 +1,54 @@
+\name{jfloat-class}
+\docType{class}
+\alias{jfloat-class}
+\alias{jlong-class}
+\alias{jbyte-class}
+\alias{jchar-class}
+\title{Classes "jfloat", "jlong", "jbyte" and "jchar" specify Java
+  native types that are not native in R}
+\description{ These classes wrap a numeric vector to be treated as
+  \code{float} or \code{long} argument when passed to Java and an
+  integer vector to be treated as \code{byte} or \code{char}. R doesn't
+  distinguish between \code{double} and \code{float}, but Java
+  does. In order to satisfy object types, numeric vectors that should be
+  converted to floats or long on the Java side must be wrapped in this
+  class. In addition \code{jbyte} must be used when passing scalar byte
+  (but not byte arrays, those are mapped into RAW vectors). Finally
+  \code{jchar} it used when mapping integer vectors into unicode Java
+  character vectors.}
+\section{Objects from the Class}{
+  Objects can be created by calling \code{\link{.jfloat}},
+  \code{\link{.jlong}}, \code{\link{.jbyte}} or \code{\link{.jchar}}
+  respectively.
+}
+\section{Slots}{
+  \describe{
+    \item{\code{.Data}:}{Payload}
+  }
+}
+\section{Extends}{
+  "jfloat" and "jlong":
+  Class \code{"numeric"}, from data part.
+  Class \code{"vector"}, by class \code{"numeric"}.
+
+  "jbyte" and "jchar":
+  Class \code{"integer"}, from data part.
+  Class \code{"vector"}, by class \code{"integer"}.
+}
+\section{Methods}{
+  "jfloat" and "jlong" have no methods other than those inherited from "numeric".
+  "jbyte" and "jchar" have no methods other than those inherited from "integer".
+}
+%\references{ ~put references to the literature/web site here ~ }
+\author{ Simon Urbanek }
+%\note{ ~~further notes~~ }
+
+% ~Make other sections like Warning with \section{Warning }{....} ~
+
+\seealso{
+  \code{\link{.jfloat}}, \code{\link{.jlong}}, \code{\link{.jbyte}}, \code{\link{.jchar}} and \code{\link{.jcall}}
+}
+%\examples{
+%##---- Should be DIRECTLY executable !! ----
+%}
+\keyword{classes}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jfloat.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jfloat.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..378918d92055460c2cd5a7910b4ad8d140571e13
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jfloat.Rd
@@ -0,0 +1,66 @@
+\name{jfloat}
+\alias{.jfloat}
+\alias{.jlong}
+\alias{.jbyte}
+\alias{.jchar}
+\alias{.jshort}
+\alias{jfloat}
+\alias{jlong}
+\alias{jbyte}
+\alias{jchar}
+\alias{jshort}
+\title{
+  Wrap numeric vector as flat Java parameter
+}
+\description{
+  \code{.jfloat} marks a numeric vector as an object that can be used
+  as parameter to Java calls that require \code{float} parameters.
+  Similarly, \code{.jlong} marks a numeric vector as \code{long} parameter.
+}
+\usage{
+.jfloat(x)
+.jlong(x)
+.jbyte(x)
+.jchar(x)
+.jshort(x)
+}
+\arguments{
+  \item{x}{numeric vector}
+}
+\value{
+  Returns a numeric vector of the class \code{jfloat}, \code{jlong},
+  \code{jbyte}, \code{jshort} or \code{jchar}
+  that can be used as parameter to Java calls that require
+  \code{float}, \code{long}, \code{byte}, \code{short} or \code{char}
+  parameters respectively.
+}
+\details{
+  R has no native \code{float} or \code{long} type. Numeric vectors are
+  stored as \code{double}s, hence there is no native way to pass float
+  numbers to Java methods. The \code{.jfloat} call marks a numeric
+  vector as having the Java type \code{float} by wrapping it in the
+  \code{jfloat} class. The class is still a subclass of \code{numeric},
+  therefore all regular R operations are unaffected by this.
+
+  Similarly, \code{.jlong} is used to mark a numeric vector as a
+  parameter of the \code{long} Java type. Please note that in general R
+  has no native type that will hold a \code{long} value, so conversion
+  between Java's \code{long} type and R's numeric is potentially lossy.
+
+  \code{.jbyte} is used when a scalar byte is to be passed ot Java. Note
+  that byte arrays are natively passed as RAW vectors, not as
+  \code{.jbyte} arrays.
+  
+  \code{jchar} is strictly experimental and may be based on
+  \code{character} vectors in the future.
+}
+\seealso{
+  \code{\link{.jcall}}, \code{\link{jfloat-class}}
+}
+%\examples{
+%\dontrun{
+%v <- .jnew("java/util/Vector")
+%.jcall("java/lang/System","I","identityHashCode",.jcast(v, "java/lang/Object"))
+%}
+%}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jinit.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jinit.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..075f5210832aa7c3ff6f04db9fbd1dde168128d8
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jinit.Rd
@@ -0,0 +1,74 @@
+\name{jinit}
+\alias{.jinit}
+\title{
+  Initialize Java VM
+}
+\description{
+  \code{.jinit} initializes the Java Virtual Machine (JVM). This
+  function must be called before any rJava functions can be used.
+}
+\usage{
+.jinit(classpath = NULL, parameters = getOption("java.parameters"), ...,
+silent = FALSE, force.init = FALSE)
+}
+\arguments{
+  \item{classpath}{Any additional classes to include in the Java class
+    paths (i.e. locations of Java classes to use). This path will be
+    prepended to paths specified in the \code{CLASSPATH} environment
+    variable. Do NOT set this system class path initializing a package,
+    use \code{\link{.jpackage}} instead, see details.}
+  \item{parameters}{character vector of parameters to be passed to
+    the virtual machine. They are implementation dependent and apply
+    to JDK version 1.2 or higher only. Please note that each parameter
+    must be in a separate element of the array, you cannot use a
+    space-separated string with multiple parameters.}
+  \item{...}{Other optional Java initialization parameters (implementation-dependent).}
+  \item{silent}{If set to \code{TRUE} no warnings are issued.}
+  \item{force.init}{If set to \code{TRUE} JVM is re-initialized even if
+    it is already running.}
+}
+\value{
+  The return value is an integer specifying whether and how the VM was
+  initialized. Negative values indicate failure, zero denotes successful
+  initialization and positive values signify partially successful
+  initilization (i.e. the VM is up, but parameters or class path could
+  not be set due to an existing or incompatible VM).
+}
+\details{
+  Starting with version 0.5 rJava provides a custom class loader that can
+  automatically track classes and native libraries that are provided in
+  R packages. Therefore R packages should NOT use \code{.jinit}, but
+  call \code{\link{.jpackage}} instead. In addition this allows the use
+  of class path modifying function \code{\link{.jaddClassPath}}.
+
+  Important note: if a class is found on the system class path (i.e. on
+  the \code{classpath} specified to \code{.jinit}) then the system class
+  loader is used instead of the rJava loader, which can lead to problems
+  with reflection and native library support is not enabled. Therefore
+  it is highly recommended to use \code{.jpackage} or
+  \code{.jaddClassPath} instead of \code{classpath} (save for system
+  classes).
+  
+  Stating with version 0.3-8 rJava is now capable of modifying the class
+  path on the fly for certain Sun-based Java virtual machines, even when
+  attaching to an existing VM. However, this is done by exploiting the
+  way ClassLoader is implemented and may fail in the future. In general
+  it is officially not possible to change the class path of a running
+  VM.
+  
+  At any rate, it is impossible to change any other VM parameters of a
+  running VM, so when using \code{.jinit} in a package, be generous with
+  limits and don't use VM parameters to unnecessarily restrict
+  resources (or preferably use \code{\link{.jpackage}} instead).
+}
+\seealso{
+  \code{\link{.jpackage}}
+}
+\examples{
+\dontrun{
+## set heap size limit to 512MB (see java -X) and
+## use "myClasses.jar" as the class path
+.jinit(classpath="myClasses.jar", parameters="-Xmx512m")
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jmemprof.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jmemprof.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..9f0857bef89de7d9138a0a26b4f40d7a432dbc31
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jmemprof.Rd
@@ -0,0 +1,47 @@
+\name{jmemprof}
+\alias{.jmemprof}
+\title{
+  rJava memory profiler
+}
+\description{
+  \code{.jmemprof} enables or disables rJava memory profiling. If rJava
+  was compiled without memory profiling support, then a call to this
+  function always causes an error.
+}
+\usage{
+.jmemprof(file = "-")
+}
+\arguments{
+  \item{file}{file to write profiling information to or \code{NULL} to
+    disable profiling}
+}
+\value{
+  Returns \code{NULL}.
+}
+\details{
+  The \code{file} parameter must be either a filename (which will be
+  opened in append-mode) or "-" to use standard output or \code{NULL} to
+  disable profiling. An empty string "" is equivalent to \code{NULL} in
+  this context.
+
+  Note that lots of finalizers are run only when R exists, so usually
+  you want to enable profiling early and let R exit to get a sensible
+  profile. Runninng gc may be helpful to get rid of references that can
+  be collected in R.
+
+  A simple perl script is provided to analyze the result of the
+  profiler. Due to its simple text format, it is possible to capture
+  entire stdout including the profiler information to have both the
+  console context for the allocations and the profile. Memory profiling
+  is also helful if rJava debug is enabled.
+
+  Note that memory profiling support must be compiled in rJava and it is
+  by default compiled only if debug mode is enabled (which is not the
+  case by default).
+}
+\examples{
+\donttest{
+.jmemprof("rJava.mem.profile.txt")
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jnew.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jnew.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..d599012346b9c68b248b07d50eca708ca537a36b
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jnew.Rd
@@ -0,0 +1,51 @@
+\name{jnew}
+\alias{.jnew}
+\title{
+  Create a Java object
+}
+\description{
+	\code{.jnew} create a new Java object.
+}
+\usage{
+.jnew(class, ..., check=TRUE, silent=!check, class.loader=NULL)
+}
+\arguments{
+  \item{class}{fully qualified class name in JNI notation (e.g. \code{"java/lang/String"}).}
+  \item{...}{
+    Any parameters that will be passed to the corresponding
+    constructor. The parameter types are determined automatically and/or
+    taken from the \code{jobjRef} object. For details see
+    \code{\link{.jcall}}. Note that all named parameters are discarded.}
+  \item{check}{
+    If set to \code{TRUE} then \code{\link{.jcheck}} is invoked before
+    and after the call to the constructor to clear any pending Java
+    exceptions.}
+  \item{silent}{
+    If set to \code{FALSE} then \code{.jnew} will fail with an error if
+    the object cannot be created, otherwise a null-reference is returned
+    instead. In addition, this flag is also passed to final
+    \code{.jcheck} if \code{check} above is set to \code{TRUE}. Note
+    that the error handling also clears exceptions, so
+    \code{check=FALSE, silent=FALSE} is usually not a meaningful
+    combination.
+  }
+  \item{class.loader}{optional class loader to force for loading the
+    class. If not set, the rJava class loader is used first. The default
+    Java class loader is always used as a last resort. This is for
+    expert use only! If you set the class loader, the class loading
+    behavior changes - use only in very special circumstances.}
+}
+\value{
+  Returns the reference (\code{jobjRef}) to the newly created object or
+  \code{null}-reference (see \code{\link{.jnull}}) if something went wrong.
+}
+\seealso{
+  \code{\link{.jcall}}, \code{\link{.jnull}}
+}
+\examples{
+\dontrun{
+f <- .jnew("java/awt/Frame","Hello")
+.jcall(f,,"setVisible",TRUE)
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jnull.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jnull.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..2f316f7faff4ced0bca90d90c797575ef7761a1a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jnull.Rd
@@ -0,0 +1,57 @@
+\name{jnull}
+\alias{.jnull}
+\alias{is.jnull}
+\title{
+  Java null object reference
+}
+\description{
+  \code{.jnull} returns a \code{null} reference of a specified class
+  type. The resulting object is of the class \code{jobjRef}.
+
+  \code{is.jnull} is an extension of \code{is.null} that also returns
+  \code{TRUE} if the supplied object is a \code{null} Java reference.
+}
+\usage{
+.jnull(class = "java/lang/Object")
+is.jnull(x)
+}
+\arguments{
+  \item{class}{fully qualified target class name in JNI notation
+    (e.g. \code{"java/lang/String"}).}
+  \item{x}{object to check}
+}
+\value{
+  \code{.jnull} returns a Java object reference (\code{jobjRef}) of a
+  \code{null} object having the specified object class.
+
+  \code{is.jnull} returns \code{TRUE} if \code{is.null(x)} is
+  \code{TRUE} or if \code{x} is a Java \code{null} reference.
+}
+\details{
+  \code{.jnull} is necesary if \code{null} is to be passed as an
+  argument of \code{\link{.jcall}} or \code{\link{.jnew}}, in order to be
+  able to find the correct method/constructor.
+
+  Example: given the following method definitions of the class \code{A}:
+  \itemize{
+    \item{o}{public static void run(String a);}
+    \item{o}{public static void run(Double n);}
+  }
+  Calling \code{.jcall("A",,"run",NULL)} is ambiguous, because it is
+  unclear which method is to be used. Therefore rJava requires class
+  information with each argument to \code{\link{.jcall}}. If we wanted
+  to run the String-version, we could use
+  \code{.jcall("A",,"run",.jnull("java/lang/String"))}.
+
+  \code{is.jnull} is a test that should be used to determine whether a
+  given Java reference is a \code{null} reference.
+}
+\seealso{
+  \code{\link{.jcall}}, \code{\link{.jcast}}
+}
+\examples{
+\dontrun{
+.jcall("java/lang/System","I","identityHashCode",.jnull())
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jobjRef-class.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jobjRef-class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..af2bfa852abaa9a6f7048a41485afcfe3d0ee1f3
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jobjRef-class.Rd
@@ -0,0 +1,24 @@
+\name{jobjRef-class}
+\docType{class}
+\alias{jobjRef-class}
+
+\title{Class "jobjRef" - Reference to a Java object }
+\description{ This class describes a reference to an object held in a JavaVM. }
+\section{Objects from the Class}{
+Objects of this class should *not* be created directly. Instead, the function \code{\link{.jnew}} should be use to create new Java objects. They can also be created as results of the \code{\link{.jcall}} function.
+}
+\section{Slots}{
+  \describe{
+    \item{\code{jobj}:}{Internal identifier of the object (external pointer to be precise)}
+    \item{\code{jclass}:}{Java class name of the object (in JNI notation)}
+  }
+  Java-side attributes are not accessed via slots, but the \code{$} operator instead.
+}
+\section{Methods}{
+This object's Java methods are not accessed directly. Instead, \code{\link{.jcall}} JNI-API should be used for invoking Java methods. For convenience the \code{$} operator can be used to call methods via reflection API.
+}
+\author{ Simon Urbanek }
+\seealso{
+  \code{\link{.jnew}}, \code{\link{.jcall}}  or \code{\link{jarrayRef-class}}
+}
+\keyword{classes}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jpackage.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jpackage.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..29daddf40f423213ae23a5ef3b4b0dd06b82ba8d
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jpackage.Rd
@@ -0,0 +1,66 @@
+\name{jpackage}
+\alias{.jpackage}
+\title{
+  Initialize an R package containing Java code
+}
+\description{
+  \code{.jpackage} initializes the Java Virtual Machine (JVM) for an R
+  package. In addition to starting the JVM it also registers Java
+  classes and native code contained in the package with the JVM.
+  function must be called before any rJava functions can be used.
+}
+\usage{
+.jpackage(name, jars='*', morePaths='', nativeLibrary=FALSE, lib.loc=NULL)
+}
+\arguments{
+  \item{name}{name of the package. It should correspond to the
+    \code{pkgname} parameter of \code{.onLoad} or \code{.First.lib}
+    function.}
+  \item{jars}{Java archives in the \code{java} directory of the package
+    that should be added to the class path. The paths must be relative
+    to package's \code{java} directory. A special value of
+    \code{'*'} adds all \code{.jar} files from the \code{java} the
+    directory.}
+  \item{morePaths}{vector listing any additional entries that should
+    be added to the class path.}
+  \item{nativeLibrary}{a logical determining whether rJava should look
+    for native code in the R package's shared object or not.}
+  \item{lib.loc}{a character vector with path names of R libraries, or
+    \code{NULL} (see \code{\link{system.file}} and examples below).}
+
+}
+\value{
+  The return value is an invisible TRUE if the initialization was successful.  
+}
+\details{
+  \code{.jpackage} initializes a Java R package as follows: first the
+  JVM is initialized via \code{\link{.jinit}} (if it is not running
+  already). Then the \code{java} directory of the package is added to
+  the class path. Then \code{.jpackage} prepends \code{jars} with the
+  path to the \code{java} directory of the package and adds them to the
+  class path (or all \code{.jar} files if \code{'*'} was specified).
+  Finally the \code{morePaths} parameter (if set) is passed to a call
+  to \code{\link{.jaddClassPath}}.
+
+  Therefore the easiest way to create a Java package is to add
+  \code{.jpackage(pkgname, lib.loc=libname)} in \code{.onLoad} or
+  \code{.First.lib}, and copy all necessary classes to a JAR file(s)
+  which is placed in the \code{inst/java/} directory of the source
+  package.
+
+  If a package needs special Java parameters, \code{"java.parameters"}
+  option can be used to set them on initialization. Note, however, that
+  Java parameters can only be used during JVM initialization and other
+  package may have intialized JVM already.
+}
+\seealso{
+  \code{\link{.jinit}}
+}
+\examples{
+\dontrun{
+.onLoad <- function(libname, pkgname) {
+  .jpackage(pkgname, lib.loc=libname)
+}
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jrectRef-class.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jrectRef-class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..88787d014f0e107b84c319344e7da964e3ba10e8
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jrectRef-class.Rd
@@ -0,0 +1,278 @@
+\name{jrectRef-class}
+\Rdversion{1.1}
+\docType{class}
+\alias{jrectRef-class}
+\alias{[,jrectRef-method}
+\alias{length,jrectRef-method}
+\alias{str,jrectRef-method}
+\alias{dim,jrectRef-method}
+\alias{dim<-,jrectRef-method}
+\alias{unique,jrectRef-method}
+\alias{duplicated,jrectRef-method}
+\alias{anyDuplicated,jrectRef-method}
+\alias{sort,jrectRef-method}
+\alias{rev,jrectRef-method}
+\alias{min,jrectRef-method}
+\alias{max,jrectRef-method}
+\alias{range,jrectRef-method}
+
+\title{Rectangular java arrays}
+\description{References to java arrays that are guaranteed to be rectangular, i.e similar 
+to R arrays}
+\section{Objects from the Class}{
+Objects of this class should *not* be created directly. 
+Instead, they usually come as a result of a java method call. 
+}
+\section{Slots}{
+  \describe{
+    \item{\code{jsig}:}{JNI signature of the array type}
+    \item{\code{jobj}:}{Internal identifier of the object}
+    \item{\code{jclass}:}{Inherited from \code{jobjRef}, but unspecified}
+    \item{\code{dimension}:}{dimension vector of the array}
+  }
+}
+\section{Extends}{
+Class \code{"\linkS4class{jarrayRef}"}, directly.
+Class \code{"\linkS4class{jobjRef}"}, by class "jarrayRef", distance 2.
+}
+\section{Methods}{
+  \describe{
+    \item{length}{\code{signature(x = "jrectRef")}: The number of elements in the array. 
+    	Note that if the array has more than one dimension, 
+    	it gives the number of arrays in the first dimension, and not the total 
+    	number of atomic objects in tha array (like R does). This gives what would be 
+		returned by \code{array.length} in java.}
+    \item{str}{\code{signature(object = "jrectRef")}: ... }
+    \item{[}{\code{signature(x = "jrectRef")}: R indexing of rectangular java arrays }
+    \item{dim}{\code{signature(x = "jrectRef")}: extracts the dimensions of the array }
+    \item{dim<-}{\code{signature(x = "jrectRef")}: sets the dimensions of the array }
+    \item{unique}{\code{signature(x = "jrectRef")}: unique objects in the array}
+    \item{duplicated}{\code{signature(x = "jrectRef")}: see \code{\link{duplicated}} }
+    \item{anyDuplicated}{\code{signature(x = "jrectRef")}: see \code{\link{anyDuplicated}} }
+    \item{sort}{\code{signature(x = "jrectRef")}: returns a \emph{new} array with elements from x in order }
+    \item{rev}{\code{signature(x = "jrectRef")}: returns a \emph{new} array with elements from x reversed }
+    \item{min}{\code{signature(x = "jrectRef")}: the smallest object in the array (in the sense of the Comparable interface) }
+    \item{max}{\code{signature(x = "jrectRef")}: the biggest object in the array (in the sense of the Comparable interface) }
+    \item{range}{\code{signature(x = "jrectRef")}: the range of the array (in the sense of the Comparable interface) }
+  }
+}
+\examples{
+\dontshow{
+# these examples are only unit tests so far
+.jinit()
+}
+v <- new( J("java.util.Vector") )
+v$add( "hello" )
+v$add( "world" )
+v$add( new( J("java.lang.Double"), "10.2" ) )
+array <- v$toArray()
+
+array[ c(TRUE,FALSE,TRUE) ]
+array[ 1:2 ]
+array[ -3 ]
+
+# length 
+length( array )
+\dontshow{stopifnot(length(array) == 3L)}
+
+# also works as a pseudo field as in java
+array$length
+\dontshow{stopifnot(array$length == 3L)}
+
+
+\dontshow{
+# # 2d
+dim2d <- c(5L, 2L)
+
+x <- .jcall( "RectangularArrayExamples", "[[Z",
+"getBooleanDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE)
+stopifnot( identical( typeof( x ), "logical" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), rep( c(FALSE,TRUE), 5 ) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[I",
+"getIntDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "integer" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), 0:9 ) )
+ 
+x <- .jcall( "RectangularArrayExamples", "[[B",
+"getByteDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "raw" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), as.raw(0:9) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[J",
+"getLongDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "double" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), as.numeric(0:9) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[S",
+"getShortDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "integer" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), 0:9 ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[D",
+"getDoubleDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "double" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), as.numeric(0:9) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[C",
+"getCharDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "integer" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), 0:9 ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[F",
+"getFloatDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "double" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), as.numeric(0:9) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[Ljava/lang/String;",
+"getStringDoubleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "character" ) )
+stopifnot( identical( dim(x) , dim2d ) )
+stopifnot( identical( as.vector(x), as.character(0:9) ) )
+
+
+# 3d
+
+dim3d <- c(5L, 3L, 2L) 
+
+x <- .jcall( "RectangularArrayExamples", "[[[Z",
+"getBooleanTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE)
+stopifnot( identical( typeof( x ), "logical" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), rep( c(FALSE,TRUE), 15L ) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[I",
+"getIntTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "integer" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), 0:29 ) )
+ 
+x <- .jcall( "RectangularArrayExamples", "[[[B",
+"getByteTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "raw" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), as.raw(0:29) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[J",
+"getLongTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "double" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), as.numeric(0:29) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[S",
+"getShortTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "integer" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), 0:29 ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[D",
+"getDoubleTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "double" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), as.numeric(0:29) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[C",
+"getCharTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "integer" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), 0:29 ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[F",
+"getFloatTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "double" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), as.numeric(0:29) ) )
+
+x <- .jcall( "RectangularArrayExamples", "[[[Ljava/lang/String;",
+"getStringTripleRectangularArrayExample",  evalArray = TRUE, simplify = TRUE )
+stopifnot( identical( typeof( x ), "character" ) )
+stopifnot( identical( dim(x) , dim3d ) )
+stopifnot( identical( as.vector(x), as.character(0:29) ) )
+          
+
+# testing the indexing
+
+xj <- .jarray( x, dispatch = TRUE )
+stopifnot( dim( xj[ ,, ] ) == c( 5L, 3L, 2L ) )
+stopifnot( dim( xj[ ] ) == c( 5L, 3L, 2L ) )
+stopifnot( dim( xj[ ,,1,drop= TRUE] ) == c( 5L, 3L ) )
+stopifnot( dim( xj[ ,,1,drop= FALSE] ) == c( 5L, 3L, 1L ) )
+stopifnot( dim( xj[ ,1,,drop= TRUE] ) == c( 5L, 2L ) )
+stopifnot( dim( xj[ ,1,,drop= FALSE] ) == c( 5L, 1L, 2L ) )
+stopifnot( dim( xj[ 1,,,drop= TRUE] ) == c( 3L, 2L ) )
+stopifnot( dim( xj[ 1,,,drop= FALSE] ) == c( 1L, 3L, 2L ) )
+stopifnot( dim( xj[ ,1,1,drop= TRUE] ) == c( 5L ) )
+stopifnot( dim( xj[ ,1,1,drop= FALSE] ) == c( 5L, 1L, 1L ) )
+stopifnot( dim( xj[ 1,1,1,drop= TRUE] ) == c( 1L ) )
+stopifnot( dim( xj[ 1,1,1,drop= FALSE] ) == c( 1L, 1L, 1L ) )
+
+# testing simplify
+stopifnot( identical( xj[simplify=TRUE], x) )
+stopifnot( identical( xj[,1,,simplify=TRUE], x[,1,]) )
+stopifnot( identical( xj[,1,-1,simplify=TRUE], x[,1,-1]) )
+stopifnot( identical( xj[4,1,c(TRUE,FALSE),simplify=TRUE], x[4,1,c(TRUE,FALSE)]) )
+stopifnot( identical( xj[1:10,simplify=TRUE], x[1:10]) )
+
+# test dim<-
+dim( xj ) <- c( 15L, 2L )
+stopifnot( xj@jsig == "[[Ljava/lang/String;" )
+stopifnot( dim( xj ) == c(15L, 2L ) )
+
+dim( xj ) <- NULL
+stopifnot( xj@jsig == "[Ljava/lang/String;" )
+stopifnot( dim( xj ) == 30L )
+
+# test unique
+# **** FIXME: this should really work even with dispatch=FALSE since
+#             it's a vector but it does not! It applies to everything
+#             below
+x <- .jarray( rep( 1:2, each = 5 ), dispatch = TRUE )
+xu <- unique( x )
+stopifnot( dim(xu) == 2L )
+
+  p1 <- .jnew( "java/awt/Point" )
+  p2 <- .jnew( "java/awt/Point" )
+  x <- .jarray( list( p1, p2 ), dispatch = TRUE )
+  xu <- unique( x )
+  stopifnot( dim( xu ) == 1L )
+
+# test duplicated
+x <- .jarray( rep( 1:2, each = 5 ), dispatch = TRUE )
+xd <- duplicated( x )
+stopifnot( xd == rep( c( FALSE, TRUE, TRUE, TRUE, TRUE), 2L ) ) 
+if (rJava:::.base.has.anyDuplicated) stopifnot( anyDuplicated( x ) == 2L )
+
+  p1 <- .jnew( "java/awt/Point" )
+  p2 <- .jnew( "java/awt/Point" )
+  x <- .jarray( list( p1, p2 ), dispatch = TRUE )
+  xd <- duplicated( x )
+  stopifnot( xd == c( FALSE, TRUE) )
+  if (rJava:::.base.has.anyDuplicated) stopifnot( anyDuplicated( x ) == 2L )
+
+# test sort, rev
+d1 <- .jnew("java/lang/Double", 0)
+d2 <- .jnew("java/lang/Double", -1)
+a <- .jarray( list( d1, d2), dispatch = TRUE )
+stopifnot( sort( a )[[1]]$doubleValue() == -1.0 )
+stopifnot( rev( a )[[1]]$doubleValue() == -1.0 )
+
+# test min, max, range
+Double <- J("java.lang.Double")
+a <- .jarray( list( new( Double, 10 ), new( Double, 4), new( Double, 5)
+), "java/lang/Double", dispatch = TRUE )
+stopifnot( min( a )$doubleValue() == 4  )
+stopifnot( max( a )$doubleValue() == 10 )
+stopifnot( range(a)[[1]]$doubleValue() == 4 )
+stopifnot( range(a)[[2]]$doubleValue() == 10)
+
+}
+}
+\keyword{classes}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jreflection.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jreflection.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..7d3b0600e1c8b15645dc8314798af1f6a545d6e9
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jreflection.Rd
@@ -0,0 +1,51 @@
+\name{jreflection}
+\alias{.jmethods}
+\alias{.jfields}
+\alias{.jconstructors}
+\title{
+  Simple helper functions for Java reflection
+}
+\description{
+  \code{.jconstructors} returns a character vector with all constructors for
+  a given class or object.
+  \code{.jmethods} returns a character vector with all methods for
+  a given class or object.
+  \code{.jfields} returns a character vector with all fileds (aka attributes) for a given class or object.
+}
+\usage{
+.jconstructors(o, as.obj = FALSE)
+.jmethods(o, name = NULL, as.obj = FALSE)
+.jfields(o, name = NULL, as.obj = FALSE)
+}
+\arguments{
+  \item{o}{Name of a class (either notation is fine) or an object whose
+    class will be queried}
+  \item{name}{Name of the method/field to look for. May contain regular
+    expressions except for \code{^$}.}
+  \item{as.obj}{if \code{TRUE} then a list of Java objects is
+    returned, otherwise a character vector (obtained by calling
+    \code{toString()} on each entry).}
+}
+\value{
+  Returns a character vector (if \code{as.obj} is \code{FALSE}) or a
+  list of Java objects. Each entry corresponds to the
+  \code{Constructor} resp. \code{Method} resp. \code{Field} object.
+}
+\details{
+  There first two functions are intended to help with finding correct
+  signatures for methods and constructors. Since the low-level API in
+  rJava doesn't use reflection automatically, it is necessary to
+  provide a proper  signature. That is somewhat easier using the above
+  methods.
+}
+\seealso{
+  \code{\link{.jcall}}, \code{\link{.jnew}}, \code{\link{.jcast}} or \code{\link{$,jobjRef-method}}
+}
+\examples{
+\dontrun{
+.jconstructors("java/util/Vector")
+v <- .jnew("java/util/Vector")
+.jmethods(v, "add")
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jserialize.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jserialize.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..29383d5784bf287dbdd6adb3de0ee81790d8f32d
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jserialize.Rd
@@ -0,0 +1,107 @@
+\name{jserialize}
+\alias{.jserialize}
+\alias{.junserialize}
+\alias{.jcache}
+\title{
+  Java object serialization
+}
+\description{
+  \code{.jserialize} serializes a Java object into raw vector using
+  Java serialization.
+
+  \code{.junserialize} re-constructs a Java object from its serialized
+  (raw-vector) form.
+
+  \code{.jcache} updates, retrieves or removes R-side object cache
+  which can be used for persistent storage of Java objects across
+  sessions.
+}
+\usage{
+.jserialize(o)
+.junserialize(data)
+.jcache(o, update=TRUE)
+}
+\arguments{
+  \item{o}{Java object}
+  \item{data}{serialized Java object as a raw vector}
+  \item{update}{must be \code{TRUE} (cache is updated), \code{FALSE}
+  (cache is retrieved) or \code{NULL} (cache is deleted).}
+}
+\value{
+  \code{.jserialize} returns a raw vector
+
+  \code{.junserialize} returns a Java object or \code{NULL} if an error
+  occurred (currently you may use \code{.jcheck()} to further
+  investigate the error)
+
+  \code{.jcache} returns the current cache (usually a raw vector) or
+  \code{NULL} if there is no cache.
+}
+\details{
+  Not all Java objects support serialization, see Java documentation
+  for details. Note that Java serialization and serialization of R
+  objects are two entirely different mechanisms that cannot be
+  interchanged. \code{.jserialize} and \code{.junserialize} can
+  be used to access Java serialization facilities.
+
+  \code{.jcache} manipulates the R-side Java object cache associated
+  with a given Java reference:
+
+  Java objects do not persist across sessions, because the Java
+  Virtual Machine (JVM) is destroyed when R is closed. All saved Java
+  object references will be restored as \code{null} references, since
+  the corresponding objects no longer exist (see R documentation on
+  serialization). However, it is possible to serialize a Java object
+  (if supported by the object) and store its serialized form in
+  R. This allows for the object to be deserialized when loaded into
+  another active session (but see notes below!)
+
+  R-side cache consists of a serialized form of the object as raw
+  vector. This cache is attached to the Java object and thus will be
+  saved when the Java object is saved. rJava provides an automated way
+  of deserializing Java references if they are \code{null} references
+  and have a cache attached. This is done on-demand basis whenever a
+  reference to a Java object is required.
+
+  Therefore packages can use \code{.jcache} to provide a way of
+  creating Java references that persist across sessions. However, they
+  must be very cautious in doing so. First, make sure the serialized
+  form is not too big. Storing whole datasets in Java serialized form
+  will hog immense amounts of memory on the R side and should be
+  avoided. In addition, be aware that the cache is just a snapshot, it
+  doesn't change when the referenced Java object is modified. Hence it
+  is most useful only for references that are not modified outside
+  R. Finally, internal references to other Java objects accessible
+  from R are not retained (see below). Most common use of
+  \code{.jcache} is with Java references that point to definitions of
+  methods (e.g., models) and other descriptive objects which are then
+  used by other, active Java classes to act upon. Caching of such
+  active objects is not a good idea, they should be instantiated by
+  functions that operate on the descriptive references instead.
+
+  \emph{Important note:} the serialization of Java references does NOT
+  take into account any dependencies on the R side. Therefore if you
+  hold a reference to a Java object in R that is also referenced by
+  the serialized Java object on the Java side, then this relationship
+  cannot be retained upon restore. Instead, two copies of disjoint
+  objects will be created which can cause confusion and errorneous
+  behavior.
+
+  The cache is attached to the reference external pointer and thus it
+  is shared with all copies of the same reference (even when changed
+  via \code{\link{.jcast}} etc.), but it is independent of other
+  references to the object obtained separately
+  (e.g., via \code{\link{.jcall}} or \code{\link{.jfield}}).
+
+  Also note that deserialization (even automated one) requires a
+  running virtual machine. Therefore you must make sure that either
+  \code{\link{.jinit}} or \code{\link{.jpackage}} is used before any
+  Java references are accessed.
+}
+%\seealso{
+%}
+%\examples{
+%\dontrun{
+%}
+%}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/jsimplify.Rd b/com.oracle.truffle.r.pkgs/rJava/man/jsimplify.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..59a8ed04624939d78d83db84ffd0566dde291749
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/jsimplify.Rd
@@ -0,0 +1,49 @@
+\name{jsimplify}
+\alias{.jsimplify}
+\title{
+  Converts Java object to a simple scalar if possible
+}
+\description{
+  \code{.jsimplify} attempts to convert Java objects that represent
+  simple scalars into corresponding scalar representation in R.
+}
+\usage{
+.jsimplify(o, promote=FALSE)
+}
+\arguments{
+  \item{o}{arbitrary object}
+  \item{promote}{logical, if \code{TRUE} then an ambiguous conversion
+  where the native type value would map to \code{NA} (e.g., Java
+  \code{int} type with value -2147483648) will be taken
+  to represent an actual value and will be promoted to a larger type
+  that can represent the value (in case of \code{int} promoted to
+  \code{double}). If \code{FALSE} then such values are assumed to
+  represent \code{NA}s.}
+}
+\value{
+  Simple scalar or \code{o} unchanged.
+}
+\details{
+  If \code{o} is not a Java object reference, \code{o} is returned
+  as-is. If \code{o} is a reference to a scalar object (such as single
+  integer, number, string or boolean) then the value of that object is
+  returned as R vector of the corresponding type and length one.
+
+  This function is used by \code{\link{.jfield}} to simplify the results
+  of field access if required.
+
+  Currently there is no function inverse to this, the usual way to wrap
+  scalar values in Java references is to use \code{\link{.jnew}} as the
+  corresponding constructor.
+}
+\seealso{
+  \code{\link{.jfield}}
+}
+\examples{
+\dontrun{
+i <- .jnew("java/lang/Integer", as.integer(10))
+print(i)
+print(.jsimplify(i))
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/loader.Rd b/com.oracle.truffle.r.pkgs/rJava/man/loader.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f7a8e4afebf1c8ac0bb74894bb5fd292e67ed43e
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/loader.Rd
@@ -0,0 +1,37 @@
+\name{loader}
+\alias{.jaddClassPath}
+\alias{.jclassPath}
+\title{
+  Java class loader
+}
+\description{
+  \code{.jaddClassPath} adds directories or JAR files to the class
+  path.
+
+  \code{.jclassPath} returns a vector containg the current entries in
+  the class path
+}
+\usage{
+.jaddClassPath(path)
+.jclassPath()
+}
+\arguments{
+  \item{path}{character string vector listing the paths to add to the
+    class path}
+}
+\value{
+  \code{.jclassPath} returns a character vector listing the class path sequence.
+}
+%\details{
+% 
+%}
+%\seealso{
+%  \code{\link{.jpackage}}
+%}
+\examples{
+\dontrun{
+.jaddClassPath("/my/jars/foo.jar","/my/classes/")
+print(.jclassPath())
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/new.Rd b/com.oracle.truffle.r.pkgs/rJava/man/new.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..8d76bfbb87c99cfca54a4425ba1a0c926c1928d2
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/new.Rd
@@ -0,0 +1,33 @@
+\name{new}
+\alias{new,jclassName-method}
+\title{
+  Create a new Java object
+}
+\description{
+  Creates a new Java object and invokes the constructor with given arguments.
+}
+\section{Methods}{
+  \describe{
+    \item{\code{new}}{\code{signature(Class = "jclassName")}: ... }
+  }
+}
+\details{
+  The \code{new} method is used as the high-level API to create new
+  Java objects (for low-level access see \code{\link{.jnew}}). It
+  returns the newly created Java object.
+
+  \code{...} arguments are passed to the constructor of the class
+  specified as \code{J("class.name")}.
+}
+\seealso{
+  \code{\link{.jnew}}, \code{\link{jclassName-class}}
+}
+\examples{
+\dontrun{
+v <- new(J("java.lang.String"), "Hello World!")
+v$length()
+v$indexOf("World")
+names(v)
+}
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/rep.Rd b/com.oracle.truffle.r.pkgs/rJava/man/rep.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..afd95df3f6f6331770018af57e31c3938860d1a6
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/rep.Rd
@@ -0,0 +1,32 @@
+\name{rep}
+\alias{rep,jarrayRef-method}
+\alias{rep,jobjRef-method}
+\alias{rep,jrectRef-method}
+
+\title{Creates java arrays by cloning}
+\description{ 
+	Creates a java array by cloning a reference several times
+}
+\section{Methods}{
+  \describe{
+    \item{rep}{\code{signature(object = "jobjRef")}: ... }
+    \item{rep}{\code{signature(object = "jarrayRef")}: ... }
+    \item{rep}{\code{signature(object = "jrectRef")}: ... }
+  }
+}
+
+\seealso{
+  \code{\link[base]{rep}} or \code{\link{.jarray}}
+}
+
+\examples{
+\dontshow{.jinit()}
+if (!nzchar(Sys.getenv("NOAWT"))) {
+  p <- .jnew( "java.awt.Point" )
+  a <- rep( p, 10 )
+
+  stopifnot( dim(a) == c(10L ) )
+  a[[1]]$move( 10L, 50L )
+  stopifnot( a[[2]]$getX() == 0.0 )
+}
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/show.Rd b/com.oracle.truffle.r.pkgs/rJava/man/show.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..4e0c5ab3607c4c31a568dc8e4c9bcdd28bdaf3ba
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/show.Rd
@@ -0,0 +1,21 @@
+\name{show}
+\alias{show,jobjRef-method}
+\alias{str,jobjRef-method}
+\alias{show,jarrayRef-method}
+\alias{show,jclassName-method}
+\title{Show a Java Object Reference}
+\description{
+  Display a Java object reference in a descriptive, textual form. The
+  default implementation calls \code{toString} Java method to obtain
+  object's printable value and uses calls \code{show} on the resulting
+  string garnished with additional details.
+}
+\section{Methods}{
+  \describe{
+    \item{show}{\code{signature(object = "jobjRef")}: ... }
+    \item{show}{\code{signature(object = "jarrayRef")}: ... }
+    \item{show}{\code{signature(object = "jclassName")}: ... }
+    \item{str}{\code{signature(object = "jobjRef")}: currently identical to show }
+  }
+}
+\keyword{interface}
diff --git a/com.oracle.truffle.r.pkgs/rJava/man/with.Rd b/com.oracle.truffle.r.pkgs/rJava/man/with.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..86c5e301d585d8a99dc80f28961de14c38563366
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/man/with.Rd
@@ -0,0 +1,106 @@
+\name{with.jobjRef}
+\alias{with.jobjRef}
+\alias{within.jobjRef}
+\alias{with.jarrayRef}
+\alias{within.jarrayRef}
+\alias{with.jclassName}
+\alias{within.jclassName}
+\title{
+with and within methods for Java objects and class names
+}
+\description{
+Convenience wrapper that allow calling methods of 
+Java object and classes from within the object (or class).
+}
+\usage{
+\S3method{with}{jobjRef}(data, expr, ...)
+\S3method{within}{jobjRef}(data, expr, ...)
+
+\S3method{with}{jarrayRef}(data, expr, ...)
+\S3method{within}{jarrayRef}(data, expr, ...)
+
+\S3method{with}{jclassName}(data, expr, ...)
+\S3method{within}{jclassName}(data, expr, ...)
+}
+\arguments{
+ \item{data}{
+ A Java object reference or a java class name. See \code{\link{J}}
+}
+ \item{expr}{
+R expression to evaluate
+}
+ \item{\dots}{
+ignored
+}
+}
+\details{
+The expression is evaluated in an environment 
+that contains a mapping between the public fields 
+and methods of the object. 
+
+The methods of the object are mapped to standard R functions
+in the environment. In case of classes, only static methods
+are used.
+
+The fields of the object are mapped to active bindings
+(see \link{makeActiveBinding}) so that they can be accessed
+and modified from within the environment. For classes, only 
+static fields are used.
+}
+\value{
+	\code{with} returns the value of the expression and 
+	\code{within} returns the \code{data} argument
+}
+\author{
+Romain Francois <francoisromain@free.fr>
+}
+\references{
+	the \code{java.lang.reflect} package: 
+	\url{http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/package-summary.html}
+}
+\examples{
+\dontshow{.jinit()}
+
+if (!nzchar(Sys.getenv("NOAWT"))) {
+  p <- .jnew( "java/awt/Point", 0L, 0L )
+  with( p, {
+	# x and y and now 0
+	move( 10L, 10L )
+	# x and y are now 10
+	x <- x + y
+  } )
+
+  f <- within( .jnew( "javax/swing/JFrame" ) , {
+	layout <- .jnew( "java/awt/BorderLayout" )
+	setLayout( layout )
+	add( .jnew( "javax/swing/JLabel", "north" ), layout$NORTH )
+	add( .jnew( "javax/swing/JLabel", "south" ), layout$SOUTH )
+	add( .jnew( "javax/swing/JLabel", "west" ), layout$WEST )
+	add( .jnew( "javax/swing/JLabel", "east" ), layout$EAST )
+	setSize( .jnew( "java/awt/Dimension", 400L, 400L ) )
+	setVisible( TRUE )
+  } )
+}
+
+Double <- J("java.lang.Double")
+with( Double, MIN_VALUE )
+with( Double, parseDouble( "10.2" ) )
+
+\dontrun{
+# inner class example
+% TODO: find a better example
+HashMap <- J("java.util.HashMap")
+with( HashMap, new( SimpleEntry, "key", "value" ) )
+with( HashMap, SimpleEntry )
+}
+
+with( J("java.lang.System"), getProperty("java.home") )
+
+\dontshow{
+stopifnot( with( Double, parseDouble("10.0") ) == 10.0 )
+d <- new( Double, "10.0") 
+stopifnot( with( d, doubleValue() ) == 10.0 )
+}
+
+}
+\keyword{ classes }
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/Makevars b/com.oracle.truffle.r.pkgs/rJava/src/Makevars
new file mode 100644
index 0000000000000000000000000000000000000000..238e93d69d420cb6688da8529b34dc0ec0f53409
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/Makevars
@@ -0,0 +1,14 @@
+JAVA_SRC=$(wildcard java/*.java)
+JFLAGS=-source 1.6 -target 1.6
+JAVAC=javac
+
+all: $(SHLIB)
+$(SHLIB): java
+
+.PHONY: all java
+
+java: $(JAVA_SRC)
+	$(JAVAC) $(JFLAGS) $(JAVA_SRC)
+	rm -rfv ../inst/java
+	mkdir -p ../inst/java
+	mv java/*.class ../inst/java
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/ArrayDimensionException.java b/com.oracle.truffle.r.pkgs/rJava/src/java/ArrayDimensionException.java
new file mode 100644
index 0000000000000000000000000000000000000000..56f86de3874fd5551b775db020de677016ffefa8
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/ArrayDimensionException.java
@@ -0,0 +1,15 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+public class ArrayDimensionException extends Exception{
+	public ArrayDimensionException(String message){
+		super( message ) ; 
+	}
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/ArrayWrapper.java b/com.oracle.truffle.r.pkgs/rJava/src/java/ArrayWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..388aadc5c14e948c12822938be8aa275c61050c5
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/ArrayWrapper.java
@@ -0,0 +1,386 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+// :tabSize=2:indentSize=2:noTabs=false:folding=explicit:collapseFolds=1:
+
+import java.lang.reflect.Array ; 
+
+/** 
+ * Utility class to deal with arrays
+ */
+public class ArrayWrapper extends RJavaArrayIterator {
+
+	/**
+	 * is this array rectangular
+	 */ 
+	private boolean isRect ;
+	
+	/**
+	 * The type name of the objects stored
+	 */
+	private String typeName ;
+	
+	/**
+	 * true if the array stores primitive types
+	 */
+	private boolean primitive ;
+	
+	private int length ; 
+	
+	/**
+	 * Constructor
+	 *
+	 * @param array the array to check
+	 * @throws NotAnArrayException if array is not an array
+	 */
+	public ArrayWrapper(Object array) throws NotAnArrayException {
+		super( RJavaArrayTools.getDimensions(array) );
+		this.array = array ;
+		typeName = RJavaArrayTools.getObjectTypeName(array );
+		primitive = RJavaArrayTools.isPrimitiveTypeName( typeName ) ;
+		if( dimensions.length == 1){
+			isRect = true ;
+		} else{
+			isRect = isRectangular_( array, 0 );
+		}
+		// reset the dimensions if the array is not rectangular
+		if( !isRect ){
+			dimensions = null ;
+			length = -1; 
+		} else{
+			length = 1; 
+			for( int i=0; i<dimensions.length; i++) {
+				length *= dimensions[i] ;
+			}
+		}
+	}
+	
+	// making java < 1.5 happy
+	public ArrayWrapper(int x)      throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(boolean x)  throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(byte x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(long x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(short x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(double x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(char x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	public ArrayWrapper(float x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type") ; }
+	
+	
+	/**
+	 * @return true if the array is rectangular
+	 */
+	public boolean isRectangular( ){
+		return isRect ;
+	}
+	
+	/**
+	 * Recursively check all dimensions to see if an array is rectangular
+	 */
+	private boolean isRectangular_(Object o, int depth){
+		if( depth == dimensions.length ) return true ; 
+		int n = Array.getLength(o) ;
+		if( n != dimensions[depth] ) return false ;
+		for( int i=0; i<n; i++){
+			if( !isRectangular_(Array.get(o, i),  depth+1) ){
+				return false;
+			}
+		}
+		return true ;
+	}
+	
+	/**
+	 * @return the type name of the objects stored in the wrapped array
+	 */
+	public String getObjectTypeName(){
+		return typeName; 
+	}
+	
+	/** 
+	 * @return true if the array contains java primitive types
+	 */ 
+	public boolean isPrimitive(){
+		return primitive ; 
+	}
+	
+	// {{{ flat_* methods
+	
+	// {{{ flat_int
+	/**
+	 * Flattens the array into a single dimensionned int array
+	 */ 
+	public int[] flat_int() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "I".equals(typeName) ) throw new PrimitiveArrayException("int"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (int[])array ;
+		} else{
+			int[] payload = new int[length] ;
+			
+			int k; 
+			while( hasNext() ){
+				int[] current = (int[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ; 
+		}
+	}
+	// }}}
+	
+	// {{{ flat_boolean
+	/**
+	 * Flattens the array into a single dimensionned boolean array
+	 * 
+	 */ 
+	public boolean[] flat_boolean() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "Z".equals(typeName) ) throw new PrimitiveArrayException("boolean"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (boolean[])array ;
+		} else{
+			boolean[] payload = new boolean[length] ;
+			
+			int k; 
+			while( hasNext() ){
+				boolean[] current = (boolean[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ;
+		}
+	}
+	// }}}
+	
+	// {{{ flat_byte
+	/**
+	 * Flattens the array into a single dimensionned byte array
+	 * 
+	 */ 
+	public byte[] flat_byte() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "B".equals(typeName) ) throw new PrimitiveArrayException("byte"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (byte[])array ;
+		} else{
+			byte[] payload = new byte[length] ;
+			int k; 
+			while( hasNext() ){
+				byte[] current = (byte[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ;  
+		}
+	}
+
+	// }}}
+	
+	// {{{ flat_long
+	/**
+	 * Flattens the array into a single dimensionned long array
+	 * 
+	 */ 
+	public long[] flat_long() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "J".equals(typeName) ) throw new PrimitiveArrayException("long"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (long[])array ;
+		} else{
+			long[] payload = new long[length] ;
+			int k; 
+			while( hasNext() ){
+				long[] current = (long[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ; 
+		}
+	}
+	
+	// }}}
+	
+	// {{{ flat_short
+	/**
+	 * Flattens the array into a single dimensionned short array
+	 * 
+	 */ 
+		public short[] flat_short() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "S".equals(typeName) ) throw new PrimitiveArrayException("short"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (short[])array ;
+		} else{
+			short[] payload = new short[length] ;
+			int k; 
+			while( hasNext() ){
+				short[] current = (short[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ;
+ 		}
+	}
+// }}}
+
+	// {{{ flat_double
+	/**
+	 * Flattens the array into a single dimensionned double array
+	 * 
+	 */ 
+	public double[] flat_double() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "D".equals(typeName) ) throw new PrimitiveArrayException("double"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (double[])array ;
+		} else{
+			double[] payload= new double[length] ;
+			int k; 
+			while( hasNext() ){
+				double[] current = (double[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ;
+ 		}
+	}
+
+	// }}}
+	
+	// {{{ flat_char
+	/**
+	 * Flattens the array into a single dimensionned double array
+	 * 
+	 */ 
+	public char[] flat_char() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "C".equals(typeName) ) throw new PrimitiveArrayException("char"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (char[])array ;
+		} else{
+			char[] payload = new char[length] ;
+			int k; 
+			while( hasNext() ){
+				char[] current = (char[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ; 
+		}
+	}
+	
+	// }}}
+
+	// {{{ flat_float
+	/**
+	 * Flattens the array into a single dimensionned float array
+	 * 
+	 */ 
+	public float[] flat_float() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "F".equals(typeName) ) throw new PrimitiveArrayException("float"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (float[])array ;
+		} else{
+			float[] payload = new float[length] ;
+			int k; 
+			while( hasNext() ){
+				float[] current = (float[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ; 
+		}
+	}
+	
+	// }}}
+	
+	// {{{ flat_Object
+	public Object[] flat_Object() throws FlatException, ObjectArrayException {
+		if( isPrimitive() ) throw new ObjectArrayException( typeName) ; 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (Object[])array ;
+		} else{
+			ClassLoader loader = array.getClass().getClassLoader() ;
+			Class type = Object.class; 
+			try{
+				type = Class.forName( typeName, true, array.getClass().getClassLoader() );
+			} catch( ClassNotFoundException e){}
+			
+			Object[] payload = (Object[])Array.newInstance( type,  length ) ; 
+			int k; 
+			while( hasNext() ){
+				Object[] current = (Object[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = type.cast( current[j] );
+				}
+			}
+			return payload ; 
+		}
+	}
+	// }}}
+	
+	// {{{ flat_String
+	/**
+	 * Flattens the array into a single dimensionned String array
+	 * 
+	 */ 
+	// this is technically not required as this can be handled
+	// by flat_Object but this is slightly more efficient so ...
+	public String[] flat_String() throws PrimitiveArrayException,FlatException {
+		
+		if( ! "java.lang.String".equals(typeName) ) throw new PrimitiveArrayException("java.lang.String"); 
+		if( !isRect ) throw new FlatException(); 
+		if( dimensions.length == 1 ){
+			return (String[])array ;
+		} else{
+			String[] payload = new String[length] ;
+			int k; 
+			while( hasNext() ){
+				String[] current = (String[])next() ;
+				k = start ; 
+				for( int j=0; j<current.length; j++, k+=increment){
+					payload[k] = current[j] ;
+				}
+			}
+			return payload ; 
+		}
+	}
+	// }}}
+	
+	// }}}
+	
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/DummyPoint.java b/com.oracle.truffle.r.pkgs/rJava/src/java/DummyPoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec0f600b7e297d65d7c4fb7bc3479e56a789ae18
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/DummyPoint.java
@@ -0,0 +1,30 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+public class DummyPoint implements Cloneable {
+	public int x; 
+	public int y ;
+	public DummyPoint(){
+		this( 0, 0 ) ;
+	}
+	public DummyPoint( int x, int y){
+		this.x = x ;
+		this.y = y ;
+	}
+	public double getX(){
+		return (double)x ;
+	}
+	public void move(int x, int y){
+		this.x += x ;
+		this.y += y ;
+	}
+	
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/FlatException.java b/com.oracle.truffle.r.pkgs/rJava/src/java/FlatException.java
new file mode 100644
index 0000000000000000000000000000000000000000..91ce8a08f77268c43789b43a3fec6fd28e39ca26
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/FlatException.java
@@ -0,0 +1,19 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+/**
+ * Generated when one attemps to flatten an array that is not rectangular
+ */
+public class FlatException extends Exception{
+	public FlatException(){
+		super( "Can only flatten rectangular arrays" ); 
+	}
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/Makefile b/com.oracle.truffle.r.pkgs/rJava/src/java/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a476c847334dd6a103e70c02d9938cdc50546615
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/Makefile
@@ -0,0 +1,45 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006, Simon Urbanek
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+JAVA_SRC=$(wildcard *.java)
+JFLAGS=-source 1.6 -target 1.6
+JAVAC=javac
+JAVA=java
+JAVADOC=javadoc
+JAVADOCFLAGS=-author -version -breakiterator -link http://java.sun.com/j2se/1.4.2/docs/api
+
+all: compile test
+
+compile: $(JAVA_SRC)
+	$(JAVAC) $(JFLAGS) $(JAVA_SRC)
+
+test_RJavaTools: compile
+	$(JAVA) RJavaTools_Test
+
+test_RJavaArrayTools: compile
+	$(JAVA) RJavaArrayTools_Test
+
+test_ArrayWrapper:
+	$(JAVA) ArrayWrapper_Test
+
+test_RectangularArrayBuilder:
+	$(JAVA) RectangularArrayBuilder_Test
+
+test: compile test_RJavaTools test_RJavaArrayTools test_ArrayWrapper test_RectangularArrayBuilder
+
+javadoc:
+	$(JAVADOC) $(JAVADOCFLAGS) -d javadoc $(JAVA_SRC)
+
+clean:
+	rm -rfv *.class *~
+
+.PHONY: all clean
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/NotAnArrayException.java b/com.oracle.truffle.r.pkgs/rJava/src/java/NotAnArrayException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f9cf8f23f233c9eea9533c92f7dec2099c66e85
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/NotAnArrayException.java
@@ -0,0 +1,23 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+/**
+ * Exception indicating that an object is not a java array
+ */
+public class NotAnArrayException extends Exception{
+	public NotAnArrayException(Class clazz){
+		super( "not an array : " + clazz.getName() ) ;
+	}
+	public NotAnArrayException(String message){
+		super( message ) ;
+	}
+}
+	
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/NotComparableException.java b/com.oracle.truffle.r.pkgs/rJava/src/java/NotComparableException.java
new file mode 100644
index 0000000000000000000000000000000000000000..73eac55972345735d33d9627354279949fc59217
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/NotComparableException.java
@@ -0,0 +1,35 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+/**
+ * Exception generated when two objects cannot be compared
+ * 
+ * Such cases happen when an object does not implement the Comparable 
+ * interface or when the comparison produces a ClassCastException
+ */
+public class NotComparableException extends Exception{
+	public NotComparableException(Object a, Object b){
+		super( "objects of class " + a.getClass().getName() + 
+			" and " + b.getClass().getName() + " are not comparable"  ) ;
+	}
+	public NotComparableException( Object o){
+		this( o.getClass().getName() ) ;
+	}
+	
+	public NotComparableException( Class cl){
+		this( cl.getName() ) ;
+	}
+	
+	public NotComparableException( String type ){
+		super( "class " + type + " does not implement java.util.Comparable" ) ; 
+	}
+	
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/ObjectArrayException.java b/com.oracle.truffle.r.pkgs/rJava/src/java/ObjectArrayException.java
new file mode 100644
index 0000000000000000000000000000000000000000..9333fd07470dee580940dc77c2cf884fb66d4858
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/ObjectArrayException.java
@@ -0,0 +1,21 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+/**
+ * Generated when one tries to access an array of primitive
+ * values as an array of Objects
+ */
+public class ObjectArrayException extends Exception{
+	public ObjectArrayException(String type){
+		super( "array is of primitive type : " + type ) ; 
+	}
+	
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/PrimitiveArrayException.java b/com.oracle.truffle.r.pkgs/rJava/src/java/PrimitiveArrayException.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4f60fcdf572ea584d5a84fd8b977279986134a7
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/PrimitiveArrayException.java
@@ -0,0 +1,21 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+/**
+ * Generated when one tries to convert an arrays into 
+ * a primitive array of the wrong type
+ */
+public class PrimitiveArrayException extends Exception{
+	public PrimitiveArrayException(String type){
+		super( "cannot convert to single dimension array of primitive type" + type ) ; 
+	}
+	
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayIterator.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b4dfd1e7254dae4fa72d203301bff14d5daf948
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayIterator.java
@@ -0,0 +1,96 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+import java.lang.reflect.Array ;
+
+public abstract class RJavaArrayIterator {
+
+	protected int[] dimensions; 
+	protected int nd ; 
+	protected int[] index ;
+	protected int[] dimprod ;
+	protected Object array ;
+	protected int increment; 
+	protected int position ;
+	protected int start ;
+	
+	public Object getArray(){
+		return array ; 
+	}
+	
+	/**
+	 * @return the class name of the array
+	 */
+	public String getArrayClassName(){
+		return array.getClass().getName();
+	}
+	
+	public int[] getDimensions(){
+		return dimensions; 
+	}
+	
+	public RJavaArrayIterator(){
+		dimensions = null; 
+		index = null ;
+		dimprod = null ;
+		array = null ;
+	}
+	
+	public RJavaArrayIterator(int[] dimensions){
+		this.dimensions = dimensions ; 
+		nd = dimensions.length ;
+		if( nd > 1){
+			index = new int[ nd-1 ] ;
+			dimprod = new int[ nd-1 ] ;
+			for( int i=0; i<(nd-1); i++){
+				index[i] = 0 ;
+				dimprod[i] = (i==0) ? dimensions[i] : ( dimensions[i]*dimprod[i-1] );
+				increment = dimprod[i] ;
+			}
+		}
+		position = 0 ;
+		start = 0; 
+	}
+	public RJavaArrayIterator(int d1){
+		this( new int[]{ d1} ) ;
+	}
+	
+	protected Object next( ){
+		
+		/* get the next array and the position of the first elemtn in the flat array */
+		Object o = array ;
+		for( int i=0; i<index.length; i++){
+			o = Array.get( o, index[i] ) ;
+			if( i == 0 ) {
+				start = index[i]; 
+			} else {
+				start += index[i] * dimprod[i-1] ;
+			}
+		}
+		
+		/* increment the index */
+		for( int i=index.length-1; i>=0; i--){
+			if( (index[i] + 1) == dimensions[i] ){
+				index[i] = 0 ; 
+			} else{
+				index[i] = index[i] + 1 ;
+			}
+		}
+				
+		position++ ;
+		return o; 
+	}
+	
+	protected boolean hasNext( ){
+		return position < increment ;
+	}
+	
+	
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayTools.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..87658c8a8094d1c3b697d30a4111d6205949974a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayTools.java
@@ -0,0 +1,738 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2009-2010, Simon Urbanek and Romain Francois
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+import java.lang.reflect.Array ; 
+import java.util.Map; 
+import java.util.HashMap;
+import java.util.Vector ;
+import java.util.Arrays ;
+import java.util.Iterator;
+
+import java.lang.reflect.Method ;
+import java.lang.reflect.InvocationTargetException ;
+
+public class RJavaArrayTools {
+
+	// TODO: maybe factor this out of this class
+	private static Map primitiveClasses = initPrimitiveClasses() ;
+	private static Map initPrimitiveClasses(){
+		Map primitives = new HashMap(); 
+		primitives.put( "I", Integer.TYPE ); 
+		primitives.put( "Z", Boolean.TYPE );
+		primitives.put( "B", Byte.TYPE );
+		primitives.put( "J", Long.TYPE );
+		primitives.put( "S", Short.TYPE );
+		primitives.put( "D", Double.TYPE );
+		primitives.put( "C", Character.TYPE );
+		primitives.put( "F", Float.TYPE );
+		return primitives; 
+	}
+	
+	// {{{ getObjectTypeName
+	/**
+	 * Get the object type name of an multi dimensional array.
+	 * 
+	 * @param o object
+	 * @throws NotAnArrayException if the object is not an array
+	 */
+	public static String getObjectTypeName(Object o) throws NotAnArrayException {
+		Class o_clazz = o.getClass();
+		if( !o_clazz.isArray() ) throw new NotAnArrayException( o_clazz ); 
+		
+		String cl = o_clazz.getName();
+		return cl.replaceFirst("\\[+L?", "").replace(";", "") ; 
+	}
+	public static int getObjectTypeName(int x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type : int     ") ; }
+	public static int getObjectTypeName(boolean x) throws NotAnArrayException { throw new NotAnArrayException("primitive type : boolean ") ; }
+	public static int getObjectTypeName(byte x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : byte    ") ; }
+	public static int getObjectTypeName(long x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : long    ") ; }
+	public static int getObjectTypeName(short x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : short   ") ; }
+	public static int getObjectTypeName(double x)  throws NotAnArrayException { throw new NotAnArrayException("primitive type : double  ") ; }
+	public static int getObjectTypeName(char x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : char    ") ; }
+	public static int getObjectTypeName(float x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : float   ") ; }
+	// }}}
+	
+	// {{{ makeArraySignature
+	// TODO: test
+	public static String makeArraySignature( String typeName, int depth ){
+		StringBuffer buffer = new StringBuffer() ;
+		for( int i=0; i<depth; i++){
+			buffer.append( '[' ) ; 
+		}
+		buffer.append( typeName ); 
+		if( ! isPrimitiveTypeName( typeName ) ){
+			buffer.append( ';') ;
+		}
+		return buffer.toString(); 
+	}
+	// }}}
+	
+	// {{{ getClassForSignature
+	public static Class getClassForSignature(String signature, ClassLoader loader) throws ClassNotFoundException {
+		if( primitiveClasses.containsKey(signature) ){
+			return (Class)primitiveClasses.get( signature ) ;
+		}
+		return Class.forName(signature, true, loader) ;
+	}
+	// }}}
+	
+	// {{{ isSingleDimensionArray
+	public static boolean isSingleDimensionArray( Object o) throws NotAnArrayException{
+		if( !isArray(o) ) throw new NotAnArrayException( o.getClass() ) ;
+		
+		String cn = o.getClass().getName() ; 
+		if( cn.lastIndexOf('[') != 0 ) return false; 
+		return true ; 
+	}
+	// }}}
+	
+	// {{{ isPrimitiveTypeName
+	public static boolean isPrimitiveTypeName(String name){
+		if( name.length() > 1 ) return false; 
+		if( name.equals("I") ) return true ;
+		if( name.equals("Z") ) return true ;
+		if( name.equals("B") ) return true ;
+		if( name.equals("J") ) return true ;
+		if( name.equals("S") ) return true ;
+		if( name.equals("D") ) return true ;
+		if( name.equals("C") ) return true ;
+		if( name.equals("F") ) return true ;
+		return false; 
+	}
+	// }}}
+	
+	// {{{ isRectangularArray
+	/**
+	 * Indicates if o is a rectangular array
+	 * 
+	 * @param o an array
+	 * @deprecated use new ArrayWrapper(o).isRectangular() instead
+	 */
+	public static boolean isRectangularArray(Object o) {
+		if( !isArray(o) ) return false; 
+		boolean res = false; 
+		try{
+			if( getDimensionLength( o ) == 1 ) return true ;
+			res = ( new ArrayWrapper(o) ).isRectangular() ;
+		} catch( NotAnArrayException e){
+			res = false; 
+		}
+		return res ;
+	}
+	
+	
+	// thoose below make java < 1.5 happy and me unhappy ;-)
+	public static boolean isRectangularArray(int x)      { return false ; }
+	public static boolean isRectangularArray(boolean x)  { return false ; }
+	public static boolean isRectangularArray(byte x)     { return false ; }
+	public static boolean isRectangularArray(long x)     { return false ; }
+	public static boolean isRectangularArray(short x)    { return false ; }
+	public static boolean isRectangularArray(double x)   { return false ; }
+	public static boolean isRectangularArray(char x)     { return false ; }
+	public static boolean isRectangularArray(float x)    { return false ; }
+	
+	// }}}
+	
+	// {{{ getDimensionLength
+	/** 
+	 * Returns the number of dimensions of an array
+	 *
+	 * @param o an array
+	 * @throws NotAnArrayException if this is not an array
+	 */
+	public static int getDimensionLength( Object o) throws NotAnArrayException, NullPointerException {
+		if( o == null ) throw new NullPointerException( "array is null" ) ;
+		Class clazz = o.getClass();
+		if( !clazz.isArray() ) throw new NotAnArrayException(clazz) ;
+		int n = 0; 
+		while( clazz.isArray() ){
+			n++ ; 
+			clazz = clazz.getComponentType() ;
+		}
+		return n ; 
+	}
+	// thoose below make java < 1.5 happy and me unhappy ;-)
+	public static int getDimensionLength(int x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type : int     ") ; }
+	public static int getDimensionLength(boolean x) throws NotAnArrayException { throw new NotAnArrayException("primitive type : boolean ") ; }
+	public static int getDimensionLength(byte x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : byte    ") ; }
+	public static int getDimensionLength(long x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : long    ") ; }
+	public static int getDimensionLength(short x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : short   ") ; }
+	public static int getDimensionLength(double x)  throws NotAnArrayException { throw new NotAnArrayException("primitive type : double  ") ; }
+	public static int getDimensionLength(char x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : char    ") ; }
+	public static int getDimensionLength(float x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : float   ") ; }
+	// }}}                                                                                          
+	
+	// {{{ getDimensions
+	/** 
+	 * Returns the dimensions of an array
+	 *
+	 * @param o an array
+	 * @throws NotAnArrayException if this is not an array
+	 * @return the dimensions of the array or null if the object is null
+	 */
+	public static int[] getDimensions( Object o) throws NotAnArrayException, NullPointerException {
+		if( o == null ) throw new NullPointerException( "array is null" )  ;
+		
+		Class clazz = o.getClass();
+		if( !clazz.isArray() ) throw new NotAnArrayException(clazz) ;
+		Object a = o ;
+		
+		int n = getDimensionLength( o ) ; 
+		int[] dims = new int[n] ;
+		int i=0;
+		int current ; 
+		while( clazz.isArray() ){
+			current = Array.getLength( a ) ;
+			dims[i] = current ;
+			i++;
+			if( current == 0 ){
+				break ; // the while loop 
+			} else {
+				a = Array.get( a, 0 ) ;
+				clazz = clazz.getComponentType() ;
+			}
+		}
+		
+		/* in case of premature stop, we fill the rest of the array with 0 */
+		// this might not be true: 
+		// Object[][] = new Object[0][10] will return c(0,0)
+		while( i < dims.length){
+			dims[i] = 0 ;
+			i++ ;
+		}
+		return dims ; 
+	}
+	// thoose below make java < 1.5 happy and me unhappy ;-)
+	public static int[] getDimensions(int x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type : int     ") ; }
+	public static int[] getDimensions(boolean x) throws NotAnArrayException { throw new NotAnArrayException("primitive type : boolean ") ; }
+	public static int[] getDimensions(byte x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : byte    ") ; }
+	public static int[] getDimensions(long x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : long    ") ; }
+	public static int[] getDimensions(short x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : short   ") ; }
+	public static int[] getDimensions(double x)  throws NotAnArrayException { throw new NotAnArrayException("primitive type : double  ") ; }
+	public static int[] getDimensions(char x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : char    ") ; }
+	public static int[] getDimensions(float x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : float   ") ; }
+	// }}}                                                                                          
+	
+	// {{{ getTrueLength
+	/** 
+	 * Returns the true length of an array (the product of its dimensions)
+	 *
+	 * @param o an array
+	 * @throws NotAnArrayException if this is not an array
+	 * @return the number of objects in the array (the product of its dimensions).
+	 */
+	public static int getTrueLength( Object o) throws NotAnArrayException, NullPointerException {
+		if( o == null ) throw new NullPointerException( "array is null" ) ;
+		
+		Class clazz = o.getClass();
+		if( !clazz.isArray() ) throw new NotAnArrayException(clazz) ;
+		Object a = o ;
+		
+		int len = 1 ;
+		int i = 0; 
+		while( clazz.isArray() ){
+			len = len * Array.getLength( a ) ;
+			if( len == 0 ) return 0 ; /* no need to go further */
+			i++;
+			a = Array.get( a, 0 ) ;
+			clazz = clazz.getComponentType() ;
+		}
+		return len ; 
+	}
+	// thoose below make java < 1.5 happy and me unhappy ;-)
+	public static int getTrueLength(int x)     throws NotAnArrayException { throw new NotAnArrayException("primitive type : int     ") ; }
+	public static int getTrueLength(boolean x) throws NotAnArrayException { throw new NotAnArrayException("primitive type : boolean ") ; }
+	public static int getTrueLength(byte x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : byte    ") ; }
+	public static int getTrueLength(long x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : long    ") ; }
+	public static int getTrueLength(short x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : short   ") ; }
+	public static int getTrueLength(double x)  throws NotAnArrayException { throw new NotAnArrayException("primitive type : double  ") ; }
+	public static int getTrueLength(char x)    throws NotAnArrayException { throw new NotAnArrayException("primitive type : char    ") ; }
+	public static int getTrueLength(float x)   throws NotAnArrayException { throw new NotAnArrayException("primitive type : float   ") ; }
+	// }}}                                                                                          
+	
+	// {{{ isArray
+	/**
+	 * Indicates if a java object is an array
+	 * 
+	 * @param o object
+	 * @return true if the object is an array
+	 * @deprecated use RJavaArrayTools#isArray
+	 */
+	public static boolean isArray(Object o){
+		if( o == null) return false ; 
+		return o.getClass().isArray() ; 
+	}
+	// thoose below make java < 1.5 happy and me unhappy ;-)
+	public static boolean isArray(int x){ return false ; }
+	public static boolean isArray(boolean x){ return false ; }
+	public static boolean isArray(byte x){ return false ; }
+	public static boolean isArray(long x){ return false ; }
+	public static boolean isArray(short x){ return false ; }
+	public static boolean isArray(double x){ return false ; }
+	public static boolean isArray(char x){ return false ; }
+	public static boolean isArray(float x){ return false ; }
+	// }}}
+	
+	// {{{ ArrayDimensionMismatchException
+	public static class ArrayDimensionMismatchException extends Exception {
+		public ArrayDimensionMismatchException( int index_dim, int actual_dim ){
+			super( "dimension of indexer (" + index_dim + ") too large for array (depth ="+ actual_dim+ ")") ;
+		}
+	}
+	// }}}
+	
+	// {{{ get
+	/**
+	 * Gets a single object from a multi dimensional array
+	 *
+	 * @param array java array
+	 * @param position
+	 */
+	public static Object get( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.get( getArray( array, position ), position[ position.length -1] ); 
+	}
+	
+	public static int getInt( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getInt( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static boolean getBoolean( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getBoolean( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static byte getByte( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getByte( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static long getLong( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getLong( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static short getShort( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getShort( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static double getDouble( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getDouble( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static char getChar( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getChar( getArray( array, position ), position[ position.length -1] ); 
+	}
+	public static float getFloat( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return Array.getFloat( getArray( array, position ), position[ position.length -1] ); 
+	}
+
+	
+	public static Object get( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return get( array, new int[]{position} ) ;
+	}
+	public static int getInt( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getInt( array, new int[]{position} ) ; 
+	}
+	public static boolean getBoolean( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getBoolean( array, new int[]{position} ) ; 
+	}
+	public static byte getByte( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getByte( array, new int[]{position} ) ; 
+	}
+	public static long getLong( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getLong( array, new int[]{position} ) ; 
+	}
+	public static short getShort( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getShort( array, new int[]{position} ) ; 
+	}
+	public static double getDouble( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getDouble( array, new int[]{position} ) ; 
+	}
+	public static char getChar( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getChar( array, new int[]{position} ) ;
+	}
+	public static float getFloat( Object array, int position ) throws NotAnArrayException, ArrayDimensionMismatchException {
+		return getFloat( array, new int[]{position} ) ; 
+	}
+	
+	private static void checkDimensions(Object array, int[] position) throws NotAnArrayException, ArrayDimensionMismatchException {
+		int poslength = position.length ;
+		int actuallength = getDimensionLength(array); 
+		if( poslength > actuallength ){
+			throw new ArrayDimensionMismatchException( poslength, actuallength ) ; 
+		}
+	}
+	
+	// }}}
+	
+	// {{{ set
+	/**
+	 * Replaces a single value of the array 
+	 *
+	 * @param array array 
+	 * @param position index
+	 * @param value the new value
+	 * 
+	 * @throws NotAnArrayException if array is not an array
+	 * @throws ArrayDimensionMismatchException if the length of position is too big
+	 */
+	public static void set( Object array, int[] position, Object value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.set( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	
+	/* primitive versions */
+	public static void set( Object array, int[] position, int value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setInt( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, boolean value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setBoolean( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, byte value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setByte( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, long value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setLong( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, short value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setShort( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, double value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setDouble( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, char value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setChar( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+	public static void set( Object array, int[] position, float value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		Array.setFloat( getArray( array, position ), position[ position.length - 1], value ) ;
+	}
+
+	
+	public static void set( Object array, int position, Object value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value ); 
+	}
+	public static void set( Object array, int position, int value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, boolean value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, byte value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, long value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, short value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, double value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, char value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+	public static void set( Object array, int position, float value ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		set( array, new int[]{ position }, value );
+	}
+
+
+	
+	private static Object getArray( Object array, int[] position ) throws NotAnArrayException, ArrayDimensionMismatchException{
+		checkDimensions( array, position ) ;
+		int poslength = position.length ;
+		
+		Object o = array ;
+		int i=0 ;
+		if( poslength > 1 ){
+			while( i< (poslength-1) ){
+					o = Array.get( o, position[i] ) ;
+					i++ ;
+			}
+		}
+		return o ;
+	}
+	
+	// TODO: also have primitive types in value
+	// }}}
+	
+
+	// {{{ unique
+	// TODO: cannot use LinkedHashSet because it first was introduced in 1.4 
+	//       and code in this area needs to work on 1.2 jvm
+	public static Object[] unique( Object[] array ){
+		int n = array.length ;
+		boolean[] unique = new boolean[ array.length ];
+		for( int i=0; i<array.length; i++){
+			unique[i] = true ; 
+		}
+		
+		Vector res = new Vector();
+		boolean added ;
+		for( int i=0; i<n; i++){
+			if( !unique[i] ) continue ;
+			Object current = array[i];
+			added = false; 
+			
+			for( int j=i+1; j<n; j++){
+				Object o_j = array[j] ;
+				if( unique[j] && current.equals( o_j ) ){
+					if( !added ){
+						unique[i] = false; 
+						res.add( current ); 
+						added = true ;
+					}
+					unique[j] = false;
+				}
+			}
+		}
+		// build the array using newInstance so that it has the same
+		// component type as the original array and not just Object
+		Object[] res_array = (Object[])Array.newInstance( array.getClass().getComponentType(), res.size() ) ;
+		res.toArray( res_array ); 
+		return res_array ;
+	}
+	// }}}
+	
+	// {{{ duplicated
+	public static boolean[] duplicated( Object[] array ){
+		int n = array.length ;
+		boolean[] duplicated = new boolean[ array.length ];
+		for( int i=0; i<array.length; i++){
+			duplicated[i] = false ; 
+		}
+		
+		for( int i=0; i<n; i++){
+			if( duplicated[i] ) continue ;
+			Object current = array[i];
+			
+			for( int j=i+1; j<n; j++){
+				Object o_j = array[j] ;
+				if( !duplicated[j] && current.equals( o_j ) ){
+					duplicated[j] = true;
+				}
+			}
+		}
+		
+		return duplicated ;
+	}	
+	// }}}
+	
+	// {{{ anyDuplicated
+	public static int anyDuplicated( Object[] array ){
+		int n = array.length ;
+		
+		for( int i=0; i<n; i++){
+			Object current = array[i];
+			
+			for( int j=i+1; j<n; j++){
+				Object o_j = array[j] ;
+				if( current.equals( o_j ) ){
+					return j ;
+				}
+			}
+		}
+		
+		return -1 ;
+	}	
+	// }}}
+	
+	// {{{ sort
+	/**
+	 * Returns a copy of the array where elements are sorted
+	 *
+	 * @param array array of Objects.  
+	 * @param decreasing if true the sort is in decreasing order
+	 * 
+	 * @throws NotComparableException if the component type of the array does not
+	 * implement the Comparable interface
+	 */
+	public static Object[] sort( Object[] array, boolean decreasing ) throws NotComparableException {
+		Class ct = array.getClass().getComponentType() ;
+		if( Comparable.class.isAssignableFrom( ct ) ){
+			throw new NotComparableException( ct ) ; 
+		}
+		int n = array.length ;
+		Object[] res = copy( array ) ; 
+		Arrays.sort( res ) ;
+		
+		if( !decreasing ){
+			return res ;
+		} else{
+			Object current ;
+			int top = (res.length) / 2 ; 
+			for( int i=0; i<top ; i++ ){
+				current = res[i] ;
+				res[ i ] = res[ n-i-1 ] ;
+				res[ n-i-1 ] = current ; 
+			}
+		}
+		return res ;
+	}
+	// }}}
+	
+	// {{{ rev
+	/**
+	 * Returns a copy of the input array with elements in
+	 * reverse order
+	 * 
+	 * @param original input array
+	 */
+	public static Object[] rev( Object[] original ){
+		int n = original.length ;
+		Object[] copy = (Object[])Array.newInstance( original.getClass().getComponentType() , n ); 
+		for( int i=0; i<n ; i++ ){
+			copy[n-i-1] = original[i] ;
+		}
+		return copy ;
+	}    
+	// }}}
+	    
+	// {{{ copy
+	public static Object[] copy( Object[] original ){
+		int n = original.length ;
+		Object[] copy = (Object[])Array.newInstance( original.getClass().getComponentType() , n ); 
+		for( int i=0; i<n ; i++ ){
+			copy[i] = original[i] ;
+		}
+		return copy ;
+	}
+	// }}}
+	
+	// {{{ getIterableContent
+	public static Object[] getIterableContent( Iterable o){
+		Vector v = new Vector(); 
+		Iterator iterator = o.iterator(); 
+		while( iterator.hasNext() ){
+			v.add( iterator.next() ); 
+		}
+		return v.toArray(); 
+	}
+	// }}}
+	
+	// {{{ rep
+	/**
+	 * Creates a java array by cloning o several times
+	 * 
+	 * @param o object to clone
+	 * @param size number of times to replicate the object
+	 */
+	public static Object[] rep( Object o, int size ) throws Throwable {
+		Object[] res = (Object[])Array.newInstance( o.getClass(), size ) ;
+		if( ! ( o instanceof Cloneable )){
+			return res ;
+		}
+		
+		Method m = getCloneMethod( o.getClass() ) ;
+		boolean access = m.isAccessible() ; 
+		m.setAccessible( true ) ;
+		try{
+			for( int i=0; i<size; i++){
+				Object cloned = o.getClass().cast( m.invoke( o, (Object[])null ) );
+				res[i] = cloned ;
+			}
+		} catch( IllegalAccessException e) {
+			m.setAccessible( access );
+			/* should not happen */
+		} catch( InvocationTargetException e){
+			m.setAccessible( access );
+			throw e.getCause() ; 
+		} 
+		return res ;
+	}
+	
+	private static Method getCloneMethod(Class cl){
+		Method[] methodz ;
+		Method m = null ;
+		while( cl != null ){
+			methodz = cl.getDeclaredMethods( ) ;
+			for( int i=0; i<methodz.length; i++){
+				m = methodz[i];
+				if( "clone".equals( m.getName() ) && m.getParameterTypes().length == 0 ){
+					return m ;
+				}
+			}
+			cl = cl.getSuperclass();        
+		}
+		return null ; /* never happens */
+	}
+	// }}}
+	
+	// {{{ cloneObject
+	public static Object cloneObject( Object o) throws Throwable {
+		Method m = getCloneMethod( o.getClass() ) ;
+		boolean access = m.isAccessible() ; 
+		m.setAccessible( true ) ;
+		
+		Object copy = null ; 
+		
+		try{
+				copy = o.getClass().cast( m.invoke( o, (Object[])null ) );
+		} catch( IllegalAccessException e) {
+			m.setAccessible( access );
+			/* should not happen */
+		} catch( InvocationTargetException e){
+			m.setAccessible( access );
+			throw e.getCause() ; 
+		}
+		return copy ;
+	}
+	// }}}
+	
+	/// boxing and unboxing for Double[] and Integer[]
+        public static final int NA_INTEGER = -2147483648;
+	public static final double NA_REAL = Double.longBitsToDouble(0x7ff00000000007a2L);
+        static final long NA_bits = Double.doubleToRawLongBits(Double.longBitsToDouble(0x7ff00000000007a2L));
+
+	public static double[] unboxDoubles(Double[] o) {
+		if (o == null) return null;
+		int i = 0, n = o.length;
+		double d[] = new double[n];
+		for (i = 0; i < n; i++) d[i] = (o[i] == null) ? NA_REAL : o[i].doubleValue();
+		return d;
+	}
+
+	public static int[] unboxIntegers(Integer[] o) {
+		if (o == null) return null;
+		int i = 0, n = o.length;
+		int d[] = new int[n];
+		for (i = 0; i < n; i++) d[i] = (o[i] == null) ? NA_INTEGER : o[i].intValue();
+		return d;
+	}
+
+	public static int[] unboxBooleans(Boolean[] o) {
+		if (o == null) return null;
+		int i = 0, n = o.length;
+		int d[] = new int[n];
+		for (i = 0; i < n; i++) d[i] = (o[i] == null) ? NA_INTEGER : (o[i].booleanValue() ? 1 : 0);
+		return d;
+	}
+
+        public static boolean isNA(double value) {
+                /* on OS X i386 the MSB of the fraction is set even though R doesn't set it.
+                   Although this is technically a good idea (to make it a QNaN) it's not what R does and thus makes the comparison tricky */
+                return (Double.doubleToRawLongBits(value) & 0xfff7ffffffffffffL) == (NA_bits & 0xfff7ffffffffffffL);
+        }
+
+	public static Double[] boxDoubles(double[] d) {
+		if (d == null) return null;
+		int i = 0, n = d.length;
+		Double o[] = new Double[i];
+		for (i = 0; i < n; i++) if (!isNA(d[i])) o[i] = new Double(d[i]);
+		return o;
+	}
+
+	public static Integer[] boxIntegers(int[] d) {
+		if (d == null) return null;
+		int i = 0, n = d.length;
+		Integer o[] = new Integer[i];
+		for (i = 0; i < n; i++) if (d[i] != NA_INTEGER) o[i] = new Integer(d[i]);
+		return o;
+	}
+
+	public static Boolean[] boxBooleans(int[] d) {
+		if (d == null) return null;
+		int i = 0, n = d.length;
+		Boolean o[] = new Boolean[i];
+		for (i = 0; i < n; i++) if (d[i] != NA_INTEGER) o[i] = new Boolean((d[i] == 0) ? false : true);
+		return o;
+	}
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaClassLoader.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaClassLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..9823e602e7c6308445c7bbb3ea7e0795cfc1ad06
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaClassLoader.java
@@ -0,0 +1,675 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+// :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1:
+
+// {{{ imports
+import java.io.*;
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.zip.*;
+// }}}
+
+/**
+ * Class loader used internally by rJava
+ * 
+ * The class manages the class paths and the native libraries (jri, ...)
+ */
+public class RJavaClassLoader extends URLClassLoader {
+	
+	// {{{ fields 
+	/** 
+	 * path of RJava
+	 */
+	String rJavaPath ;
+	
+	/**
+	 * lib sub directory of rJava
+	 */
+	String rJavaLibPath;
+	
+	/**
+	 * map of libraries
+	 */
+	HashMap/*<String,UnixFile>*/ libMap;
+	
+	/**
+	 * The class path vector 
+	 */ 
+	Vector/*<UnixFile>*/ classPath;
+
+	/**
+	 * singleton
+	 */
+	public static RJavaClassLoader primaryLoader = null;
+
+	/**
+	 * Print debug messages if is set to <code>true</code>
+	 */
+	public static boolean verbose = false;
+
+	/**
+	 * Should the system class loader be used to resolve classes 
+	 * as well as this class loader
+	 */
+	public boolean useSystem = true;
+	// }}}
+
+	// {{{ UnixFile class
+	/**
+	 * Light extension of File that handles file separators and updates
+	 */
+	class UnixFile extends File {
+		
+		/**
+		 * cached "last time modified" stamp
+		 */ 
+		long lastModStamp;
+		
+		/** 
+		 * Constructor. Modifies the path so that 
+		 * the proper path separator is used (most useful on windows)
+		 */
+		public UnixFile(String fn) {
+			super( u2w(fn) ) ;
+			lastModStamp=0;
+		}
+		
+		/**
+		 * @return whether the file modified since last time the update method was called
+		 */
+		public boolean hasChanged() {
+			long curMod = lastModified();
+			return (curMod != lastModStamp);
+		}
+		
+		/**
+		 * Cache the result of the lastModified stamp
+		 */
+		public void update() {
+			lastModStamp = lastModified();
+		}
+	}
+	// }}}
+	
+	// {{{ UnixJarFile
+	/**
+	 * Specialization of UnixFile that deals with jar files
+	 */
+	class UnixJarFile extends UnixFile {
+		
+		/**
+		 * The cached jar file
+		 */
+		private ZipFile zfile ;
+		
+		/**
+		 * common prefix for all URLs within this jar file
+		 */
+		private String urlPrefix ;
+		
+		public UnixJarFile( String filename ){
+			super( filename );
+		}
+		
+		/* @Override */
+		public void update(){
+			try {
+				if (zfile != null){
+					zfile.close();
+				}
+				zfile = new ZipFile( this ) ;
+			} catch (Exception tryCloseX) {}
+
+			/* time stamp */
+			super.update( ) ; 
+		}
+		
+		/**
+		 * Get an input stream for a resource contained in the jar file
+		 * 
+		 * @param name file name of the resource within the jar file
+		 * @return an input stream representing the resouce if it exists or null
+		 */ 
+		public InputStream getResourceAsStream( String name ){
+			
+			if (zfile==null || hasChanged()) {
+				update(); 
+			}
+			try {
+				if (zfile == null) return null;
+				ZipEntry e = zfile.getEntry(name);
+				if (e != null)
+					return zfile.getInputStream(e);
+			} catch(Exception e) {
+				if (verbose) System.err.println("RJavaClassLoader$UnixJarFile: exception: "+e.getMessage());
+			}
+			return null;
+		}
+
+				
+		public URL getResource(String name ){
+			if( zfile == null  || zfile.getEntry( name ) == null ){
+				return null ;
+			}
+			
+			URL u = null ; 
+			if( urlPrefix == null ){
+				try{
+					urlPrefix = "jar:" + toURL().toString() + "!" ;
+				} catch( java.net.MalformedURLException ex){
+				} catch( java.io.IOException ex){
+				}
+			}
+			
+			try{
+				u = new URL( urlPrefix + name ) ;
+			} catch( java.net.MalformedURLException ex ){
+				/* not to worry */
+			}
+			return u ;
+		}
+		
+	}
+	// }}}
+	
+	// {{{ UnixDirectory class
+	/**
+	 * Specialization of UnixFile representing a directory
+	 */ 
+	/* it is not really a specialization but makes possible to dispatch on instanceof*/
+	class UnixDirectory extends UnixFile {
+		public UnixDirectory( String dirname ){
+			super( dirname ) ;
+		}
+	}
+	// }}}	
+	
+	
+	// {{{ getPrimaryLoader
+	/**
+	 * Returns the singleton instance of RJavaClassLoader
+	 */ 
+	public static RJavaClassLoader getPrimaryLoader() {
+		return primaryLoader;
+	}
+	// }}}
+
+	// {{{ constructor
+	/**
+	 * Constructor. The first time an RJavaClassLoader is created, it is
+	 * cached as the primary loader. 
+	 *
+	 * @param path path of the rJava package
+	 * @param libpath lib sub directory of the rJava package
+	 */
+	public RJavaClassLoader(String path, String libpath) {
+		super(new URL[] {});
+		// respect rJava.debug level
+		String rjd = System.getProperty("rJava.debug");
+		if (rjd != null && rjd.length() > 0 && !rjd.equals("0")) verbose = true;
+		if (verbose) System.out.println("RJavaClassLoader(\""+path+"\",\""+libpath+"\")");
+		if (primaryLoader==null) {
+			primaryLoader = this;
+			if (verbose) System.out.println(" - primary loader");
+		} else {
+			if (verbose) System.out.println(" - NOT primrary (this="+this+", primary="+primaryLoader+")");
+		}
+		libMap = new HashMap/*<String,UnixFile>*/();
+		
+		classPath = new Vector/*<UnixFile>*/();
+		classPath.add(new UnixDirectory(path+"/java"));
+		
+		rJavaPath = path;
+		rJavaLibPath = libpath;
+		
+		/* load the rJava library */
+		UnixFile so = new UnixFile(rJavaLibPath+"/rJava.so");
+		if (!so.exists())
+			so = new UnixFile(rJavaLibPath+"/rJava.dll");
+		if (so.exists())
+			libMap.put("rJava", so);
+
+		/* load the jri library */
+		UnixFile jri = new UnixFile(path+"/jri/libjri.so");
+		String rarch = System.getProperty("r.arch");
+		if (rarch != null && rarch.length()>0) {
+			UnixFile af = new UnixFile(path+"/jri"+rarch+"/libjri.so");
+			if (af.exists())
+			    jri = af;
+			else {
+			    af = new UnixFile(path+"/jri"+rarch+"/jri.dll");
+			    if (af.exists())
+				jri = af;
+			}			
+		}
+		if (!jri.exists())
+			jri = new UnixFile(path+"/jri/libjri.jnilib");
+		if (!jri.exists())
+			jri = new UnixFile(path+"/jri/jri.dll");
+		if (jri.exists()) {
+			libMap.put("jri", jri);
+			if (verbose) System.out.println(" - registered JRI: "+jri);
+		}
+
+		/* if we are the primary loader, make us the context loader so
+		   projects that rely on the context loader pick us */
+		if (primaryLoader == this)
+			Thread.currentThread().setContextClassLoader(this);
+
+		if (verbose) {
+		    System.out.println("RJavaClassLoader initialized.\n\nRegistered libraries:");
+		    for(Iterator entries = libMap.keySet().iterator(); entries.hasNext(); ) {
+			Object key = entries.next(); System.out.println("  " + key + ": '" + libMap.get(key) + "'");
+		    }
+		    System.out.println("\nRegistered class paths:");
+		    for (Enumeration e = classPath.elements() ; e.hasMoreElements() ;)
+			System.out.println("  '"+e.nextElement()+"'");
+		    System.out.println("\n-- end of class loader report --");
+		}
+	}
+	// }}}
+
+	// {{{ classNameToFile
+	/**
+	 * convert . to /
+	 */ 
+	String classNameToFile(String cls) {
+		return cls.replace('.','/');
+	}
+	// }}}
+
+	// {{{ findClass
+	protected Class findClass(String name) throws ClassNotFoundException {
+		Class cl = null;
+		if (verbose) System.out.println(""+this+".findClass("+name+")");
+		if ("RJavaClassLoader".equals(name)) return getClass();
+		
+		// {{{ use the usual method of URLClassLoader
+		if (useSystem) {
+			try {
+				cl = super.findClass(name);
+				if (cl != null) {
+					if (verbose) System.out.println("RJavaClassLoader: found class "+name+" using URL loader");
+					return cl;
+				}
+			} catch (Exception fnf) {
+			    if (verbose) System.out.println(" - URL loader did not find it: " + fnf);
+			}	    
+		}
+		if (verbose) System.out.println("RJavaClassLoader.findClass(\""+name+"\")");
+		// }}}
+
+		// {{{ iterate through the elements of the class path
+		InputStream ins = null;
+		Exception defineException = null;
+		Enumeration/*<UnixFile>*/ e = classPath.elements() ;
+		while( e.hasMoreElements() ){
+			UnixFile cp = (UnixFile) e.nextElement();
+
+			if (verbose) System.out.println(" - trying class path \""+cp+"\"");
+			try {
+				ins = null;
+				/* a file - assume it is a jar file */
+				if (cp instanceof UnixJarFile){
+					ins = ((UnixJarFile)cp).getResourceAsStream( classNameToFile(name) + ".class" ) ;
+					if (verbose) System.out.println("   JAR file, can get '" + classNameToFile(name) + "'? " + ((ins == null) ? "NO" : "YES"));
+				} else if ( cp instanceof UnixDirectory ){
+					UnixFile class_f = new UnixFile(cp.getPath()+"/"+classNameToFile(name)+".class");
+					if (class_f.isFile() ) {
+						ins = new FileInputStream(class_f);
+					}
+					if (verbose) System.out.println("   Directory, can get '" + class_f + "'? " + ((ins == null) ? "NO" : "YES"));
+				}
+				
+				/* some comments on the following :
+					
+				   we could call ZipEntry.getSize in case of a jar file to 
+				   find out the size of the byte[] directly
+				   
+				   also ByteBuffer seems more efficient, but the ByteBuffer class
+				   is java >= 1.4 and the defineClass method that uses the class
+				   is java >= 1.5
+				*/
+				
+				if (ins != null) {
+					int al = 128*1024;
+					byte fc[] = new byte[al];
+					int n = ins.read(fc);
+					int rp = n;
+					if( verbose ) System.out.println("  loading class file, initial n = "+n);
+					while (n > 0) {
+						if (rp == al) {
+							int nexa = al*2;
+							if (nexa<512*1024) nexa=512*1024;
+							byte la[] = new byte[nexa];
+							System.arraycopy(fc, 0, la, 0, al);
+							fc = la;
+							al = nexa;
+						}
+						n = ins.read(fc, rp, fc.length-rp);
+						if( verbose ) System.out.println("  next n = "+n+" (rp="+rp+", al="+al+")");
+						if (n>0) rp += n;
+					}
+					ins.close();
+					n = rp;
+					if (verbose) System.out.println("RJavaClassLoader: loaded class "+name+", "+n+" bytes");
+					try {
+					    cl = defineClass(name, fc, 0, n);
+					} catch (Exception dce) {
+					    // we want to save this one so we can pass it on
+					    defineException = dce;
+					    break;
+					}
+					if (verbose) System.out.println("  defineClass('" + name +"') returned " + cl);
+					// System.out.println(" - class = "+cl);
+					return cl;
+				}
+			} catch (Exception ex) {
+				// System.out.println(" * won't work: "+ex.getMessage());
+			}
+		}
+		// }}}
+		
+		if (defineException != null) // we bailed out on class interpretation, re-throw it
+		    throw (new ClassNotFoundException("Class not found - candidate class binary found but could not be loaded", defineException));
+
+		// giving up
+		if( verbose ) System.out.println("    >> ClassNotFoundException ");
+		if (cl == null) {
+			throw (new ClassNotFoundException());
+		}
+		return cl;
+	}
+	// }}}
+
+	// {{{ findResource 
+	public URL findResource(String name) {
+		if (verbose) System.out.println("RJavaClassLoader: findResource('"+name+"')");
+		
+		// {{{ use the standard way
+		if (useSystem) {
+			try {
+				URL u = super.findResource(name);
+				if (u != null) {
+					if (verbose) System.out.println("RJavaClassLoader: found resource in "+u+" using URL loader.");
+					return u;
+				}
+			} catch (Exception fre) {
+			}
+		}
+		// }}}
+		
+		// {{{ iterate through the classpath
+		if (verbose) System.out.println(" - resource not found with URL loader, trying alternative");
+		Enumeration/*<UnixFile>*/ e = classPath.elements() ;
+		while( e.hasMoreElements()) {
+			UnixFile cp = (UnixFile) e.nextElement();
+
+			try {
+				/* is a file - assume it is a jar file */
+				if (cp instanceof UnixJarFile ) {
+					URL u = ( (UnixJarFile)cp ).getResource( name ) ;
+					if (u != null) {
+						if (verbose) System.out.println(" - found in a JAR file, URL "+u);
+						return u;
+					}
+				} else if(cp instanceof UnixDirectory ) {
+					UnixFile res_f = new UnixFile(cp.getPath()+"/"+name);
+					if (res_f.isFile()) {
+						if (verbose) System.out.println(" - find as a file: "+res_f);
+						return res_f.toURL();
+					}
+				}
+			} catch (Exception iox) {
+			}
+		}
+		// }}}
+		return null;
+	}
+	// }}}
+
+	// {{{ addRLibrary
+	/** add a library to path mapping for a native library */
+	public void addRLibrary(String name, String path) {
+		libMap.put(name, new UnixFile(path));
+	}
+	// }}}
+
+	// {{{ addClassPath
+	/** 
+	 * adds an entry to the class path
+	 */ 
+	public void addClassPath(String cp) {
+		UnixFile f = new UnixFile(cp);
+		
+		// use the URLClassLoader
+		if (useSystem) {
+			try {
+				addURL(f.toURL());
+				if (verbose) System.out.println("RJavaClassLoader: added '" + cp + "' to the URL class path loader");
+				//return; // we need to add it anyway so it appears in .jclassPath()
+			} catch (Exception ufe) {
+			}
+		}
+		
+		UnixFile g = null ;
+		if( f.isFile() && (f.getName().endsWith(".jar") || f.getName().endsWith(".JAR"))) {
+			g = new UnixJarFile(cp) ;
+			if (verbose) System.out.println("RJavaClassLoader: adding Java archive file '"+cp+"' to the internal class path");
+		} else if( f.isDirectory() ){
+			g = new UnixDirectory(cp) ;
+			if (verbose) System.out.println("RJavaClassLoader: adding class directory '"+cp+"' to the internal class path");
+		} else if (verbose)
+		    System.err.println(f.exists() ?
+				       ("WARNING: the path '"+cp+"' is neither a directory nor a .jar file, it will NOT be added to the internal class path!") :
+				       ("WARNING: the path '"+cp+"' does NOT exist, it will NOT be added to the internal class path!"));
+		
+		if (g != null && !classPath.contains(g)) {
+			// this is the real meat - add it to our internal list
+			classPath.add(g);
+			// this is just cosmetics - it doesn't really have any meaning
+			System.setProperty("java.class.path",
+					System.getProperty("java.class.path")+File.pathSeparator+g.getPath());
+		}
+	}
+	
+	/** 
+	 * adds several entries to the class path
+	 */
+	public void addClassPath(String[] cp) {
+		int i = 0;
+		while (i < cp.length) addClassPath(cp[i++]);
+	}
+	// }}}
+
+	// {{{ getClassPath
+	/**
+	 * @return the array of class paths used by this class loader
+	 */
+	public String[] getClassPath() {
+		int j = classPath.size();
+		String[] s = new String[j];
+		int i = 0;
+		while (i < j) {
+			s[i] = ((UnixFile) classPath.elementAt(i)).getPath();
+			i++;
+		}
+		return s;
+	}
+	// }}}
+	
+	// {{{ findLibrary
+	protected String findLibrary(String name) {
+		if (verbose) System.out.println("RJavaClassLoader.findLibrary(\""+name+"\")");
+		//if (name.equals("rJava"))
+		//    return rJavaLibPath+"/"+name+".so";
+
+		UnixFile u = (UnixFile) libMap.get(name);
+		String s = null;
+		if (u!=null && u.exists()) s=u.getPath();
+		if (verbose) System.out.println(" - mapping to "+((s==null)?"<none>":s));
+
+		return s;
+	}
+	// }}}
+
+	// {{{ bootClass
+	/**
+	 * Boots the specified method of the specified class
+	 * 
+	 * @param cName class to boot
+	 * @param mName method to boot (typically main). The method must take a String[] as parameter
+	 * @param args arguments to pass to the method
+	 */
+	public void bootClass(String cName, String mName, String[] args) throws java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException, java.lang.NoSuchMethodException, java.lang.ClassNotFoundException {
+		Class c = findClass(cName);
+		resolveClass(c);
+		java.lang.reflect.Method m = c.getMethod(mName, new Class[] { String[].class });
+		m.invoke(null, new Object[] { args });
+	}
+	// }}}
+
+	// {{{ setDebug
+	/**
+	 * Set the debug level. At the moment, there is only verbose (level &gt; 0)
+	 * or quiet
+	 *
+	 * @param level debug level. verbose (&gt;0), quiet otherwise
+	 */
+	public static void setDebug(int level) {
+		verbose=(level>0);
+	}
+	// }}}
+
+	// {{{ u2w
+	/** 
+	 * Utility to convert paths for windows. Converts / to the path separator in use
+	 * 
+	 * @param fn file name
+	 */
+	public static String u2w(String fn) {
+		return (File.separatorChar != '/') ? fn.replace('/', File.separatorChar) : fn ;
+	}
+	// }}}
+
+	// {{{ main
+	/**
+	 * main method
+	 * 
+	 * This uses the system properties: 
+	 * <ul>
+	 * <li><code>rjava.path</code> : path of the rJava package</li>
+	 * <li><code>rjava.lib</code>  : lib sub directory of the rJava package</li>
+	 * <li><code>main.class</code> : main class to "boot", assumes Main if not specified</li>
+	 * <li><code>rjava.class.path</code> : set of paths to populate the initiate the class path</li>
+	 * </ul>
+	 *
+	 * <p>and boots the "main" method of the specified <code>main.class</code>, 
+	 * passing the args down to the booted class</p>
+	 *
+	 * <p>This makes sure R and rJava are known by the class loader</p>
+	 */
+	public static void main(String[] args) {
+		String rJavaPath = System.getProperty("rjava.path");
+		if (rJavaPath  == null) {
+			System.err.println("ERROR: rjava.path is not set");
+			System.exit(2);
+		}
+		String rJavaLib = System.getProperty("rjava.lib");
+		if (rJavaLib == null) { // it is not really used so far, just for rJava.so, so we can guess
+			rJavaLib = rJavaPath + File.separator + "libs";
+		}
+		RJavaClassLoader cl = new RJavaClassLoader(u2w(rJavaPath), u2w(rJavaLib));
+		String mainClass = System.getProperty("main.class");
+		if (mainClass == null || mainClass.length()<1) {
+			System.err.println("WARNING: main.class not specified, assuming 'Main'");
+			mainClass = "Main";
+		}
+		String classPath = System.getProperty("rjava.class.path");
+		if (classPath != null) {
+			StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
+			while (st.hasMoreTokens()) {
+				String dirname = u2w(st.nextToken());
+				cl.addClassPath(dirname);
+			}
+		}
+		try {
+			cl.bootClass(mainClass, "main", args);
+		} catch (Exception ex) { 
+			System.err.println("ERROR: while running main method: "+ex);
+			ex.printStackTrace();
+		}
+	}
+	// }}}
+
+	//----- tools -----
+	
+	// {{{ RJavaObjectInputStream class
+	class RJavaObjectInputStream extends ObjectInputStream {
+		public RJavaObjectInputStream(InputStream in) throws IOException {
+			super(in);
+		}
+		protected Class resolveClass(ObjectStreamClass desc) throws ClassNotFoundException {
+			return Class.forName(desc.getName(), false, RJavaClassLoader.getPrimaryLoader());
+		}
+	}
+	// }}}
+
+	// {{{ toByte
+	/** 
+	 * Serialize an object to a byte array. (code by CB)
+	 *
+	 * @param object object to serialize
+	 * @return byte array that represents the object
+	 * @throws Exception 
+	 */
+	public static byte[] toByte(Object object) throws Exception {
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		ObjectOutputStream   oos = new ObjectOutputStream((OutputStream) os);
+		oos.writeObject(object);
+		oos.close();
+		return os.toByteArray();
+	}
+	// }}}
+
+	// {{{ toObject
+	/** 
+	 * Deserialize an object from a byte array. (code by CB)
+	 *
+	 * @param byteArray
+	 * @return the object that is represented by the byte array
+	 * @throws Exception 
+	 */
+	public Object toObject(byte[] byteArray) throws Exception {
+		InputStream        is = new ByteArrayInputStream(byteArray);
+		RJavaObjectInputStream ois = new RJavaObjectInputStream(is);
+		Object o = (Object) ois.readObject();
+		ois.close();
+		return o;
+	}
+	// }}}
+
+	// {{{ toObjectPL
+	/**
+	 * converts the byte array into an Object using the primary RJavaClassLoader
+	 */
+	public static Object toObjectPL(byte[] byteArray) throws Exception{
+		return RJavaClassLoader.getPrimaryLoader().toObject(byteArray);
+	}
+	// }}}
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaComparator.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaComparator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a220269cdbe713b49550df26576e5c960c04d3af
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaComparator.java
@@ -0,0 +1,62 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+import java.lang.Comparable ; 
+
+/**
+ * Utility class to compare two objects in the sense
+ * of the java.lang.Comparable interface
+ *
+ */
+public class RJavaComparator {
+	           
+	/**
+	 * compares a and b in the sense of the java.lang.Comparable if possible
+	 *
+	 * <p>instances of the Number interface are treated specially, in order to 
+	 * allow comparing Numbers of different classes, for example it is allowed 
+	 * to compare a Double with an Integer. if the Numbers have the same class,
+	 * they are compared normally, otherwise they are first converted to Doubles
+	 * and then compared</p>
+	 * 
+	 * @param a an object
+	 * @param b another object 
+	 * 
+	 * @return the result of <code>a.compareTo(b)</code> if this makes sense
+	 * @throws NotComparableException if the two objects are not comparable
+	 */
+	public static int compare( Object a, Object b ) throws NotComparableException{
+		int res ; 
+		if( a.equals( b ) ) return 0 ;
+		
+		// treat Number s separately
+		if( a instanceof Number && b instanceof Number && !( a.getClass() == b.getClass() ) ){
+			Double _a = new Double( ((Number)a).doubleValue() );
+			Double _b = new Double( ((Number)b).doubleValue() );
+			return _a.compareTo( _b ); 
+		}
+		
+		if( ! ( a instanceof Comparable ) ) throw new NotComparableException( a ); 
+		if( ! ( b instanceof Comparable ) ) throw new NotComparableException( b ); 
+		
+		try{
+			res = ( (Comparable)a ).compareTo( b ) ; 
+		} catch( ClassCastException e){
+			try{
+				res = - ((Comparable)b).compareTo( a ) ;
+			} catch( ClassCastException f){
+				throw new NotComparableException( a, b ); 
+			}
+		}
+		return res ;
+	}
+	
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaImport.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaImport.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b5f664808b26bb87accc5af55b8eac418a1f917
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaImport.java
@@ -0,0 +1,182 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+import java.util.regex.Pattern ;
+import java.util.regex.Matcher ;
+
+import java.util.Vector; 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Collection;
+import java.util.Set ;
+import java.util.Iterator ;
+
+import java.io.Serializable; 
+
+/**
+ * Utilities to manage java packages and how they are "imported" to R
+ * databases. This is the back door of the <code>javaImport</code>
+ * system in the R side
+ *
+ * @author Romain Francois &lt;francoisromain@free.fr&gt;
+ */
+public class RJavaImport implements Serializable {
+
+	/**
+	 * Debug flag. Prints some messages if it is set to TRUE
+	 */
+	public static boolean DEBUG = false ; 
+	
+	/** 
+	 * list of imported packages
+	 */
+	/* TODO: vector is not good enough, we need to control the order
+	         in which the packages appear */
+	private Vector/*<String>*/ importedPackages ;
+	
+	/**
+	 * maps a simple name to a fully qualified name
+	 */
+	/* String -> java.lang.String */
+  /* should we cache the Class instead ? */
+	private Map/*<String,String>*/ cache ;
+	
+	/**
+	 * associated class loader
+	 */
+	public ClassLoader loader ;
+	
+	/**
+	 * Constructor. Initializes the imported package vector and the cache
+	 */ 
+	public RJavaImport( ClassLoader loader ){
+	    this.loader = loader ;
+		importedPackages = new Vector/*<String>*/(); 
+		cache = new HashMap/*<String,String>*/() ;
+	}
+	
+	/**
+	 * Look for the class in the set of packages
+	 *
+	 * @param clazz the simple class name
+	 * 
+	 * @return an instance of Class representing the actual class
+	 */
+	public Class lookup( String clazz){
+		Class res = lookup_(clazz) ;
+		if( DEBUG ) System.out.println( "  [J] lookup( '" + clazz + "' ) = " + (res == null ? " " : ("'" + res.getName() + "'" ) ) ) ;
+		return res ;
+	}
+
+	private Class lookup_( String clazz ){
+		Class res = null ;
+		
+		if( cache.containsKey( clazz ) ){
+			try{
+				String fullname = (String)cache.get( clazz ) ;
+				Class cl = Class.forName( fullname ) ; 
+				return cl ;
+			} catch( Exception e ){
+				/* does not happen */
+			}
+		}
+		
+		/* first try to see if the class does not exist verbatim */
+		try{
+			res = Class.forName( clazz ) ;
+		} catch( Exception e){}
+		if( res != null ) {
+			cache.put( clazz, clazz ) ;
+			return res;
+		}
+		
+		int npacks = importedPackages.size() ;
+		if( DEBUG ) System.out.println( "    [J] " + npacks + " packages" ) ;
+		if( npacks > 0 ){
+			for( int i=0; i<npacks; i++){
+				try{
+				    String p = (String)importedPackages.get(i); 
+				    String candidate = p + "." + clazz ;
+				    if( DEBUG ) System.out.println( "    [J] trying class : " + candidate ) ;
+					res = Class.forName( candidate ) ;
+				} catch( Exception e){
+				    if( DEBUG ) System.out.println( "   [JE] " + e.getMessage() );
+				}
+				if( res != null ){
+					cache.put( clazz, res.getName() ) ;
+					return res ; 
+				}
+			}
+		}
+		return null ;
+	}
+	
+	/**
+	 * @return true if the class is known
+	 */
+	public boolean exists( String clazz){
+		boolean res = exists_(clazz) ;
+		if( DEBUG ) System.out.println( "  [J] exists( '" + clazz + "' ) = " + res ) ;
+		return res ;
+	}
+
+	public boolean exists_( String clazz ){
+		if( cache.containsKey( clazz ) ) return true ;
+		
+		return ( lookup_( clazz ) != null );
+	}
+	
+	/**
+	 * Adds a package to the list of "imported" packages
+	 *
+	 * @param packageName package path name
+	 */
+  public void importPackage( String packageName ){
+  	importedPackages.add( packageName ) ; 
+  }
+	
+  /**
+   * Adds a set of packages
+   *
+   * @param packages package path names
+   */
+  public void importPackage( String[] packages ){
+  	for( int i=0; i<packages.length; i++){
+  		importPackage( packages[i] ) ;
+  	}
+  }
+  
+  /**
+   * @return the simple names of the classes currently known
+   * by this importer
+   */
+  public String[] getKnownClasses(){
+  	Set/*<String>*/ set = cache.keySet() ; 
+  	int size = set.size() ;
+  	String[] res = new String[size];
+  	set.toArray( res );
+  	if( DEBUG ) System.out.println( "  [J] getKnownClasses().length = "  + res.length ) ;
+  	return res ;
+  }
+  
+  public static Class lookup( String clazz , Set importers ){
+  	Class res  ;
+  	Iterator iterator = importers.iterator() ;
+  	while( iterator.hasNext()){
+  		RJavaImport importer = (RJavaImport)iterator.next() ;
+  		res = importer.lookup( clazz ) ;
+  		if( res != null ) return res ;
+  	}
+  	return null ;
+  }
+  
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaTools.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7906f94bf24832931efa3a81e6adcc5dbf14be3
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RJavaTools.java
@@ -0,0 +1,748 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2009-2010, Simon Urbanek and Romain Francois
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+// RJavaTools.java: rJava - low level R to java interface
+//
+// Copyright (C) 2009 - 2010	Simon Urbanek and Romain Francois
+//
+// This file is part of rJava.
+//
+// rJava is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// rJava is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with rJava.  If not, see <http://www.gnu.org/licenses/>.
+
+import java.lang.reflect.Method ;
+import java.lang.reflect.Field ;
+import java.lang.reflect.Constructor ;
+import java.lang.reflect.InvocationTargetException ;
+import java.lang.reflect.Modifier ;
+import java.lang.reflect.Member ;
+
+import java.util.Vector ;
+
+
+/** 
+ * Tools used internally by rJava.
+ * 
+ * The method lookup code is heavily based on ReflectionTools 
+ * by Romain Francois &lt;francoisromain@free.fr&gt; licensed under GPL v2 or higher.
+ */
+public class RJavaTools {
+	
+	/**
+	 * Returns an inner class of the class with the given simple name
+	 * 
+	 * @param cl class
+	 * @param name simple name of the inner class
+	 * @param staticRequired boolean, if <code>true</code> the inner class is required to be static
+	 */
+	public static Class getClass(Class cl, String name, boolean staticRequired){
+		Class[] clazzes = cl.getClasses(); 
+		for( int i=0; i<clazzes.length; i++){
+			if( getSimpleName( clazzes[i].getName() ).equals( name ) && ( !staticRequired || isStatic(clazzes[i]) ) ){
+				return clazzes[i] ;
+			}
+		}
+		return null; 
+	}
+	
+	
+	/**
+	 * Returns the static inner classes of the class
+	 * 
+	 * @param cl class
+	 * @return an array of classes or null if cl does not have static inner classes
+	 */
+	public static Class[] getStaticClasses(Class cl){
+		 Class[] clazzes = cl.getClasses(); 
+		 if( clazzes == null ) return null; 
+		 
+		 Vector vec = new Vector() ;
+		 int n = clazzes.length; 
+		 for( int i=0; i<n; i++){
+			Class clazz = clazzes[i] ;
+			if( isStatic( clazz ) ){
+				vec.add( clazz ) ; 
+			}
+		}
+		if( vec.size() == 0 ){
+			return null ;
+		}
+		Class[] out = new Class[ vec.size() ] ;
+		vec.toArray( out ) ; 
+		return out ; 
+	}
+	
+	/**
+	 * Indicates if a class is static
+	 * 
+	 * @param clazz class
+	 * @return true if the class is static
+	 */
+	public static boolean isStatic( Class clazz ){
+		return (clazz.getModifiers() & Modifier.STATIC) != 0  ;
+	}
+	
+	/**
+	 * Returns the static fields of the class
+	 *
+	 * @param cl class 
+	 * @return an array of static fields
+	 */
+	public static Field[] getStaticFields( Class cl ){
+		Field[] members = cl.getFields() ;
+		if( members.length == 0 ){
+			return null;  
+		}
+		Vector vec = new Vector() ;
+		int n = members.length ; 
+		for( int i=0; i<n; i++){
+			Field memb = members[i] ;
+			if( isStatic( memb ) ){
+				vec.add( memb ) ; 
+			}
+		}
+		if( vec.size() == 0 ){
+			return null ;
+		}
+		Field[] out = new Field[ vec.size() ] ;
+		vec.toArray( out ) ; 
+		return out ; 
+	}
+	
+	/**
+	 * Returns the static methods of the class
+	 *
+	 * @param cl class 
+	 * @return an array of static fields
+	 */
+	public static Method[] getStaticMethods( Class cl ){
+		Method[] members = cl.getMethods() ;
+		Vector vec = new Vector() ;
+		if( members.length == 0 ){
+			return null;  
+		}
+		int n = members.length ; 
+		for( int i=0; i<n; i++){
+			Method memb = members[i] ;
+			if( isStatic( memb ) ){
+				vec.add( memb ) ; 
+			}
+		}
+		if( vec.size() == 0 ){
+			return null ;
+		}
+		Method[] out = new Method[ vec.size() ] ;
+		vec.toArray( out ) ; 
+		return out ; 
+	}
+	
+	
+	/**
+	 * Returns the names of the fields of a given class
+	 *
+	 * @param cl class 
+	 * @param staticRequired if true only static fields are returned
+	 * @return the public (and maybe only static) names of the fields. 
+	 */
+	public static String[] getFieldNames( Class cl, boolean staticRequired ){
+		return getMemberNames( cl.getFields(), staticRequired ) ; 
+	}
+	
+	/**
+	 * Returns the completion names of the methods of a given class. 
+	 * See the getMethodCompletionName method below
+	 *
+	 * @param cl class 
+	 * @param staticRequired if true only static methods are returned
+	 * @return the public (and maybe only static) names of the methods. 
+	 */
+	public static String[] getMethodNames( Class cl, boolean staticRequired ){
+		return getMemberNames( cl.getMethods(), staticRequired ) ;
+	}
+	
+	private static String[] getMemberNames(Member[] members, boolean staticRequired){
+		String[] result = null ;
+		int nm = members.length ;
+		if( nm == 0 ){
+			return new String[0] ;
+		}
+		if( staticRequired ){
+			Vector names = new Vector();
+			for( int i=0; i<nm; i++ ){
+				Member member = members[i] ; 
+				if( isStatic( member ) ){
+					names.add( getCompletionName(member) ) ; 
+				}
+			}
+			if( names.size() == 0 ){
+				return new String[0] ;
+			}
+			result = new String[ names.size() ] ;
+		  names.toArray( result ) ; 
+		} else{ 
+			/* don't need the vector */
+			result = new String[nm] ;
+			for( int i=0; i<nm; i++ ){
+				result[i] = getCompletionName( members[i] ) ;
+			}
+		}
+		return  result; 
+	}
+	
+	/**
+	 * Completion name of a member. 
+	 * 
+	 * <p>For fields, it just returns the name of the fields
+	 *
+	 * <p>For methods, this returns the name of the method
+	 * plus a suffix that depends on the number of arguments of the method.
+	 * 
+	 * <p>The string "()" is added 
+	 * if the method has no arguments, and the string "(" is added
+	 * if the method has one or more arguments.
+	 */
+	public static String getCompletionName(Member m){
+		if( m instanceof Field ) return m.getName();
+		if( m instanceof Method ){
+			String suffix = ( ((Method)m).getParameterTypes().length == 0 ) ? ")" : "" ;
+			return m.getName() + "(" + suffix ;
+		}
+		return "" ;
+	}
+	 
+	/**
+	 * Indicates if a member of a Class (field, method ) is static
+	 * 
+	 * @param member class member
+	 * @return true if the member is static
+	 */
+	public static boolean isStatic( Member member ){
+		return (member.getModifiers() & Modifier.STATIC) != 0  ;
+	}
+	
+	/**
+	 * Checks if the class of the object has the given field. The 
+	 * getFields method of Class is used so only public fields are 
+	 * checked
+	 *
+	 * @param o object
+	 * @param name name of the field
+	 *
+	 * @return <code>true</code> if the class of <code>o</code> has the field <code>name</code>
+	 */
+	public static boolean hasField(Object o, String name) {
+		return classHasField(o.getClass(), name, false);
+	}
+	
+	/**
+	 * Checks if the class of the object has the given inner class. The 
+	 * getClasses method of Class is used so only public classes are 
+	 * checked
+	 *
+	 * @param o object
+	 * @param name (simple) name of the inner class
+	 *
+	 * @return <code>true</code> if the class of <code>o</code> has the class <code>name</code>
+	 */
+	public static boolean hasClass(Object o, String name) {
+		return classHasClass(o.getClass(), name, false);
+	}
+	
+	
+	/**
+	 * Checks if the specified class has the given field. The 
+	 * getFields method of Class is used so only public fields are 
+	 * checked
+	 *
+	 * @param cl class object
+	 * @param name name of the field
+	 * @param staticRequired if <code>true</code> then the field is required to be static
+	 *
+	 * @return <code>true</code> if the class <code>cl</code> has the field <code>name</code>
+	 */
+	public static boolean classHasField(Class cl, String name, boolean staticRequired) {
+		Field[] fields = cl.getFields();
+		for (int i = 0; i < fields.length; i++)
+			if(name.equals(fields[i].getName()) && (!staticRequired || ((fields[i].getModifiers() & Modifier.STATIC) != 0)))
+				return true; 
+		return false;
+	}
+	
+	
+	/**
+	 * Checks if the specified class has the given method. The 
+	 * getMethods method of Class is used so only public methods are 
+	 * checked
+	 *
+	 * @param cl class
+	 * @param name name of the method
+	 * @param staticRequired if <code>true</code> then the method is required to be static
+	 *
+	 * @return <code>true</code> if the class <code>cl</code> has the method <code>name</code>
+	 */
+	public static boolean classHasMethod(Class cl, String name, boolean staticRequired) {
+		Method[] methodz = cl.getMethods();
+		for (int i = 0; i < methodz.length; i++)
+			if (name.equals(methodz[i].getName()) && (!staticRequired || ((methodz[i].getModifiers() & Modifier.STATIC) != 0)))
+				return true;
+		return false;
+	}
+	
+	/**
+	 * Checks if the specified class has the given inner class. The 
+	 * getClasses method of Class is used so only public classes are 
+	 * checked
+	 *
+	 * @param cl class
+	 * @param name name of the inner class
+	 * @param staticRequired if <code>true</code> then the method is required to be static
+	 *
+	 * @return <code>true</code> if the class <code>cl</code> has the field <code>name</code>
+	 */
+	public static boolean classHasClass(Class cl, String name, boolean staticRequired) {
+		Class[] clazzes = cl.getClasses();
+		for (int i = 0; i < clazzes.length; i++)
+			if (name.equals( getSimpleName(clazzes[i].getName()) ) && (!staticRequired || isStatic( clazzes[i] ) ) )
+				return true;
+		return false;
+	}
+	
+	/**
+	 * Checks if the class of the object has the given method. The 
+	 * getMethods method of Class is used so only public methods are 
+	 * checked
+	 *
+	 * @param o object
+	 * @param name name of the method
+	 *
+	 * @return <code>true</code> if the class of <code>o</code> has the field <code>name</code>
+	 */
+	public static boolean hasMethod(Object o, String name) {
+		return classHasMethod(o.getClass(), name, false); 
+	}
+	
+	
+	
+	/**
+	 * Object creator. Find the best constructor based on the parameter classes
+	 * and invoke newInstance on the resolved constructor
+	 */
+	public static Object newInstance( Class o_clazz, Object[] args, Class[] clazzes ) throws Throwable {
+		
+		boolean[] is_null = new boolean[args.length];
+		for( int i=0; i<args.length; i++) {
+			is_null[i] = ( args[i] == null ) ;
+		}
+		
+		Constructor cons = getConstructor( o_clazz, clazzes, is_null );
+		
+		/* enforcing accessibility (workaround for bug 128) */
+		boolean access = cons.isAccessible(); 
+		cons.setAccessible( true ); 
+		
+		Object o; 
+		try{
+			o = cons.newInstance( args ) ; 
+		} catch( InvocationTargetException e){
+			/* the target exception is much more useful than the reflection wrapper */
+			throw e.getTargetException() ;
+		} finally{
+			cons.setAccessible( access ); 
+		}
+		return o;                                 
+	}
+	
+	static boolean[] arg_is_null(Object[] args){
+		if( args == null ) return null ;
+		boolean[] is_null = new boolean[args.length];
+		for( int i=0; i<args.length; i++) {
+			is_null[i] = ( args[i] == null ) ;
+		}
+		return is_null ;
+	}
+	
+	/**
+	 * Invoke a method of a given class
+	 * <p>First the appropriate method is resolved by getMethod and
+	 * then invokes the method
+	 */
+	public static Object invokeMethod( Class o_clazz, Object o, String name, Object[] args, Class[] clazzes) throws Throwable {
+		
+		Method m = getMethod( o_clazz, name, clazzes, arg_is_null(args) );
+		
+		/* enforcing accessibility (workaround for bug 128) */
+		boolean access = m.isAccessible(); 
+		m.setAccessible( true ); 
+		
+		Object out; 
+		try{
+			out = m.invoke( o, args ) ; 
+		} catch( InvocationTargetException e){
+			/* the target exception is much more useful than the reflection wrapper */
+			throw e.getTargetException() ;
+		} finally{
+			m.setAccessible( access ); 
+		}
+		return out ; 
+	}
+	
+	/**
+	 * Attempts to find the best-matching constructor of the class
+	 * o_clazz with the parameter types arg_clazz
+	 * 
+	 * @param o_clazz Class to look for a constructor
+	 * @param arg_clazz parameter types
+	 * @param arg_is_null indicates if each argument is null
+	 * 
+	 * @return <code>null</code> if no constructor is found, or the constructor
+	 *
+	 */
+	public static Constructor getConstructor( Class o_clazz, Class[] arg_clazz, boolean[] arg_is_null) 
+		throws SecurityException, NoSuchMethodException {
+		
+		if (o_clazz == null)
+			return null; 
+
+		Constructor cons = null ;
+		
+		/* if there is no argument, try to find a direct match */
+		if (arg_clazz == null || arg_clazz.length == 0) {
+			cons = o_clazz.getConstructor( (Class[] )null );
+			return cons ;
+		}
+
+		/* try to find an exact match */
+		try {
+			cons = o_clazz.getConstructor(arg_clazz);
+			if (cons != null)
+				return cons ;
+		} catch (NoSuchMethodException e) {
+			/* we catch this one because we want to further search */
+		}
+		
+		/* ok, no exact match was found - we have to walk through all methods */
+		cons = null;
+		Constructor[] candidates = o_clazz.getConstructors();
+		for (int k = 0; k < candidates.length; k++) {
+			Constructor c = candidates[k];
+			Class[] param_clazz = c.getParameterTypes();
+			if (arg_clazz.length != param_clazz.length) // number of parameters must match
+				continue;
+			int n = arg_clazz.length;
+			boolean ok = true; 
+			for (int i = 0; i < n; i++) {
+				if( arg_is_null[i] ){
+					/* then the class must not be a primitive type */
+					if( isPrimitive(arg_clazz[i]) ){ 
+						ok = false ;
+						break ;
+					}
+				} else{
+					if (arg_clazz[i] != null && !param_clazz[i].isAssignableFrom(arg_clazz[i])) {
+						ok = false; 
+						break;
+					}
+				}
+			}
+			// it must be the only match so far or more specific than the current match
+			if (ok && (cons == null || isMoreSpecific(c, cons)))
+				cons = c; 
+		}
+		
+		if( cons == null ){
+			throw new NoSuchMethodException( "No constructor matching the given parameters" ) ;
+		}
+		
+		return cons; 
+		
+	}
+	
+	
+	static boolean isPrimitive(Class cl){
+		return cl.equals(Boolean.TYPE) || cl.equals(Integer.TYPE) || 
+						cl.equals(Double.TYPE) || cl.equals(Float.TYPE) || 
+						cl.equals(Long.TYPE) || cl.equals(Short.TYPE) ||
+						cl.equals(Character.TYPE) ;
+	}
+	
+	/**
+	 * Attempts to find the best-matching method of the class <code>o_clazz</code> with the method name <code>name</code> and arguments types defined by <code>arg_clazz</code>.
+	 * The lookup is performed by finding the most specific methods that matches the supplied arguments (see also {@link #isMoreSpecific}).
+	 *
+	 * @param o_clazz class in which to look for the method
+	 * @param name method name
+	 * @param arg_clazz an array of classes defining the types of arguments
+	 * @param arg_is_null indicates if each argument is null
+	 *
+	 * @return <code>null</code> if no matching method could be found or the best matching method.
+	 */
+	public static Method getMethod(Class o_clazz, String name, Class[] arg_clazz, boolean[] arg_is_null) 
+		throws SecurityException, NoSuchMethodException {
+		
+		if (o_clazz == null)
+			return null; 
+
+		/* if there is no argument, try to find a direct match */
+		if (arg_clazz == null || arg_clazz.length == 0) {
+				return o_clazz.getMethod(name, (Class[])null);
+		}
+
+		/* try to find an exact match */
+		Method met;
+		try {
+			met = o_clazz.getMethod(name, arg_clazz);
+			if (met != null)
+				return met;
+		} catch (NoSuchMethodException e) {
+			/* we want to search further */
+		}
+		
+		/* ok, no exact match was found - we have to walk through all methods */
+		met = null;
+		Method[] ml = o_clazz.getMethods();
+		for (int k = 0; k < ml.length; k++) {
+			Method m = ml[k];
+			if (!m.getName().equals(name)) // the name must match
+				continue; 
+			Class[] param_clazz = m.getParameterTypes();
+			if (arg_clazz.length != param_clazz.length) // number of parameters must match
+				continue;
+			int n = arg_clazz.length;
+			boolean ok = true; 
+			for (int i = 0; i < n; i++) {
+				if( arg_is_null[i] ){
+					/* then the class must not be a primitive type */
+					if( isPrimitive(arg_clazz[i]) ){ 
+						ok = false ;
+						break ;
+					}
+				} else{
+					if (arg_clazz[i] != null && !param_clazz[i].isAssignableFrom(arg_clazz[i])) {
+						ok = false; 
+						break;
+					}
+				}
+			}
+			if (ok && (met == null || isMoreSpecific(m, met))) // it must be the only match so far or more specific than the current match
+				met = m; 
+		}
+		
+		if( met == null ){
+			throw new NoSuchMethodException( "No suitable method for the given parameters" ) ; 
+		}
+		return met; 
+	}
+
+	/** 
+	 * Returns <code>true</code> if <code>m1</code> is more specific than <code>m2</code>. 
+	 * The measure used is described in the isMoreSpecific( Class[], Class[] ) method
+	 *
+	 * @param m1 method to compare
+	 * @param m2 method to compare 
+	 *
+	 * @return <code>true</code> if <code>m1</code> is more specific (in arguments) than <code>m2</code>.
+	 */
+	private static boolean isMoreSpecific(Method m1, Method m2) {
+		Class[] m1_param_clazz = m1.getParameterTypes();
+		Class[] m2_param_clazz = m2.getParameterTypes();
+		return isMoreSpecific( m1_param_clazz, m2_param_clazz ); 
+	}
+	
+	/** 
+	 * Returns <code>true</code> if <code>cons1</code> is more specific than <code>cons2</code>. 
+	 * The measure used is described in the isMoreSpecific( Class[], Class[] ) method
+	 *
+	 * @param cons1 constructor to compare
+	 * @param cons2 constructor to compare 
+	 * 
+	 * @return <code>true</code> if <code>cons1</code> is more specific (in arguments) than <code>cons2</code>.
+	 */
+	private static boolean isMoreSpecific(Constructor cons1, Constructor cons2) {
+		Class[] cons1_param_clazz = cons1.getParameterTypes();
+		Class[] cons2_param_clazz = cons2.getParameterTypes();
+		return isMoreSpecific( cons1_param_clazz, cons2_param_clazz ); 
+	}
+	 
+	/**
+	 * Returns <code>true</code> if <code>c1</code> is more specific than <code>c2</code>. 
+	 *
+	 * The measure used is the sum of more specific arguments minus the sum of less specific arguments 
+	 * which in total must be positive to qualify as more specific. 
+	 * (More specific means the argument is a subclass of the other argument). 
+	 *
+	 * Both set of classes must have signatures fully compatible in the arguments 
+	 * (more precisely incompatible arguments are ignored in the comparison).
+	 *
+	 * @param c1 set of classes to compare
+	 * @param c2 set of classes to compare
+   */
+	private static boolean isMoreSpecific( Class[] c1, Class[] c2){
+	 	int n = c1.length ;
+		int res = 0; 
+		for (int i = 0; i < n; i++)
+			if( c1[i] != c2[i]) {
+				if( c1[i].isAssignableFrom(c2[i]))
+					res--;
+				else if( c2[i].isAssignableFrom(c2[i]) )
+					res++;
+			}
+		return res > 0;
+	}
+	
+	/**
+	 * Returns the list of classes of the object 
+	 *
+	 * @param o an Object
+	 */
+	public static Class[] getClasses(Object o){
+		Vector/*<Class<?>>*/ vec = new Vector(); 
+		Class cl = o.getClass(); 
+		while( cl != null ){
+			vec.add( cl ) ; 
+			cl = cl.getSuperclass() ;
+		}
+		Class[] res = new Class[ vec.size() ] ;
+		vec.toArray( res) ;
+		return res ;
+	}
+	
+	/**
+	 * Returns the list of class names of the object 
+	 *
+	 * @param o an Object
+	 */
+	public static String[] getClassNames(Object o){
+		Vector/*<String>*/ vec = new Vector(); 
+		Class cl = o.getClass(); 
+		while( cl != null ){
+			vec.add( cl.getName() ) ;
+			cl = cl.getSuperclass() ;
+		}
+		String[] res = new String[ vec.size() ] ;
+		vec.toArray( res) ;
+		return res ;
+	}
+	
+	/**
+	 * Returns the list of simple class names of the object
+	 *
+	 * @param o an Object
+	 */
+	public static String[] getSimpleClassNames(Object o, boolean addConditionClasses){
+		boolean hasException = false ;
+		Vector/*<String>*/ vec = new Vector(); 
+		Class cl = o.getClass();
+		String name ;
+		while( cl != null ){
+			name = getSimpleName( cl.getName() ) ;
+			if( "Exception".equals( name) ){
+				hasException = true ;
+			}
+			vec.add( name ) ;
+			cl = cl.getSuperclass() ;
+		}
+		if( addConditionClasses ){
+			if( !hasException ){
+				vec.add( "Exception" ) ;
+			}
+			vec.add( "error" ) ;
+			vec.add( "condition" ) ;
+		}
+		
+		String[] res = new String[ vec.size() ] ;
+		vec.toArray( res) ;
+		return res ;
+	}
+
+	/* because Class.getSimpleName is java 5 API */ 
+	private static String getSimpleClassName( Object o ){
+		return getSimpleName( o.getClass().getName() ) ; 
+	}
+	
+	private static String getSimpleName( String s ){
+		int lastsquare = s.lastIndexOf( '[' ) ;
+		if( lastsquare >= 0 ){
+			if( s.charAt(  s.lastIndexOf( '[' ) + 1 ) == 'L' ){
+				s = s.substring( s.lastIndexOf( '[' ) + 2, s.lastIndexOf( ';' ) ) ;
+			} else {
+				char first = s.charAt( 0 );
+				if( first == 'I' ) {
+					s = "int" ;
+				} else if( first == 'D' ){
+					s = "double" ;
+				} else if( first == 'Z' ){
+					s = "boolean" ;
+				} else if( first == 'B' ){
+					s = "byte" ;
+				} else if( first == 'J' ){
+					s = "long" ; 
+				} else if( first == 'F' ){
+					s = "float" ; 
+				} else if( first == 'S' ){
+					s = "short" ; 
+				} else if( first == 'C' ){
+					s = "char" ;
+				}
+			}
+		}
+		
+		int lastdollar = s.lastIndexOf( '$' ) ;
+		if( lastdollar >= 0 ){
+			s = s.substring( lastdollar + 1);
+		}
+		
+		int lastdot = s.lastIndexOf( '.' ) ;
+		if( lastdot >= 0 ){
+			s = s.substring( lastdot + 1);
+		}
+		
+		if( lastsquare >= 0 ){
+			StringBuffer buf = new StringBuffer( s );
+			int i ;
+			for( i=0; i<=lastsquare; i++){
+				buf.append( "[]" ); 
+			}
+			return buf.toString(); 
+		} else {
+			return s ;
+		}
+		
+	}
+	
+	/**
+	 * @param cl class 
+	 * @param field name of the field 
+	 * 
+	 * @return the class name of the field of the class (or null) 
+	 * if the class does not have the given field)
+	 */
+	public static String getFieldTypeName( Class cl, String field){
+		String res = null ; 
+		try{
+			res = cl.getField( field ).getType().getName() ;
+		} catch( NoSuchFieldException e){
+			/* just return null */
+			res = null ;
+		}
+		return res ;
+	}
+		
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayBuilder.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c4b174fc12bcdc36c6ce9e63eee9410e13917b3
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayBuilder.java
@@ -0,0 +1,199 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+// :tabSize=2:indentSize=2:noTabs=false:folding=explicit:collapseFolds=1:
+
+import java.lang.reflect.Array ; 
+
+/**
+ * Builds rectangular java arrays
+ */
+public class RectangularArrayBuilder extends RJavaArrayIterator {
+	
+	// {{{ constructors
+	/**
+	 * constructor
+	 *
+	 * @param payload one dimensional array
+	 * @param dimensions target dimensions
+	 * @throws NotAnArrayException if payload is not an array
+	 */
+	public RectangularArrayBuilder( Object payload, int[] dimensions) throws NotAnArrayException, ArrayDimensionException {
+		
+		super( dimensions ) ; 
+		if( !RJavaArrayTools.isArray(payload) ){
+			throw new NotAnArrayException( payload.getClass() ) ;
+		}
+		if( !RJavaArrayTools.isSingleDimensionArray(payload)){
+			throw new ArrayDimensionException( "not a single dimension array : " + payload.getClass() ) ;
+		}
+		
+		if( dimensions.length == 1 ){
+			array = payload ;
+		} else{
+			
+			String typeName = RJavaArrayTools.getObjectTypeName( payload ); 
+			Class clazz = null ;
+			try{
+				clazz = RJavaArrayTools.getClassForSignature( typeName, payload.getClass().getClassLoader() );  
+			} catch( ClassNotFoundException e){/* should not happen */}
+			
+			array = Array.newInstance( clazz , dimensions ) ;
+		  if( typeName.equals( "I" ) ){
+		  	fill_int( (int[])payload ) ;
+		  } else if( typeName.equals( "Z" ) ){
+		  	fill_boolean( (boolean[])payload ) ;
+		  } else if( typeName.equals( "B" ) ){
+		  	fill_byte( (byte[])payload ) ;
+		  } else if( typeName.equals( "J" ) ){
+		  	fill_long( (long[])payload ) ;
+		  } else if( typeName.equals( "S" ) ){
+		  	fill_short( (short[])payload ) ;
+		  } else if( typeName.equals( "D" ) ){
+		  	fill_double( (double[])payload ) ;
+		  } else if( typeName.equals( "C" ) ){
+		  	fill_char( (char[])payload ) ;
+		  } else if( typeName.equals( "F" ) ){
+		  	fill_float( (float[])payload ) ;
+		  } else{
+		  	fill_Object( (Object[])payload ) ;
+		  }
+			
+		}
+	}
+	public RectangularArrayBuilder( Object payload, int length ) throws NotAnArrayException, ArrayDimensionException{
+		this( payload, new int[]{ length } ) ;
+	}
+
+	// java < 1.5 kept happy
+	public RectangularArrayBuilder(int x    , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : int     ") ; }
+	public RectangularArrayBuilder(boolean x, int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : boolean ") ; }
+	public RectangularArrayBuilder(byte x   , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : byte    ") ; }
+	public RectangularArrayBuilder(long x   , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : long    ") ; }
+	public RectangularArrayBuilder(short x  , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : short   ") ; }
+	public RectangularArrayBuilder(double x , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : double  ") ; }
+	public RectangularArrayBuilder(char x   , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : char    ") ; }
+	public RectangularArrayBuilder(float x  , int[] dim ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : float   ") ; }
+
+	public RectangularArrayBuilder(int x    , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : int     ") ; }
+	public RectangularArrayBuilder(boolean x, int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : boolean ") ; }
+	public RectangularArrayBuilder(byte x   , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : byte    ") ; }
+	public RectangularArrayBuilder(long x   , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : long    ") ; }
+	public RectangularArrayBuilder(short x  , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : short   ") ; }
+	public RectangularArrayBuilder(double x , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : double  ") ; }
+	public RectangularArrayBuilder(char x   , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : char    ") ; }
+	public RectangularArrayBuilder(float x  , int length ) throws NotAnArrayException { throw new NotAnArrayException("primitive type : float   ") ; }
+	// }}}
+	
+	// {{{ fill_**
+	private void fill_int( int[] payload ){
+		int k; 
+		while( hasNext() ){
+			int[] current = (int[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+	
+	private void fill_boolean( boolean[] payload ){
+		int k; 
+		while( hasNext() ){
+			boolean[] current = (boolean[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+	
+	private void fill_byte( byte[] payload ){
+		int k; 
+		while( hasNext() ){
+			byte[] current = (byte[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+	
+	private void fill_long( long[] payload ){
+		int k; 
+		while( hasNext() ){
+			long[] current = (long[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+
+	private void fill_short( short[] payload ){
+		int k; 
+		while( hasNext() ){
+			short[] current = (short[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+
+	private void fill_double( double[] payload ){
+		int k; 
+		while( hasNext() ){
+			double[] current = (double[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+
+	private void fill_char( char[] payload ){
+		int k; 
+		while( hasNext() ){
+			char[] current = (char[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+
+	private void fill_float( float[] payload ){
+		int k; 
+		while( hasNext() ){
+			float[] current = (float[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+	
+	private void fill_Object( Object[] payload ){
+		int k; 
+		while( hasNext() ){
+			Object[] current = (Object[])next() ;
+			k = start ; 
+			for( int j=0; j<current.length; j++, k+=increment){
+				current[j] = payload[k];
+			}
+		}
+	}
+
+	// }}}
+
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayExamples.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayExamples.java
new file mode 100644
index 0000000000000000000000000000000000000000..37221045298aacf25d39d9c663ad2fc8661b5ffb
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayExamples.java
@@ -0,0 +1,265 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+// :tabSize=2:indentSize=2:noTabs=false:folding=explicit:collapseFolds=1:
+
+/**
+ * Utility class that makes example rectangular java arrays of 2 and 3 dimensions
+ * for all primitive types, String and Point (as an example of array of non primitive object)
+ */
+public class RectangularArrayExamples {
+
+	// {{{ Example 2d rect arrays 
+	public static int[][] getIntDoubleRectangularArrayExample(){
+		int[][] x = new int[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = k ;
+			}
+		}
+		return x; 
+	}
+	
+	public static boolean[][] getBooleanDoubleRectangularArrayExample(){
+		boolean[][] x = new boolean[5][2]; 
+		boolean current = false;  
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, current = !current){
+				x[i][j] = current ;
+			}
+		}
+		return x ;
+	}
+	
+	public static byte[][] getByteDoubleRectangularArrayExample(){
+		byte[][] x = new byte[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = (byte)k ;
+			}
+		}
+		return x; 
+	}
+	
+	public static long[][] getLongDoubleRectangularArrayExample(){
+		long[][] x = new long[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = (long)k ;
+			}
+		}
+		return x; 
+	}
+	
+	public static short[][] getShortDoubleRectangularArrayExample(){
+		short[][] x = new short[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = (short)k ;
+			}
+		}
+		return x; 
+	}
+	
+	public static double[][] getDoubleDoubleRectangularArrayExample(){
+		double[][] x = new double[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = k + 0.0 ;
+			}
+		}
+		return x; 
+	}
+	
+	public static char[][] getCharDoubleRectangularArrayExample(){
+		char[][] x = new char[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = (char)k ;
+			}
+		}
+		return x; 
+	}
+	
+	public static float[][] getFloatDoubleRectangularArrayExample(){
+		float[][] x = new float[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = k + 0.0f ;
+			}
+		}
+		return x; 
+	}
+	
+	public static String[][] getStringDoubleRectangularArrayExample(){
+		String[][] x = new String[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = "" + k ;
+			}
+		}
+		return x; 
+	}
+	
+	public static DummyPoint[][] getDummyPointDoubleRectangularArrayExample(){
+		DummyPoint[][] x = new DummyPoint[5][2]; 
+		int k= 0; 
+		for( int j=0; j<2; j++){
+			for( int i=0; i<5; i++, k++){
+				x[i][j] = new DummyPoint(k,k) ;
+			}
+		}
+		return x; 
+	}
+	// }}}
+	
+	// {{{ Example 3d rect arrays 
+	public static int[][][] getIntTripleRectangularArrayExample(){
+		int[][][] x = new int[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static boolean[][][] getBooleanTripleRectangularArrayExample(){
+		boolean[][][] x = new boolean[5][3][2]; 
+		boolean current = false ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current= !current){
+					x[i][j][k] = current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static byte[][][] getByteTripleRectangularArrayExample(){
+		byte[][][] x = new byte[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = (byte)current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static long[][][] getLongTripleRectangularArrayExample(){
+		long[][][] x = new long[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = (long)current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static short[][][] getShortTripleRectangularArrayExample(){
+		short[][][] x = new short[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = (short)current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static double[][][] getDoubleTripleRectangularArrayExample(){
+		double[][][] x = new double[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = 0.0 + current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static char[][][] getCharTripleRectangularArrayExample(){
+		char[][][] x = new char[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = (char)current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static float[][][] getFloatTripleRectangularArrayExample(){
+		float[][][] x = new float[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = 0.0f + current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static String[][][] getStringTripleRectangularArrayExample(){
+		String[][][] x = new String[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = ""+current ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	public static DummyPoint[][][] getDummyPointTripleRectangularArrayExample(){
+		DummyPoint[][][] x = new DummyPoint[5][3][2]; 
+		int current = 0 ;
+		for( int k=0; k<2; k++){
+			for( int j=0; j<3; j++){
+				for( int i=0; i<5; i++, current++){
+					x[i][j][k] = new DummyPoint( current, current ) ;
+				}
+			}
+		}
+		return x; 
+	}
+	
+	// }}}
+	
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArraySummary.java b/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArraySummary.java
new file mode 100644
index 0000000000000000000000000000000000000000..686a6c259f0475b1f591caf0b91638b5d1675fb2
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArraySummary.java
@@ -0,0 +1,280 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+// :tabSize=2:indentSize=2:noTabs=false:folding=explicit:collapseFolds=1:
+
+import java.lang.reflect.Array ; 
+
+/** 
+ * Utility class to extract something from a rectangular array
+ */
+public class RectangularArraySummary extends RJavaArrayIterator {
+	
+	private int length ; 
+	
+	private String typeName ;
+	
+	private boolean isprimitive ;
+	
+	private Class componentType ;
+	
+	/**
+	 * Constructor
+	 *
+	 * @param array the array to check
+	 * @throws NotAnArrayException if array is not an array
+	 */
+	public RectangularArraySummary(Object array, int[] dimensions) throws NotAnArrayException, NotComparableException {
+		super( dimensions );
+		this.array = array ;
+		typeName = RJavaArrayTools.getObjectTypeName(array );
+		isprimitive = RJavaArrayTools.isPrimitiveTypeName( typeName ) ;
+		try{
+			componentType = RJavaArrayTools.getClassForSignature( typeName , array.getClass().getClassLoader() ) ;
+		} catch( ClassNotFoundException e){}
+		checkComparableObjects() ;
+	}
+	
+	public RectangularArraySummary(Object array, int length ) throws NotAnArrayException, NotComparableException{
+		this( array, new int[]{ length } ); 
+	}
+	
+	/** 
+	 * Iterates over the array to find the minimum value
+	 * (in the sense of the Comparable interface)
+	 */
+	public Object min( boolean narm ) {
+		if( isprimitive ){
+			return null ; // TODO :implement
+		}
+		Object smallest = null ;
+		Object current ;
+		boolean found = false ;
+		
+		if( dimensions.length == 1 ){
+			return( min( (Object[])array, narm ) ) ;
+		} else{
+			
+			/* need to iterate */
+			while( hasNext() ){
+				current = min( (Object[])next(), narm ) ;
+				if( current == null ){
+					if( !narm ) return null ;
+				} else{
+					if( !found ){
+						smallest = current ;
+						found = true ;
+					} else if( smaller( current, smallest ) ) {
+						smallest = current ;
+					}					
+				}
+			}
+			return smallest ;
+		}
+		
+	}
+	
+	/** 
+	 * Iterates over the array to find the maximum value
+	 * (in the sense of the Comparable interface)
+	 */
+	public Object max( boolean narm )  {
+		if( isprimitive ){
+			return null ; // TODO :implement
+		}
+		
+		Object biggest = null ;
+		Object current ;
+		boolean found = false ;
+		
+		if( dimensions.length == 1 ){
+			return( max( (Object[])array, narm ) ) ;
+		} else{
+			
+			/* need to iterate */
+			while( hasNext() ){
+				current = max( (Object[])next(), narm ) ;
+				if( current == null ){
+					if( !narm ) return null ;
+				} else{
+					if( !found ){
+						biggest = current ;
+						found = true ;
+					} else if( bigger( current, biggest) ){ 
+						biggest = current ;
+					}					
+				}
+			}
+			return biggest ;
+		}
+		
+	}
+
+	/** 
+	 * Iterates over the array to find the range of the java array
+	 * (in the sense of the Comparable interface)
+	 */
+	public Object[] range( boolean narm )  {
+		if( isprimitive ){
+			return null ; // TODO :implement
+		}
+		
+		if( dimensions.length == 1 ){
+			return( range( (Object[])array, narm ) ) ;
+		} else{
+			
+			Object[] range = null ;
+			Object[] current ;
+			boolean found = false ;
+		
+			/* need to iterate */
+			while( hasNext() ){
+				current = range( (Object[])next(), narm ) ;
+				if( current == null ){
+					if( !narm ) return null ;
+				} else{
+					if( !found ){
+						range = current ;
+						found = true ;
+					} else {
+						if( bigger( current[1], range[1] ) ){
+							range[1] = current[1] ;
+						}
+						if( smaller( current[0], range[0] ) ){
+							range[0] = current[0] ;
+						}	
+						
+					}
+				}
+			}
+			return range ;
+		}
+		
+	}
+
+	
+	
+	
+	/**
+	 * returns the minimum (in the sense of Comparable) of the 
+	 * objects in the one dimensioned array
+	 */ 
+	private static Object min( Object[] x, boolean narm ){
+		
+		int n = x.length ;
+		Object smallest = null ; 
+		Object current ;
+		boolean found_min = false; 
+		
+		// find somewhere to start from ()
+		for( int i=0; i<n; i++){
+			current = x[i] ;
+			if( current == null ){
+				if( !narm ) return null ;
+			} else{
+				if( !found_min ){
+					smallest = current ;
+					found_min = true ;
+				} else if( ((Comparable)smallest).compareTo(current) > 0 ) {
+					smallest = current ;
+				}
+			}
+		}
+		return smallest ; 
+		
+	}
+	
+	/**
+	 * returns the minimum (in the sense of Comparable) of the 
+	 * objects in the one dimensioned array
+	 */ 
+	private static Object max( Object[] x, boolean narm ){
+		
+		int n = x.length ;
+		Object biggest = null ; 
+		Object current ;
+		boolean found_min = false; 
+		
+		// find somewhere to start from ()
+		for( int i=0; i<n; i++){
+			current = x[i] ;
+			if( current == null ){
+				if( !narm ) return null ;
+			} else{
+				if( !found_min ){
+					biggest = current ;
+					found_min = true ;
+				} else if( ((Comparable)biggest).compareTo(current) < 0 ) {
+					biggest = current ;
+				}
+			}
+		}
+		return biggest ; 
+		
+	}
+
+	/**
+	 * returns the range (in the sense of Comparable) of the 
+	 * objects in the one dimensioned array
+	 */ 
+	private static Object[] range( Object[] x, boolean narm ){
+		
+		int n = x.length ;
+		Object[] range = (Object[])Array.newInstance( x.getClass().getComponentType(), 2) ; 
+		Object current ;
+		boolean found = false; 
+		
+		// find somewhere to start from ()
+		for( int i=0; i<n; i++){
+			current = x[i] ;
+			if( current == null ){
+				if( !narm ) return null ;
+			} else{
+				if( !found ){
+					range[0] = current ;
+					range[1] = current ;
+					found = true ;
+				} else {
+					// max
+					if( ((Comparable)range[1]).compareTo(current) < 0 ) {
+						range[1] = current ;
+					}
+					// min
+					if( ((Comparable)range[0]).compareTo(current) > 0 ) {
+						range[0] = current ;
+					}
+					
+				}
+			}
+		}
+		return range ; 
+		
+	}
+	
+	public void checkComparableObjects() throws NotComparableException {
+		if( ! containsComparableObjects() ) throw new NotComparableException( typeName ) ;
+	}
+	
+	public boolean containsComparableObjects(){
+		return Comparable.class.isAssignableFrom( componentType ) ;
+	}
+	
+	// TODO : use these
+	private static boolean smaller( Object x, Object y){
+		return ( (Comparable)x ).compareTo(y) < 0 ;
+	}
+	private static boolean bigger( Object x, Object y){
+		return ( (Comparable)x ).compareTo(y) > 0 ;
+	}
+	
+	
+}
+
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R
deleted file mode 100644
index 46b38886ec61b333475eda982a77f68ac0bdd59a..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R
+++ /dev/null
@@ -1,5 +0,0 @@
-library(testthat)
-library(rjava)
-
-test_check("rjava")
-typeName
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
deleted file mode 100644
index 1fb95666c0d118d0b40b88a009f4a5f3f1051f61..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
+++ /dev/null
@@ -1,104 +0,0 @@
-# prerequisites:
-# - 'testthat' package has to be installed: install.packages("testthat")
-# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava
-
-library(testthat)
-library(rJava)
-
-.jaddClassPath(paste0(Sys.getenv("R_HOME"), "/mxbuild/dists/fastr-unit-tests.jar"))
-
-testName <- "test .jarray"
-test_that(testName, {
-    cat(paste0(testName, "\n"))
-	    
-    a <- .jarray(c(1.1, 2.1, 3.1))
-    expect_true(is.external.array(a))
-    expect_equal(length(a), 3)
-    expect_equal(a[1], c(1.1))
-    expect_equal(a[2], c(2.1))
-    expect_equal(a[3], c(3.1))
-
-    a <- .jarray(c(1L, 2L, 3L))
-    expect_true(is.external.array(a))
-    expect_equal(length(a), 3)
-    expect_equal(a[1], c(1))
-    expect_equal(a[2], c(2))
-    expect_equal(a[3], c(3))
-
-    a <- .jarray(c(TRUE, FALSE))
-    expect_true(is.external.array(a))
-    expect_equal(length(a), 2)
-    expect_equal(a[1], TRUE)
-    expect_equal(a[2], FALSE)
-
-    a <- .jarray(c(.jbyte(1), .jchar("a"), .jfloat(1.1), .jlong(2), .jshort(123)))
-    expect_true(is.external.array(a))
-    expect_equal(length(a), 5)
-    expect_equal(a[1], 1)
-    expect_equal(a[2], "a")
-    expect_true((a[3] - 1.1)^2 < 1e-8)
-    expect_equal(a[4], 2)
-    expect_equal(a[5], 123)
-
-    to <- .jnew('java.util.ArrayList')
-    a <- .jarray(to)
-    expect_true(is.external.array(a))
-    expect_equal(length(a), 1)
-    # fails at the moment  
-    # testthat passes 'to' into .Call("find_label_", quote(to), environment()) 
-    # expect_equal(a[1], to)
-  
-    to <- .jnew('java.util.ArrayList')
-    a <- .jarray(c(to, to))
-    expect_true(is.external.array(a))
-    # fails at the moment    
-    # expect_equal(length(a), 2)
-    # expect_equal(a[1], to)
-    # expect_equal(a[2], to)
-
-    a <- .jarray(list(1, 2, 3))
-    expect_true(is.external.array(a))
-    expect_equal(length(a), 3)
-    expect_equal(a[1], 1)
-    expect_equal(a[2], 2)
-    expect_equal(a[3], 3)
-})
-
-testName <- "test .jevalArray"
-test_that(testName, {
-    cat(paste0(testName, "\n"))
-
-    expectedValues <- list(
-        Boolean=list("logical", TRUE, FALSE, TRUE), 
-        Byte=list("integer", 1,2,3), 
-        Char=list("character", "a", "b", "c"), 
-        Double=list("double",1.1, 2.1, 3.1), 
-        Float=list("double", 1.1, 2.1, 3.1), 
-        Integer=list("integer",1,2,3), 
-        Long=list("double", 1,2,3), 
-        Short=list("integer",1,2,3), 
-        String=list("character", "a", "b", "c"))
-    testClassName <- "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
-    t<-.jnew(class=testClassName)
-
-    for(expectedName in names(expectedValues)) {                
-        fieldName <- paste0("fieldStatic", expectedName, "Array")
-        ev<-expectedValues[expectedName][[1]]
-        arrayType <- ev[[1]]
-        arrayLength <- length(ev) - 1
-        a<-t[fieldName]
-        expect_true(is.external.array(a), info=paste0("the array was returned for ", fieldName), label="is.external.array")
-        ae<-.jevalArray(a)
-        expect_true(is.vector(ae), info=paste0("the array was returned for ", fieldName), label="is.vector")
-        expect_equal(typeof(ae), arrayType, info=paste0("the array was returned for ", fieldName), label="typeof")
-        expect_equal(length(ae), arrayLength, info=paste0("the array was returned for ", fieldName), label="array length")
-        for(i in 1:arrayLength) {
-            if(expectedName != "Float") {
-                expect_equal(a[i], ev[[i+1]], info=paste0("the array was returned for ", fieldName), label=paste0("value at", i))
-            } else {
-                expect_true((ev[[i+1]] - a[i])^2 < 1e-8, info=paste0("the array was returned for ", fieldName), label=paste0("value at", i))
-            }
-        }
-    }
-
-})
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R
deleted file mode 100644
index 1062c93039bbe8c78bbe2bb8bb816a81bf4bce15..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R
+++ /dev/null
@@ -1,135 +0,0 @@
-# prerequisites:
-# - 'testthat' package has to be installed: install.packages("testthat")
-# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava
-
-library(testthat)
-library(rJava)
-.jaddClassPath(paste0(Sys.getenv("R_HOME"), "/mxbuild/dists/fastr-unit-tests.jar"))
-
-bo <- TRUE
-bt <- 123
-ch <- 'a'
-d  <- 1.123456
-f  <- 1.123
-i  <- 12345L
-l  <- 123456
-sh <- 1234
-st <- "a test string"
-
-jbt <- .jbyte(bt)
-jch <- .jchar(ch)
-jf  <- .jfloat(f)
-jl  <- .jlong(l)
-jsh <- .jshort(sh)
-
-primitiveTypeNames <- c("Boolean", "Byte", "Char", "Double", "Float", "Integer", "Long", "Short")
-expectedValues <- list(bo, bt, ch, d, f, i, l, sh, st)
-
-testClassName <- "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
-t<-.jnew(class=testClassName, bo, jbt, jch, d, jf, i, jl, jsh, st)
-
-testForMember <- function(valueProvider, memberNameProvider, typeNames) {
-	for(idx in 1:length(typeNames)) {	
-		typeName <- typeNames[idx]
-		member <- memberNameProvider(typeName)
-		expectedValue <- expectedValues[[idx]]
-		value <- valueProvider(t, member)
-		testValue(member, typeName, expectedValue, value)
-	}
-}
-
-testValue <- function(memberName, typeName, expectedValue, value) {
-	cat(paste0("  ", memberName, " returned value [", value, "] and is expected to be [", expectedValue, "]"), "\n")
-	if(typeName != "Float") {
-		expect_that(expectedValue, equals(value), info=memberName, label=memberName)
-	} else {
-		expect_true((expectedValue - value)^2 < 1e-8, info=memberName, label=memberName)
-	}
-}
-
-testName <- "test if primitive field access works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("field", typeName) },
-                   primitiveTypeNames )
-})
-
-testName <- "test if primitive static field access works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("fieldStatic", typeName) },
-                   primitiveTypeNames )
-})
-
-testName <- "test if static field access works"
-test_that("test if static field access works", {
-	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("fieldStatic", typeName, "Object") },
-                   c(primitiveTypeNames, "String") )
-})
-
-testName <- "test if field access works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("field", typeName, "Object")},
-                   c(primitiveTypeNames, "String") )
-})
-
-testName <- "test if calling static method returning primitive values works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("methodStatic", typeName) },
-                   primitiveTypeNames )
-})
-
-testName <- "test if calling method returning primitive values works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("method", typeName) },
-                   primitiveTypeNames )
-})
-
-testName <- "test if calling static method returning object values works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("methodStatic", typeName, "Object") },
-                   c(primitiveTypeNames, "String") )
-})
-
-testName <- "test if calling method returning object values works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
-                   memberNameProvider = function(typeName) { paste0("method", typeName, "Object") },
-                   c(primitiveTypeNames, "String") )
-})
-
-testName <- "test if static access via class name works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	value <- .jfield(testClassName, , "fieldStaticInteger")
-	testValue("fieldStaticInteger", "Integer", i, value)
-
-	value <- .jcall(testClassName, , "methodStaticInteger")
-	testValue("methodStaticInteger", "Integer", i, value)
-})
-
-testName <- "test if calling method with all primitive type parameters + string works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	value <- .jcall(t, , "allTypesMethod", bo, jbt, jch, d, jf, i, jl, jsh, st)
-	expect_false(is.null(value))
-})
-
-testName <- "test if calling method with all primitive type parameters + string works"
-test_that(testName, {
-	cat(paste0(testName, "\n"))
-	value <- .jcall(t, , "allTypesStaticMethod", bo, jbt, jch, d, jf, i, jl, jsh, st)
-	expect_false(is.null(value))
-})
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testJ.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testJ.R
deleted file mode 100644
index a406765bfd11c9486d53507445846d5dfbfda577..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testJ.R
+++ /dev/null
@@ -1,21 +0,0 @@
-# prerequisites:
-# - 'testthat' package has to be installed: install.packages("testthat")
-# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava
-
-library(testthat)
-library(rJava)
-
-.jaddClassPath(paste0(Sys.getenv("R_HOME"), "/mxbuild/dists/fastr-unit-tests.jar"))
-
-testName <- "test J function"
-test_that(testName, {
-    cat(paste0(testName, "\n"))
-    tc <- J("com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass")
-    expect_equal(2147483647L, tc$fieldStaticInteger)
-
-    tc <- J("com/oracle/truffle/r/test/library/fastr/TestJavaInterop$TestClass")
-    expect_equal(2147483647L, tc$fieldStaticInteger)
-
-    expect_equal(2147483647L, J("com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass", "methodStaticInteger"))
-    expect_equal(2147483647L, J("com/oracle/truffle/r/test/library/fastr/TestJavaInterop$TestClass", "methodStaticInteger"))
-})
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 531d285ffd8af586e24062ab1bda8a3a70e48fd0..376ba865e2ab3799c5ab434ed3821fb517e7fbe1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -123,6 +123,23 @@ public final class RError extends RuntimeException implements TruffleException {
      */
     public static final ErrorContext SHOW_CALLER = new ErrorContextImpl();
 
+    /**
+     * This flags a call to {@code error} or {@code warning} where the error message should show the
+     * caller provided function if such is available. Otherwise the caller of the current function
+     * will be shown.
+     */
+    public static final class ShowCallerOf extends ErrorContext {
+        private final String function;
+
+        public ShowCallerOf(String function) {
+            this.function = function;
+        }
+
+        public String getCallerOf() {
+            return function;
+        }
+    }
+
     /**
      * A very special case that ensures that no caller is output in the error/warning message. This
      * is needed where, even if there is a caller, GnuR does not show it.
@@ -193,7 +210,7 @@ public final class RError extends RuntimeException implements TruffleException {
 
     @TruffleBoundary
     public static RError handleInteropException(Node node, RuntimeException e) {
-        if (e instanceof TruffleException) {
+        if (e instanceof TruffleException || e.getCause() instanceof ClassNotFoundException) {
             if (RContext.getInstance().stateInteropTry.isInTry()) {
                 // will be catched and handled in .fastr.interop.try builtin
                 throw new FastRInteropTryException(e);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 14cbbbc8216169c4ca2e8770410c69787fec6a70..bd968fce28658fa6a8960386888877b6d8a88099 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -828,11 +828,29 @@ public final class RContext {
         }
     };
 
-    public Class<?> loadClass(String className) throws ClassNotFoundException {
-        if (FastRConfig.InternalGridAwtSupport) {
-            return interopClassLoader.loadClass(className);
+    private final HashMap<String, Class<?>> classCache = new HashMap<>();
+
+    /**
+     * This function also takes class names with '/' instead of '.'. A null return value means that
+     * the class was not found.
+     */
+    public Class<?> loadClass(String className) {
+        if (classCache.containsKey(className)) {
+            return classCache.get(className);
         }
-        return Class.forName(className);
+        String demangled = className.replaceAll("/", ".");
+        Class<?> result;
+        try {
+            if (FastRConfig.InternalGridAwtSupport) {
+                result = interopClassLoader.loadClass(demangled);
+            } else {
+                result = Class.forName(demangled);
+            }
+        } catch (ClassNotFoundException e) {
+            result = null;
+        }
+        classCache.put(className, result);
+        return result;
     }
 
     /**
@@ -849,6 +867,29 @@ public final class RContext {
             urls[i] = Paths.get(entries[i]).toUri().toURL();
         }
         interopClassLoader = URLClassLoader.newInstance(urls, interopClassLoader);
+        classCache.clear();
+    }
+
+    /**
+     * Returns all entries in the Java interop class loader.
+     * 
+     * @return the CP entries
+     */
+    public String[] getInteropClasspathEntries() {
+        if (!FastRConfig.InternalGridAwtSupport) {
+            throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Custom class loading not supported.");
+        }
+        if (interopClassLoader instanceof URLClassLoader) {
+            URL[] urls = ((URLClassLoader) interopClassLoader).getURLs();
+            if (urls != null) {
+                String[] ret = new String[urls.length];
+                for (int i = 0; i < urls.length; i++) {
+                    ret[i] = urls[i].getPath();
+                }
+                return ret;
+            }
+        }
+        return new String[0];
     }
 
     public final class ConsoleIO {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
index 2cd826b8689a3a24251aa967c053f58ca022fa80..e3ca6bcac927d0cf283afb8b0fb05dc11fd8f33f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
@@ -267,7 +267,6 @@ public abstract class ForeignArray2R extends RBaseNode {
         int size = arrayData.elements.size();
 
         int[] dims = arrayData.dims != null && arrayData.dims.size() > 1 ? arrayData.dims.stream().mapToInt((i) -> i.intValue()).toArray() : null;
-        assert dims == null || sizeByDims(dims) == size : sizeByDims(dims) + " " + size;
 
         switch (type) {
             case NONE:
diff --git a/com.oracle.truffle.r.test.tck/src/com/oracle/truffle/r/test/tck/RTCKLanguageProvider.java b/com.oracle.truffle.r.test.tck/src/com/oracle/truffle/r/test/tck/RTCKLanguageProvider.java
index 90561ebb5c8c32bf8e7f87c4beebbab9ee45736c..9e79652192acdda8ac5de6311e4e067a54fffc45 100644
--- a/com.oracle.truffle.r.test.tck/src/com/oracle/truffle/r/test/tck/RTCKLanguageProvider.java
+++ b/com.oracle.truffle.r.test.tck/src/com/oracle/truffle/r/test/tck/RTCKLanguageProvider.java
@@ -143,6 +143,7 @@ public final class RTCKLanguageProvider implements LanguageProvider {
         ops.add(createBinaryOperator(context, "/", numOrBoolOrArrNumBool, numOrBoolOrNullOrArrNumBool, numOrBoolOrNullOrArrNumBool,
                         RResultVerifier.newBuilder(numOrBoolOrNullOrArrNumBool, numOrBoolOrNullOrArrNumBool).emptyArrayCheck().build()));
 
+        // TODO cause occasional and more then accasional fails on gate builds
         // <
         // ops.add(createBinaryOperator(context, "<", boolOrArrBool, strOrNumOrBoolOrArrStrNumBool,
         // strOrNumOrBoolOrArrStrNumBool,
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 38955f0d5d51209d884f310d4dc15a09ec383c31..28e719055c235dd5c8ca7d1063e7c0edaeee97f6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -148283,16 +148283,18 @@ NULL
 [1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
-#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(1) : unsupported type', '<<<NEWLINE>>>') } else { java.class(1) }
-Error in java.class(1) : unsupported type
+#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(1) : unsupported type java.lang.Double', '<<<NEWLINE>>>') } else { java.class(1) }
+Error in java.class(1) : unsupported type java.lang.Double
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
-#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(NULL) : unsupported type', '<<<NEWLINE>>>') } else { java.class(NULL) }
-Error in java.class(NULL) : unsupported type
+#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(NULL) :', '<<<NEWLINE>>>', ' unsupported type com.oracle.truffle.r.runtime.data.RNull', '<<<NEWLINE>>>') } else { java.class(NULL) }
+Error in java.class(NULL) :
+  unsupported type com.oracle.truffle.r.runtime.data.RNull
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
-#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(to$methodReturnsNull()) : unsupported type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));java.class(to$methodReturnsNull()) }
-Error in java.class(to$methodReturnsNull()) : unsupported type
+#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(to$methodReturnsNull()) :', '<<<NEWLINE>>>', ' unsupported type com.oracle.truffle.r.runtime.data.RNull', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));java.class(to$methodReturnsNull()) }
+Error in java.class(to$methodReturnsNull()) :
+  unsupported type com.oracle.truffle.r.runtime.data.RNull
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIdentical#
 #if (!any(R.version$engine == "FastR")) { FALSE } else { b1 <- as.external.byte(1); b2 <- as.external.byte(1); identical(b1, b2) }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index a48f99ef1321e44a58d58491625b9420d9f1818e..c9436739bc2e8270d04065925f01259a5a223d19 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -247,9 +247,9 @@ public class TestJavaInterop extends TestBase {
     public void testGetClass() {
         assertEvalFastR(CREATE_TRUFFLE_OBJECT + "java.class(to)", "'com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'");
 
-        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "java.class(to$methodReturnsNull())", errorIn("java.class(to$methodReturnsNull())", "unsupported type"));
-        assertEvalFastR("java.class(NULL)", errorIn("java.class(NULL)", "unsupported type"));
-        assertEvalFastR("java.class(1)", errorIn("java.class(1)", "unsupported type"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "java.class(to$methodReturnsNull())", errorIn("java.class(to$methodReturnsNull())", "unsupported type com.oracle.truffle.r.runtime.data.RNull"));
+        assertEvalFastR("java.class(NULL)", errorIn("java.class(NULL)", "unsupported type com.oracle.truffle.r.runtime.data.RNull"));
+        assertEvalFastR("java.class(1)", errorIn("java.class(1)", "unsupported type java.lang.Double"));
     }
 
     @Test
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 100cb2cf768764ba0bb0c3975809c57fd4cc3398..7b0d3d3e6faed594cd935beb1abb230ed702db62 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -953,3 +953,21 @@ com.oracle.truffle.r.native/gnur/patch/src/nmath/nmath.h,no.copyright
 com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h,no.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java,no.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java,no.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/ArrayDimensionException.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/ArrayWrapper.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/DummyPoint.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/FlatException.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/Makefile,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/NotAnArrayException.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/NotComparableException.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/ObjectArrayException.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/PrimitiveArrayException.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayIterator.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RJavaArrayTools.java,rjava_romain.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RJavaClassLoader.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RJavaComparator.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RJavaImport.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RJavaTools.java,rjava_romain.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayBuilder.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArrayExamples.java,rjava.copyright
+com.oracle.truffle.r.pkgs/rJava/src/java/RectangularArraySummary.java,rjava.copyright
\ No newline at end of file
diff --git a/mx.fastr/copyrights/rjava.copyright.hash b/mx.fastr/copyrights/rjava.copyright.hash
new file mode 100644
index 0000000000000000000000000000000000000000..9e3b79043d75b8c32b937a85630cf9b0ceccd738
--- /dev/null
+++ b/mx.fastr/copyrights/rjava.copyright.hash
@@ -0,0 +1,10 @@
+##
+ # This material is distributed under the GNU General Public License
+ # Version 2. You may review the terms of this license at
+ # http://www.gnu.org/licenses/gpl-2.0.html
+ #
+ # Copyright (c) 2006, Simon Urbanek
+ # Copyright (c) 2018, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
diff --git a/mx.fastr/copyrights/rjava.copyright.hash.regex b/mx.fastr/copyrights/rjava.copyright.hash.regex
new file mode 100644
index 0000000000000000000000000000000000000000..c20f92dbc17b5a9ff1aa828011be693afb3843de
--- /dev/null
+++ b/mx.fastr/copyrights/rjava.copyright.hash.regex
@@ -0,0 +1 @@
+##\n # This material is distributed under the GNU General Public License\n # Version 2. You may review the terms of this license at\n # http://www.gnu.org/licenses/gpl-2.0.html\n #\n # Copyright \(c\) 2006, Simon Urbanek\n # Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates\n #\n # All rights reserved.\n##\n.*
\ No newline at end of file
diff --git a/mx.fastr/copyrights/rjava.copyright.star b/mx.fastr/copyrights/rjava.copyright.star
new file mode 100644
index 0000000000000000000000000000000000000000..21d71837814993fe3c6f5ad0425fee8c58c1fde8
--- /dev/null
+++ b/mx.fastr/copyrights/rjava.copyright.star
@@ -0,0 +1,10 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2006, Simon Urbanek
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
diff --git a/mx.fastr/copyrights/rjava.copyright.star.regex b/mx.fastr/copyrights/rjava.copyright.star.regex
new file mode 100644
index 0000000000000000000000000000000000000000..40ec1b6bfc0a660f1d4355e816cb333cb06f392a
--- /dev/null
+++ b/mx.fastr/copyrights/rjava.copyright.star.regex
@@ -0,0 +1 @@
+/\*\n \* This material is distributed under the GNU General Public License\n \* Version 2. You may review the terms of this license at\n \* http://www.gnu.org/licenses/gpl-2.0.html\n \*\n \* Copyright \(c\) 2006, Simon Urbanek\n \* Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates\n \*\n \* All rights reserved.\n \*/\n.*
\ No newline at end of file
diff --git a/mx.fastr/copyrights/rjava_romain.copyright.star b/mx.fastr/copyrights/rjava_romain.copyright.star
new file mode 100644
index 0000000000000000000000000000000000000000..e9d81b3a1c797033882ffbcc62568b9e837ba71e
--- /dev/null
+++ b/mx.fastr/copyrights/rjava_romain.copyright.star
@@ -0,0 +1,10 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2009-2010, Simon Urbanek and Romain Francois
+ * Copyright (c) 2018, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
\ No newline at end of file
diff --git a/mx.fastr/copyrights/rjava_romain.copyright.star.regex b/mx.fastr/copyrights/rjava_romain.copyright.star.regex
new file mode 100644
index 0000000000000000000000000000000000000000..98390228623fb0ab663e87077fa7207d78ae522a
--- /dev/null
+++ b/mx.fastr/copyrights/rjava_romain.copyright.star.regex
@@ -0,0 +1 @@
+/\*\n \* This material is distributed under the GNU General Public License\n \* Version 2. You may review the terms of this license at\n \* http://www.gnu.org/licenses/gpl-2.0.html\n \*\n \* Copyright \(c\) (?:(20[0-9][0-9])-)?(20[0-9][0-9]), Simon Urbanek and Romain Francois\n \* Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates\n \*\n \* All rights reserved.\n \*/\n.*
\ No newline at end of file