Javaとの相互運用性
GraalVM Rランタイムでは、Javaとの組込みの相互運用性が提供されます。Javaクラス・オブジェクトは、java.type(...)
を介して取得できます。Javaとの相互運用性機能を使用してRを実行するには、--jvm
オプションを指定してR
またはRscript
コマンドを起動する必要があります。
R --jvm
ノート: この後の例はすべて、R REPLで実行することを目的としています。追加のJava依存性は必要ありません。
- 標準の
new
関数は、String引数をJavaクラスとして解釈します(そのようなクラスが存在する場合)。 new
は、java.type
から返されたJava型も受け入れます。- Javaオブジェクトのフィールドおよびメソッドには、
$
演算子を使用してアクセスできます。 - また、
awt(...)
を使用すると、Java GraphicsサーフェスでR描画デバイスを直接開くことができます。詳細は、「Java Graphicsとの相互運用性」を参照してください。
次の例では、新しいJava BufferedImage
オブジェクトを作成し、Rのgrid
パッケージを使用してそれにランダム・データをプロットし、JavaのAWT
フレームワークを使用してウィンドウにイメージを表示します。Javaとの相互運用性機能を使用するには、--jvm
を指定してRスクリプトを開始する必要があります。
library(grid)
openJavaWindow <- function () {
# create image and register graphics
imageClass <- java.type('java.awt.image.BufferedImage')
image <- new(imageClass, 450, 450, imageClass$TYPE_INT_RGB);
graphics <- image$getGraphics()
graphics$setBackground(java.type('java.awt.Color')$white);
grDevices:::awt(image$getWidth(), image$getHeight(), graphics)
# draw image
grid.newpage()
pushViewport(plotViewport(margins = c(5.1, 4.1, 4.1, 2.1)))
grid.xaxis(); grid.yaxis()
grid.points(x = runif(10, 0, 1), y = runif(10, 0, 1),
size = unit(0.01, "npc"))
# open frame with image
imageIcon <- new("javax.swing.ImageIcon", image)
label <- new("javax.swing.JLabel", imageIcon)
panel <- new("javax.swing.JPanel")
panel$add(label)
frame <- new("javax.swing.JFrame")
frame$setMinimumSize(new("java.awt.Dimension",
image$getWidth(), image$getHeight()))
frame$add(panel)
frame$setVisible(T)
while (frame$isVisible()) Sys.sleep(1)
}
openJavaWindow()
GraalVMのRランタイムには、GitHubで入手可能な独自のrJava互換の置換パッケージが用意されており、次を使用してインストールできます:
R -e "install.fastr.packages('rJava')"
サード・パーティのJavaライブラリにアクセスするには、それらをRのクラスパスに配置する必要があります:
> java.addToClasspath("/foo/bar.jar")
> java.addToClasspath(c("/foo/bar.jar", "/foo/bar2.jar"))
Javaクラスの取得
Java型へのアクセスを確立するには、java.type
関数に完全修飾クラス名を指定します:
> calendarClass <- java.type('java.util.GregorianCalendar')
返される値は、Java型を表すポリグロット・オブジェクトです。
その後、class
プロパティを介してそれぞれのJavaクラスを使用できます:
> calendarClass$class
同じことが静的クラス・メンバーにも機能します:
> calendarClass$getInstance()
要求したそれぞれのクラスがRのクラスパスに存在する必要があります。上で使用したGregorianCalendar
などのJDKクラスは即時利用可能です。
新しいJavaオブジェクトの作成
新しいJavaオブジェクトを作成するには、new
関数にJava型を指定します:
> calendar <- new(calendarClass)
追加のコンストラクタ引数を渡すこともできます:
> calendar <- new(calendarClass, year=2042L, moth=3L, day=1L)
また、クラス名のみを使用することもできます:
calendar <- new("java.util.GregorianCalendar")
calendar <- new("java.util.GregorianCalendar", year=2042L, moth=3L, day=1L)
フィールドおよびメソッドへのアクセス
静的フィールドおよびメソッドとインスタンス・フィールドおよびメソッドへのアクセスは、$
および[
演算子によって提供されます。
Javaフィールドにアクセスするには:
> calendarClass$SUNDAY
> calendarClass["SUNDAY"]
Javaメソッドを起動するには:
> currentTime <- calendar$getTime()
> currentTime["toString"]()
> calendar$setTime(currentTime)
フィールドまたはメソッドから返された、あるいはnew
を介して作成されたポリグロット・オブジェクトは、対応するR値に自動的に変換されるか、GraalVM Rランタイムにポリグロット・オブジェクトとして存続します。必要に応じて、それらをJavaに渡すことができます:
> cet <- java.type("java.util.TimeZone")$getTimeZone("CET")
> cetCalendar <- new(calendarClass, cet)
Javaプリミティブの処理
返されたJavaプリミティブ、プリミティブ・ラッパーおよびStringインスタンスは、対応するR値に自動的に変換され、次のようにマップされます:
- Rの
integer
値はJavaのint
/Integer
に直接マップされます - Rの
numeric
はJavaのdouble
/Double
に - Rの
logical
はJavaのboolean
/Boolean
に - Rの
character
はJavaのString
に - 必要に応じて、Rの
integer
およびdouble
は必要なJava型に変換されます
ポリグロット・オブジェクトの検査
names
関数を使用して、ポリグロットJavaオブジェクトまたはJavaクラスからインスタンス・メンバーおよび静的メンバーのリストを取得できます:
> names(calendar)
> names(calendarClass)
コード補完も機能します:
> calendar$a<TAB>
Java配列の操作
Java配列の必要性が生じるのは、それらを引数としてjava
に渡す必要がある場合です。
配列を作成するには、配列クラスを作成し、そこから配列をインスタンス化します:
> arrayClass <- java.type('int[]')
> intArray <- new(arrayClass, 3)
プリミティブ配列のコンポーネントの型名は、boolean
、byte
、char
、double
、float
、int
、long
およびshort
で、それぞれの特定のプリミティブ・ラッパーのTYPE定数と同じです(Integer.TYPE.getName()
などを参照)。予想されるJava配列がプリミティブ・コンポーネント型またはStringである場合は、RベクターをJavaメソッドに渡すことができます。その後、バックグラウンドで自動的に変換が行われます。
> integerArray <- new(java.type('java.lang.Integer[]'), 3L)
> integer2DimArray <- new('java.lang.Integer[][]', c(2L, 3L))
> stringArray <- new(java.type('java.lang.String[]'), 3L)
配列要素へのアクセスは、[
演算子によって提供されます:
> stringArray[1] <- 'a'
> string2DimArray[1,1] <- 'a'
> element <- stringArray[1]
> element <- string2DimArray[1,1]
RオブジェクトへのJava配列の変換
Javaプリミティブやそのラッパーとは異なり、Java配列は自動的にRベクターに変換されません。ただし、適切な場合は、R組込み関数によってネイティブのRオブジェクトと同様にそれらを処理できます:
> sapply(intArray, function(e) { e })
> length(stringArray)
> length(string2DimArray[1])
明示的なJava配列の変換
Java配列の変換を明示的に行うには、as.vector
関数にJava配列を指定します:
> intVec <- as.vector(intArray)
Javaプリミティブ・コンポーネント型を持つ配列は、Rベクターに変換されます。それ以外の場合は、配列要素を含むリストが作成されます:
> characterVector <- as.character(intArray)
> logicalVector <- as.logical(intArray)
> ...
Javaの反復可能インタフェース
適切な場合、java.lang.Iterable
を実装するJavaオブジェクトは、引数として関数に渡されたときにJava配列と同様に処理されます:
> javaList <- new(java.type('java.util.ArrayList'))
> javaList$add(0);
> javaList$add(1)
> length(javaList)
> as.integer(javaList)
> as.logical(javaList)
rJavaとの互換性
GraalVM Rランタイムには、Javaとの相互運用性機能に基づくrJava互換性レイヤーが付属しています。公式に文書化されたrJava関数のほとんどがサポートされています。詳細は、rJavaのCRANドキュメントを参照してください。
install.packages("rJava")
を使用して、GraalVM RランタイムのrJava
置換をインストールできます。Rのinstall.packages
関数には、rJava
を含む一部のパッケージについて特殊な処理があり、MRANからではなくGitHubのソース・リポジトリからrJavaがダウンロードされます。- 他のRパッケージと同様に、rJava関数を実行する前に、パッケージを最初にロードする必要があります:
> library(rJava)
サポートされているrJava機能:
$
および[
演算子は、前述と同じように機能します。
Java Graphicsとの相互運用性
GraalVM Rランタイムには、grid
パッケージと、png
、jpeg
、bmp
、svg
およびawt
(X11
はawt
に別名設定されます)グラフィック・デバイスの独自のJavaベース実装が含まれています。graphics
パッケージとその関数のほとんどは現時点ではサポートされていません。
awt
デバイスはJava Graphics2D
オブジェクトに基づいており、ユーザーは、Javaとの相互運用性の例に示されているように、awt
関数を使用してデバイスを開くときに独自のGraphics2D
オブジェクト・インスタンスにそれを渡すことができます。Graphics2D
オブジェクトがawt
に提供されない場合は、X11
のような新しいウィンドウが開きます。
GraalVM Rランタイムのsvg
デバイスでは、GNU Rのsvg
実装よりも軽量なSVGコードが生成されます。さらに、SVGデバイスを操作するために調整された関数svg.off
およびsvg.string
が用意されています。次のコード・サンプルにSVGデバイスを示します:
library(lattice)
svg()
mtcars$cars <- rownames(mtcars)
print(barchart(cars~mpg, data=mtcars))
svgCode <- svg.off()
cat(svgCode)
さらに学習するには、?functionName
構文を参照してください。