diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index c3de2199322aa65b8a7d6d0c9beb35aafcc30503..0cf2cec1a7b4ff575a71ba46cabadb79aff66f8e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -124,7 +124,7 @@ public abstract class ExtractVectorNode extends Node {
                 // TODO implicite unboxing ok? method calls seem to behave this way
                 Object result = object;
                 for (int i = 0; i < positions.length; i++) {
-                    result = send(positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
+                    result = read(this, positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
                     if (positions.length > 1 && i < positions.length - 1) {
                         assert result instanceof TruffleObject;
                     }
@@ -151,7 +151,8 @@ public abstract class ExtractVectorNode extends Node {
         return RRuntime.java2R(obj);
     }
 
-    private Object send(Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode) throws RError, InteropException {
+    public static Object read(Node caller, Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode)
+                    throws RError, InteropException {
         if (position instanceof Integer) {
             position = ((int) position) - 1;
         } else if (position instanceof Double) {
@@ -163,7 +164,7 @@ public abstract class ExtractVectorNode extends Node {
         } else if (position instanceof RAbstractStringVector) {
             position = firstString.executeString(castNode.doCast(position));
         } else if (!(position instanceof String)) {
-            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+            throw RError.error(caller, RError.Message.GENERIC, "invalid index during foreign access");
         }
 
         int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
@@ -176,7 +177,7 @@ public abstract class ExtractVectorNode extends Node {
                 return ForeignAccess.sendRead(foreignRead, clazz, position);
             }
         }
-        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+        throw RError.error(caller, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
     }
 
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"})
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index 5c4fa8b7749708527f3d6d0b2f23354e79fe3743..77ce1d830a852c0c6074d374f4ef396aee94ef4d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -100,20 +100,25 @@ public abstract class ReplaceVectorNode extends Node {
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, Object value,
                     @Cached("WRITE.createNode()") Node foreignWrite,
+                    @Cached("READ.createNode()") Node foreignRead,
                     @Cached("KEY_INFO.createNode()") Node keyInfo,
                     @SuppressWarnings("unused") @Cached("positions.length") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString) {
         Object writtenValue = RRuntime.r2Java(value);
-        Object position = positions[0];
         try {
-            return write(position, foreignWrite, keyInfo, object, writtenValue, firstString, castNode);
+            TruffleObject result = object;
+            for (int i = 0; i < positions.length - 1; i++) {
+                result = (TruffleObject) ExtractVectorNode.read(this, positions[i], foreignRead, keyInfo, result, firstString, castNode);
+            }
+            write(positions[positions.length - 1], foreignWrite, keyInfo, result, writtenValue, firstString, castNode);
+            return object;
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
-    private Object write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
+    private void write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
                     throws InteropException, RError {
         if (position instanceof Integer) {
             position = ((Integer) position) - 1;
@@ -132,12 +137,14 @@ public abstract class ReplaceVectorNode extends Node {
 
         int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
         if (KeyInfo.isWritable(info)) {
-            return ForeignAccess.sendWrite(foreignWrite, object, position, writtenValue);
+            ForeignAccess.sendWrite(foreignWrite, object, position, RRuntime.r2Java(writtenValue));
+            return;
         } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
             TruffleObject clazz = JavaInterop.toJavaClass(object);
             info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
             if (KeyInfo.isWritable(info)) {
-                return ForeignAccess.sendWrite(foreignWrite, clazz, position, writtenValue);
+                ForeignAccess.sendWrite(foreignWrite, clazz, position, RRuntime.r2Java(writtenValue));
+                return;
             }
         }
         throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
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 3f97cdba2b2cc4d11fecba065e9fc9892a9b84a2..c700f6b474620a0bc5151920c9259f33a5920e76 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
@@ -130536,51 +130536,71 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1]; }
 [1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]]; }
 [1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] }
 [1] 123
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] }
 [1] 123
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]] }
 [1] 1234
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2] }
 [1] 1234
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 12345 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]] }
+[1] 12345
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] }
 [1] 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] }
 [1] 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1] }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1] }
 [1] 1 2 3
 attr(,"is.truffle.object")
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]] }
 [1] 1 2 3
 attr(,"is.truffle.object")
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$classAsArg(tc) }
 [1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
 
@@ -131238,11 +131258,15 @@ NULL
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$equals(t) }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) {  } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.Long } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull(1) }
 Error: object 'java.lang.Long' not found
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull('string') }
 Error: object 'java.lang.String' not found
 
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 aa9ffbca00e9167da465144ebddbbf221528b70d..0997d603ee8d5b361ee38ac003ee33fa13cb8362 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
@@ -32,12 +32,22 @@ import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel;
 import com.oracle.truffle.r.test.TestBase;
