In a previous question I asked how to compile R to load it in java using JNI. Compiling libR (from the R statistical package) as a standalone C library for java+jni . Now I can load the libR in java but I get the following R error:
##Trying load RSession
##LOADED !! RSession
RSession.c:Java_RSession_test:15
RSession.c:Java_RSession_initEmbeddedR:21
[0] /path/to/TMP/R-4.3.2/bin/R
[1] --vanilla
[2] --quiet
[3] --encoding=UTF-8
[4] --no-init-file
[5] --no-readline
RSession.c:Java_RSession_initEmbeddedR:35
Error: C stack usage 134897775332 is too close to the limit
Error: C stack usage 134897775380 is too close to the limit
Error: C stack usage 134897775268 is too close to the limit
Fatal error: unable to initialize the JIT
I put a minimal code to reproduce below:
As far as I understand the is a kind of recursion at the R level but I don't know where. There is no .Renviron, .Rprofile, etc in my HOME.
java code:
public class RSession {
// Déclaration des fonctions natives
public static native int initEmbeddedR(int argc, String[] argv);
public static native void endEmbeddedR(int fatal);
public static native void test();
public static void main(String[] args) throws Throwable {
final String R_HOME = System.getenv("R_HOME");
if(R_HOME==null || R_HOME.isEmpty()) {
System.err.println("undefined R_HOME");
System.exit(-1);
}
final String libName= "RSession";
System.err.println("##Trying load "+libName);
try {
System.loadLibrary(libName);
}
catch(Throwable err) {
System.err.println("##Cannot load "+libName);
err.printStackTrace();
System.exit(-1);
}
System.err.println("##LOADED !! "+libName);
test();
String[] argv = {args[0],"--vanilla","--quiet","--encoding=UTF-8","--no-init-file","--no-readline"};
int result = RSession.initEmbeddedR(argv.length, argv);
System.out.println("initEmbeddedR returned result: " + result);
RSession.endEmbeddedR(0);
System.out.println("endEmbeddedR called successfully");
}
}
the following C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Rinternals.h>
#include <Rembedded.h>
#include <R_ext/Parse.h>
#include <jni.h>
#include "RSession.h"
#define WHERE fprintf(stderr,"%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__)
JNIEXPORT void JNICALL Java_RSession_test
(JNIEnv * env, jclass clazz) {
WHERE;
}
JNIEXPORT jint JNICALL Java_RSession_initEmbeddedR(JNIEnv *env, jobject obj, jint argc, jobjectArray argv) {
WHERE;
int i;
int len = (*env)->GetArrayLength(env, argv);
char **args = (char **)malloc(len * sizeof(char *));
for (i = 0; i < len; i++) {
jstring string = (jstring)(*env)->GetObjectArrayElement(env, argv, i);
const char *rawString = (*env)->GetStringUTFChars(env, string, 0);
args[i] = strdup(rawString);
fprintf(stderr,"[%d] %s\n",i,args[i]);
(*env)->ReleaseStringUTFChars(env, string, rawString);
}
WHERE;
int result = Rf_initEmbeddedR(argc, args);
WHERE;
// Libère la mémoire allouée pour les chaînes C
for (i = 0; i < len; i++) {
free(args[i]);
}
free(args);
WHERE;
return result;
}
JNIEXPORT void JNICALL Java_RSession_endEmbeddedR(JNIEnv *env, jobject obj, jint fatal) {
// Appelle la fonction C
WHERE;
Rf_endEmbeddedR(fatal);
WHERE;
}
and compiled and invoked with the following makefile:
SHELL=/bin/bash
CC=gcc
R_VERSION=4.3.2
test: TMP/RSession.class TMP/libRSession.so
echo | R_HOME=${PWD}/TMP/lib/R PATH=$${PATH}:{PWD}/TMP/R-$(R_VERSION)/bin java -Djava.library.path=${PWD}/TMP:TMP/R-$(R_VERSION)/lib -cp TMP RSession "${PWD}/TMP/R-$(R_VERSION)/bin/R"
TMP/libRSession.so : RSession.c TMP/R-$(R_VERSION)/lib/libR.so TMP/RSession.h
$(CC) -ITMP -I$${JAVA_HOME}/include/ -I$${JAVA_HOME}/include/linux \
-LTMP/R-$(R_VERSION)/lib `TMP/R-$(R_VERSION)/bin/R CMD config --cppflags` -shared -fPIC -o $@ -g $< -lR
TMP/RSession.h : TMP/RSession.class
touch -c $@
TMP/RSession.class : RSession.java
mkdir -p TMP
javac -h TMP -d TMP $<
touch $@
TMP/R-$(R_VERSION)/lib/libR.so :
rm -rvf "TMP/R-$(R_VERSION)" TMP/jeter.tar.gz
mkdir -p $(dir $@)
wget -O TMP/jeter.tar.gz "https://pbil.univ-lyon1.fr/CRAN/src/base/R-4/R-$(R_VERSION).tar.gz"
(cd TMP && tar xfz jeter.tar.gz && rm jeter.tar.gz && cd R-$(R_VERSION) && ./configure --with-pcre1 --enable-R-shlib --with-x=no --prefix=${PWD}/TMP && make && make install)