diff --git a/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
new file mode 100644
index 0000000000000000000000000000000000000000..22b6b722cc2bf4bf2c7ee8830d129ea8a50f8272
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
@@ -0,0 +1,11 @@
+Package: rJava
+Type: Package
+Title: FastR rJava compatibility layer
+Version: 1.0
+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
diff --git a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
new file mode 100644
index 0000000000000000000000000000000000000000..20c27039014d4fc3a4125f92e4f5960410723234
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
@@ -0,0 +1,16 @@
+# Generated by roxygen2: do not edit by hand
+
+export(.jarray)
+export(.jbyte)
+export(.jcall)
+export(.jchar)
+export(.jcheck)
+export(.jevalArray)
+export(.jfield)
+export(.jfloat)
+export(.jinit)
+export(.jlong)
+export(.jnew)
+export(.jnull)
+export(.jshort)
+export(.jsimplify)
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rj.R b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
new file mode 100644
index 0000000000000000000000000000000000000000..eb18a8713c1f47f2d7739a9fd41cf8bbbc28590d
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
@@ -0,0 +1,119 @@
+##
+ # 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 <- .fastr.java.class(class)
+    o <- .fastr.interop.new(co, ...)
+    invisible(o)
+}
+
+#' @export
+.jcall <- function (obj, returnSig = "V", method, ..., evalArray = TRUE, 
+    evalString = TRUE, check = TRUE, interface = "RcallMethod", 
+    simplify = FALSE, use.true.class = FALSE) 
+{
+    if(is.character(obj)) {
+        co <- .fastr.java.class(obj)
+        r <- co[method](...)
+    } else {
+        r <- obj[method](...)
+    }
+    r
+}
+
+#' @export
+.jfield <- function (obj, sig = NULL, name, true.class = is.null(sig), convert = TRUE) 
+{
+    if(is.character(obj)) {
+        co <- .fastr.java.class(obj)
+        r <- co[name]
+    } else {
+        r <- obj[name]
+    }
+    r    
+}
+
+#' @export
+.jarray <- function (x, contents.class = NULL, dispatch = FALSE) 
+{
+    .fastr.java.toArray(x, ,TRUE)
+}
+
+#' @export
+.jevalArray <- function (x, contents.class = NULL, dispatch = FALSE) 
+{
+    .fastr.java.fromArray(x)
+}
+
+#' @export
+.jbyte <- function (x) 
+{
+    x <- .fastr.interop.toByte(x)
+    invisible(x)
+}
+
+#' @export
+.jchar <- function (x) 
+{
+    x <- .fastr.interop.toChar(x)
+    invisible(x)
+}
+
+#' @export
+.jshort <- function (x) 
+{
+    x <- .fastr.interop.toShort(x)
+    invisible(x)
+}
+
+#' @export
+.jlong <- function (x) 
+{
+    x <- .fastr.interop.toLong(x)
+    invisible(x)
+}
+
+#' @export
+.jfloat <- function (x) 
+{    
+    x <- .fastr.interop.toFloat(x)
+    invisible(x)
+}
+
+#
+# noop stubs
+#
+
+#' @export
+.jinit <- function ()
+{    
+    # do nothing
+}
+
+#' @export
+.jsimplify <- function (x) 
+{    
+    x
+}
+
+#' @export
+.jcheck <- function(silent = FALSE) {
+    FALSE
+}
+
+#' @export
+.jnull <- function (class)
+{    
+    # do nothing
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R
new file mode 100644
index 0000000000000000000000000000000000000000..46b38886ec61b333475eda982a77f68ac0bdd59a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000000000000000000000000000000000000..d0581b43c8330e550bca70c78820096bfb5ad1ff
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
@@ -0,0 +1,102 @@
+# 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
+# - mxbuild/dists/fastr-unit-tests.jar has to be on FastR classpath
+
+library(testthat)
+library(rJava)
+
+testName <- "test .jarray"
+test_that(testName, {
+    cat(paste0(testName, "\n"))
+	
+    a <- .jarray(c(1.1, 2.1, 3.1))
+    expect_true(.fastr.java.isArray(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(.fastr.java.isArray(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(.fastr.java.isArray(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(.fastr.java.isArray(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(.fastr.java.isArray(a))
+    expect_equal(length(a), 1)
+    # fails at the moment
+    # expect_equal(a[1], to)
+
+    to <- .jnew('java.util.ArrayList')
+    a <- .jarray(c(to, to))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 2)
+    # fails at the moment    
+    # expect_equal(a[1], to)
+    # expect_equal(a[2], to)
+
+    a <- .jarray(list(1, 2, 3))
+    expect_true(.fastr.java.isArray(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), 
+        Int=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(.fastr.java.isArray(a), info=paste0("the array was returned for ", fieldName), label=".fastr.java.isArray")
+        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))
+            }
+        }
+    }
+
+})
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R
new file mode 100644
index 0000000000000000000000000000000000000000..72945437d159500915125e077db805376574defe
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R
@@ -0,0 +1,135 @@
+# 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
+# - mxbuild/dists/fastr-unit-tests.jar has to be on FastR classpath
+
+library(testthat)
+library(rJava)
+
+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