+import java.io.File;
+import org.junit.After;
 
 public class TestInterop extends TestBase {
 
     private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel();
     private static final String CHANNEL_NAME = "_fastr_channel0";
 
+    @After
+    public void cleanup() {
+        File f = new File("testScript.R");
+        if (f.exists()) {
+            f.delete();
+        }
+    }
+
     @Test
     public void testInteropEval() {
         assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16");
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 583f289e9893ebdc64d543c1a9ba5708dcf4a734..05db254460ed61f551c61cb87e6f2fc1bcc1c1ba 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
@@ -32,6 +32,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
+import org.junit.Assert;
 
 public class TestJavaInterop extends TestBase {
 
@@ -259,8 +260,7 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testClassAsParameter() {
-        // needs to be implemented in truffle
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
     }
 
     private void getValueForAllTypesMethod(String method) {
@@ -278,7 +278,9 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testNullParameter() {
+    public void testNullParameters() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL)", "");
+
         assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull('string')", "java.lang.String");
         assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull(1)", "java.lang.Long");
     }
@@ -291,18 +293,38 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testArrayAccess() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1]", getRValue(new int[]{1, 2, 3}));
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]]", getRValue(new int[]{1, 2, 3}));
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2]", "2");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]]", "2");
-
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1]", "123");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]]", "123");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2]", "1234");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]]", "1234");
+    public void testArrayReadWrite() {
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1]", "1");
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]]", "1");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1];", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]];", "1");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2]", "2");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]]", "2");
+
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1]", "123");
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]]", "123");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1]", "123");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]]", "1234");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1]", "NULL");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2]", "1234");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]]", "12345");
+    }
+
+    public void testMap() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']", "'1'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['two']", "'2'");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']<-'11'; m['one']", "'11'");
+
+        // truffle
+        assertEvalFastR(Ignored.Unimplemented, "how to put into map?", "'11'");
     }
 
     @Test
