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 ac9d5aa0bc70311575eb482b5521b1207fb2f4fa..938bee74e62f37f18dc335788f6ada2609f2ede4 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
@@ -371,8 +371,10 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create);
         add(FastRInterop.HasSize.class, FastRInteropFactory.HasSizeNodeGen::create);
         add(FastRInterop.Import.class, FastRInteropFactory.ImportNodeGen::create);
+        add(FastRInterop.InteropNew.class, FastRInteropFactory.InteropNewNodeGen::create);
         add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create);
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
+        add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
         add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create);
         add(FastRPkgSource.class, FastRPkgSourceNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 333055b1fb03ab4daf7c57182cd0935444466624..e8b5fdc22fef6506438b79306cdda20f8f1e8951 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -1360,12 +1360,10 @@ public abstract class ConnectionFunctions {
                     ByteChannel ch = JavaInterop.asJavaObject(ByteChannel.class, channel);
                     return new ChannelRConnection("", ch, open, encoding).asVector();
                 }
-                throw error(RError.Message.INVALID_CHANNEL_OBJECT, JavaInterop.unbox(channel).getClass());
+                throw error(RError.Message.INVALID_CHANNEL_OBJECT);
             } catch (IOException ex) {
                 throw RInternalError.shouldNotReachHere();
             }
         }
-
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index bb8b0830c7506c448902790900a4480c8fdd82de..cbce750d0918da1af2b72833f68f41a90336de89 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -27,17 +27,27 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
+@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 @RBuiltin(name = "names", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class Names extends RBuiltinNode {
 
@@ -64,6 +74,35 @@ public abstract class Names extends RBuiltinNode {
         return env.ls(true, null, false);
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected Object getNames(TruffleObject obj,
+                    @Cached("GET_SIZE.createNode()") Node getSizeNode,
+                    @Cached("KEYS.createNode()") Node keysNode,
+                    @Cached("READ.createNode()") Node readNode,
+                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
+                    @Cached("UNBOX.createNode()") Node unboxNode) {
+
+        try {
+            TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
+            if (keys != null) {
+                int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
+                String[] names = new String[size];
+                for (int i = 0; i < size; i++) {
+                    Object value;
+                    value = ForeignAccess.sendRead(readNode, keys, i);
+                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
+                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
+                    }
+                    names[i] = (String) value;
+                }
+                return RDataFactory.createStringVector(names, true);
+            }
+            return RNull.instance;
+        } catch (InteropException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        }
+    }
+
     @Fallback
     protected RNull getNames(@SuppressWarnings("unused") Object operand) {
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 5b86993957b17f1caaee84eab20fc9d3a8471eca..25e8d6eaeb611ef3abc24680873cde862e2e4cf3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
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 90f93075889b3d4d08d7db5c15b0bddc1d3bf75b..fcc48d956d3e48d6b64105079cc0d80038ddc58d 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
@@ -40,9 +40,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+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.source.Source;
@@ -55,9 +60,15 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class FastRInterop {
 
@@ -250,4 +261,73 @@ public class FastRInterop {
             return value;
         }
     }
+
+    @RBuiltin(name = ".fastr.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX)
+    public abstract static class JavaClass extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(JavaClass.class);
+            casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public TruffleObject javaClass(String clazz) {
+            try {
+                return JavaInterop.asTruffleObject(Class.forName(clazz));
+            } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) {
+                throw error(Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+    }
+
+    @ImportStatic({com.oracle.truffle.api.interop.Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
+    public abstract static class InteropNew extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(InteropNew.class);
+        }
+
+        private static Object toJava(Object value) {
+            Object vector = RRuntime.asAbstractVector(value);
+            if (vector instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) vector).getLength() == 1) {
+                if (vector instanceof RAbstractDoubleVector) {
+                    RAbstractDoubleVector v = (RAbstractDoubleVector) vector;
+                    return v.getDataAt(0);
+                } else if (vector instanceof RAbstractLogicalVector) {
+                    RAbstractLogicalVector v = (RAbstractLogicalVector) vector;
+                    return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
+                } else if (vector instanceof RAbstractRawVector) {
+                    RAbstractRawVector v = (RAbstractRawVector) vector;
+                    return v.getDataAt(0).getValue();
+                } else if (vector instanceof RAbstractStringVector) {
+                    RAbstractStringVector v = (RAbstractStringVector) vector;
+                    return v.getDataAt(0);
+                }
+            }
+            return value;
+        }
+
+        @Specialization(limit = "99", guards = {"isForeignObject(clazz)", "length == args.getLength()"})
+        @TruffleBoundary
+        public Object interopNew(TruffleObject clazz, RArgsValuesAndNames args,
+                        @SuppressWarnings("unused") @Cached("args.getLength()") int length,
+                        @Cached("createNew(length).createNode()") Node sendNew) {
+            try {
+                Object[] argValues = new Object[args.getLength()];
+                for (int i = 0; i < argValues.length; i++) {
+                    argValues[i] = toJava(args.getArgument(i));
+                }
+                return ForeignAccess.sendNew(sendNew, clazz, argValues);
+            } catch (SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
+                throw error(Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
+            }
+        }
+
+        @Fallback
+        public Object interopNew(@SuppressWarnings("unused") Object clazz, @SuppressWarnings("unused") Object args) {
+            throw error(Message.GENERIC, "interop object needed as receiver of NEW message");
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index b79bd831270de1056e75d0f899a33d6e43fcdf64..3268b3bd7628561656dd61a7cae16fc56f90d46f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -60,7 +60,6 @@ import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * <p>
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 72ab6fa32cf256222a315ac3d2f38419ccdfc8cb..38f80bcd6a4e9651ff0e4135b632380de2cc7a48 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
@@ -855,7 +855,7 @@ public final class RError extends RuntimeException {
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
         TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"),
         INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded"),
-        INVALID_CHANNEL_OBJECT("invalid channel object type: %s"),
+        INVALID_CHANNEL_OBJECT("invalid channel object (ByteChannel expected)"),
         INVALID_TAG("invalid tag"),
         INVALID_VARIABLE_NAMES("invalid variable names"),
         INVALID_EXPRESSION("invalid expression in '%s'"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 82eec933b6800e081b3dc4856878d4cbe6fc274d..e0d3de69805cc1ae9818feff2efeba042e25f70e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
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 47a9ac5e75d203d2058a781d31adb8a86117b586..eca54bee2cc810c911c12e0855fdc6af835b5d44 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
@@ -129769,6 +129769,11 @@ a b c d e
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', new.env()) }
 
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue') } else { v <- .fastr.interop.import('testPOJO'); names(v) }
+[1] "intValue"     "longValue"    "charValue"    "shortValue"   "booleanValue"
+[6] "stringValue"
+
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testPOJO'); print(v) }
 $intValue
@@ -129838,22 +129843,6 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); 3 * (unit(1, 'mm')); }
-[1] 3*1mm
-
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); grid:::unit.list(3 * unit(1, 'mm')); }
-[1] 3*1mm
-
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); unit.c(unit(1,'mm'), 42*unit(1,'mm')); }
-[1] 1mm    42*1mm
-
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); unit.c(unit(1,'mm'), unit(1,'mm')) }
-[1] 1mm 1mm
-
 ##com.oracle.truffle.r.test.library.methods.TestSubstituteDirect.basicTests#
 #a<-substituteDirect(quote(x+1), NA); a
 Error in substituteDirect(quote(x + 1), NA) :
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index 2250149cb2075b762143b4d249ff3d3c5a5ddc6c..35c727bf15d4abd98cd9527133e1d26b7cee275e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,5 +118,6 @@ public class TestInterop extends TestBase {
         assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[1]   1  -5 199\\n" +
                         "attr(,\"is.truffle.object\")\\n" +
                         "[1] TRUE\\n')");
+        assertEvalFastR("v <- .fastr.interop.import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')");
     }
 }