@@ -406,56 +428,53 @@ public class TestJavaInterop extends TestBase {
 
     public static class TestClass {
 
-        public static boolean fieldStaticBoolean = true;
-        public static byte fieldStaticByte = Byte.MAX_VALUE;
-        public static char fieldStaticChar = 'a';
-        public static short fieldStaticShort = Short.MAX_VALUE;
-        public static int fieldStaticInteger = Integer.MAX_VALUE;
-        public static long fieldStaticLong = Long.MAX_VALUE;
-        public static double fieldStaticDouble = Double.MAX_VALUE;
-        public static float fieldStaticFloat = Float.MAX_VALUE;
-
-        public static Boolean fieldStaticBooleanObject = fieldStaticBoolean;
-        public static Byte fieldStaticByteObject = fieldStaticByte;
-        public static Character fieldStaticCharObject = fieldStaticChar;
-        public static Short fieldStaticShortObject = fieldStaticShort;
-        public static Integer fieldStaticIntegerObject = fieldStaticInteger;
-        public static Long fieldStaticLongObject = fieldStaticLong;
-        public static Double fieldStaticDoubleObject = fieldStaticDouble;
-        public static Float fieldStaticFloatObject = fieldStaticFloat;
-        public static String fieldStaticStringObject = "a string";
-
-        public boolean fieldBoolean = fieldStaticBoolean;
-        public byte fieldByte = fieldStaticByte;
-        public char fieldChar = fieldStaticChar;
-        public short fieldShort = fieldStaticShort;
-        public int fieldInteger = fieldStaticInteger;
-        public long fieldLong = fieldStaticLong;
-        public double fieldDouble = fieldStaticDouble;
-        public float fieldFloat = fieldStaticFloat;
-
-        public Boolean fieldBooleanObject = fieldBoolean;
-        public Byte fieldByteObject = fieldByte;
-        public Character fieldCharObject = fieldChar;
-        public Short fieldShortObject = fieldShort;
-        public Integer fieldIntegerObject = fieldInteger;
-        public Long fieldLongObject = fieldLong;
-        public Double fieldDoubleObject = fieldDouble;
-        public Float fieldFloatObject = fieldFloat;
-        public String fieldStringObject = fieldStaticStringObject;
-
-        public static Double fieldStaticNaNObject = Double.NaN;
-        public static double fieldStaticNaN = Double.NaN;
-
-        public static boolean[] fieldStaticBooleanArray = new boolean[]{true, false, true};
-        public static byte[] fieldStaticByteArray = new byte[]{1, 2, 3};
-        public static char[] fieldStaticCharArray = new char[]{'a', 'b', 'c'};
-        public static double[] fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
-        public static float[] fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
-        public static int[] fieldStaticIntArray = new int[]{1, 2, 3};
-        public static long[] fieldStaticLongArray = new long[]{1, 2, 3};
-        public static short[] fieldStaticShortArray = new short[]{1, 2, 3};
-        public static String[] fieldStaticStringArray = new String[]{"a", "b", "c"};
+        public static boolean fieldStaticBoolean;
+        public static byte fieldStaticByte;
+        public static char fieldStaticChar;
+        public static short fieldStaticShort;
+        public static int fieldStaticInteger;
+        public static long fieldStaticLong;
+        public static double fieldStaticDouble;
+        public static float fieldStaticFloat;
+
+        public static Boolean fieldStaticBooleanObject;
+        public static Byte fieldStaticByteObject;
+        public static Character fieldStaticCharObject;
+        public static Short fieldStaticShortObject;
+        public static Integer fieldStaticIntegerObject;
+        public static Long fieldStaticLongObject;
+        public static Double fieldStaticDoubleObject;
+        public static Float fieldStaticFloatObject;
+        public static String fieldStaticStringObject;
+
+        public boolean fieldBoolean;
+        public byte fieldByte;
+        public char fieldChar;
+        public short fieldShort;
+        public int fieldInteger;
+        public long fieldLong;
+        public double fieldDouble;
+        public float fieldFloat;
+
+        public Boolean fieldBooleanObject;
+        public Byte fieldByteObject;
+        public Character fieldCharObject;
+        public Short fieldShortObject;
+        public Integer fieldIntegerObject;
+        public Long fieldLongObject;
+        public Double fieldDoubleObject;
+        public Float fieldFloatObject;
+        public String fieldStringObject;
+
+        public static boolean[] fieldStaticBooleanArray;
+        public static byte[] fieldStaticByteArray;
+        public static char[] fieldStaticCharArray;
+        public static double[] fieldStaticDoubleArray;
+        public static float[] fieldStaticFloatArray;
+        public static int[] fieldStaticIntArray;
+        public static long[] fieldStaticLongArray;
+        public static short[] fieldStaticShortArray;
+        public static String[] fieldStaticStringArray;
 
         public boolean[] fieldBooleanArray = fieldStaticBooleanArray;
         public byte[] fieldByteArray = fieldStaticByteArray;
@@ -467,16 +486,21 @@ public class TestJavaInterop extends TestBase {
         public short[] fieldShortArray = fieldStaticShortArray;
         public String[] fieldStringArray = fieldStaticStringArray;
 
-        public int[][] int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}};
-        public Object[] objectArray = new Object[]{new Object(), new Object(), new Object()};
-        public Object[] objectIntArray = new Object[]{1, 2, 3};
-        public Object[] objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
-        public Object[] mixedTypesArray = new Object[]{1, 2.1, 'a'};
-        public Integer[] hasNullIntArray = new Integer[]{1, null, 3};
+        public int[][] int2DimArray;
+        public Object[] objectArray;
+        public Object[] objectIntArray;
+        public Object[] objectDoubleArray;
+        public Object[] mixedTypesArray;
+        public Integer[] hasNullIntArray;
+
+        public static Double fieldStaticNaNObject = Double.NaN;
+        public static double fieldStaticNaN = Double.NaN;
 
         public static Object fieldStaticNullObject = null;
         public Object fieldNullObject = null;
 
+        public Map<String, String> map;
+
         public TestClass() {
             this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, Float.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string");
         }
@@ -519,6 +543,37 @@ public class TestJavaInterop extends TestBase {
             this.fieldDoubleObject = fieldDouble;
             this.fieldFloatObject = fieldFloat;
             this.fieldStringObject = fieldStaticStringObject;
+
+            fieldStaticBooleanArray = new boolean[]{true, false, true};
+            fieldStaticByteArray = new byte[]{1, 2, 3};
+            fieldStaticCharArray = new char[]{'a', 'b', 'c'};
+            fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
+            fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
+            fieldStaticIntArray = new int[]{1, 2, 3};
+            fieldStaticLongArray = new long[]{1, 2, 3};
+            fieldStaticShortArray = new short[]{1, 2, 3};
+            fieldStaticStringArray = new String[]{"a", "b", "c"};
+
+            fieldBooleanArray = fieldStaticBooleanArray;
+            fieldByteArray = fieldStaticByteArray;
+            fieldCharArray = fieldStaticCharArray;
+            fieldDoubleArray = fieldStaticDoubleArray;
+            fieldFloatArray = fieldStaticFloatArray;
+            fieldIntArray = fieldStaticIntArray;
+            fieldLongArray = fieldStaticLongArray;
+            fieldShortArray = fieldStaticShortArray;
+            fieldStringArray = fieldStaticStringArray;
+
+            int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}};
+            objectArray = new Object[]{new Object(), new Object(), new Object()};
+            objectIntArray = new Object[]{1, 2, 3};
+            objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
+            mixedTypesArray = new Object[]{1, 2.1, 'a'};
+            hasNullIntArray = new Integer[]{1, null, 3};
+
+            map = new HashMap<>();
+            map.put("one", "1");
+            map.put("two", "2");
         }
 
         public static boolean methodStaticBoolean() {
@@ -681,6 +736,10 @@ public class TestJavaInterop extends TestBase {
             return null;
         }
 
+        public void methodAcceptsOnlyNull(Object o) {
+            Assert.assertNull(o);
+        }
+
         public String classAsArg(Class<?> c) {
             return c.getName();
         }