Display Java console output in R using rJava - java

I have created the following Java class and saved it as Test.java, then compiled into Test.class on the command line using javac Test.java:
public class Test {
public Test() {
}
public double power(double number) {
System.out.println("calculating...");
return number * number;
}
}
Furthermore, I have created the following R script and saved it as test.R:
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
When I execute it, for example using R CMD BATCH test.R on the command line, I get the following output, which is what I want:
calculating...
[1] 9
However, when I wrap this script in a Markdown document and compile it using knitr, I lose the message that is printed about the calculation taking place. For example, I save the following script in test.Rmd and compile it using RStudio:
```{r echo=TRUE, warning=TRUE, results='show', message=TRUE}
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
```
This only returns the following output, without the message:
## [1] 9
I read somewhere that the reason is that System.out.println in Java writes to stdout, and whether this is shown in the R console or not depends on the interpreter. For example, the output is shown on Unix systems but not on Windows or in knitr.
My questions:
Is the above interpretation correct?
How can I reliably capture or display the output of System.out.println in R, irrespective of operating system or interpreter?
If that's not possible, what is a better way of designing status messages about the current calculations and progress in Java, such that R can display these messages?
Thanks!

I'll take a stab at answering my own question... Looks like the RJava folks actually offer a built-in solution (thanks Simon Urbanek if you read this). On the side of the Java code, there is the LGPL-licensed JRI.jar, which is delivered with rJava (look at the jri sub-directory in the rJava package directory in your local R library path) and which can be copied/extracted into the Java library path. It's only 82kb, so fairly light-weight.
JRI offers a replacement of the default print stream in Java. Essentially, you redirect the system output into an RConsoleOutputStream provided by JRI. The code in my question above can be modified as follows to print to the R console instead of stdout.
import java.io.PrintStream;
import org.rosuda.JRI.RConsoleOutputStream;
import org.rosuda.JRI.Rengine;
public class Test {
public Test() {
Rengine r = new Rengine();
RConsoleOutputStream rs = new RConsoleOutputStream(r, 0);
System.setOut(new PrintStream(rs));
}
public double power(double number) {
System.out.println("calculating...");
return number * number;
}
}

Related

How to determine the currently active code page from a Java console application on Windows?

This is a simple Java application which displays the default code page on Windows:
package doscommand;
import java.io.IOException;
import java.io.InputStream;
public class DosCommand {
public static void main(String[] args) throws IOException {
InputStream in = Runtime.getRuntime().exec("chcp.com").getInputStream();
int ch;
StringBuilder chcpResponse = new StringBuilder();
while ((ch = in.read()) != -1) {
chcpResponse.append((char) ch);
}
System.out.println(chcpResponse); // For example: "Active code page: 437"
}
}
On my Windows 10 machine this application always displays "Active code page: 437" because Cp437 is the default, and Runtime.getRuntime().exec() starts a new Process when running chcp.com.
Is it possible to create a Java application which instead displays the currently active code page for the existing Command Prompt window in which the code is running?
I want to be able to do something like this from the Command Prompt:
chcp 1252
java -jar "D:\NB82\DosCommand\dist\DosCommand.jar" REM Shows current code page is "1252".
chcp 850
java -jar "D:\NB82\DosCommand\dist\DosCommand.jar" REM Shows current code page is "850".
How do you specify a Java file.encoding value consistent with the underlying Windows code page? asked a similar question, though in that case the OP was seeking a non-Java solution.
I'd prefer a Java-only solution, but as alternatives:
Can this possibly be done using JNI, by calling some C/C++/C# code with access to the Windows API? The called code need only return a numeric value for the active code page.
I'll accept an answer which persuasively argues that it can't be done.
The solution turned out to be just one line of code. Using JNA, the value returned by the Windows API function GetConsoleCP() gives the console's active code page:
import com.sun.jna.platform.win32.Kernel32;
public class JnaActiveCodePage {
public static void main(String[] args) {
System.out.println("" + JnaActiveCodePage.getActiveInputCodePage());
}
/**
* Calls the Windows function GetConsoleCP() to get the active code page using JNA.
* "jna.jar" and "jna-platform.jar" must be on the classpath.
*
* #return the code page number.
*/
public static int getActiveInputCodePage() {
return Kernel32.INSTANCE.GetConsoleCP();
}
}

Allow Evosuite to write files during test generation

Im currently trying to get Evosuite to work with JNA. Consider the following basic example:
import com.sun.jna.ptr.IntByReference;
public class Example {
public static int foo(int x) {
IntByReference c = new IntByReference(x);
if (c.getValue() == 100) {
return 100;
} else {
return 0;
}
}
}
Im running Evosuite from the command line with these options:
java32 -jar evosuite.jar -projectCP "src;E:\evosuite\test\lib\jna-5.2.0.jar" -class Example -criterion branch
Evosuite wont reach 100% branch coverage (only the trivial 33%), but notifies me with this message after the timeout:
* Permissions denied during test execution:
- java.io.FilePermission:
write C:\Users\PC\AppData\Local\Temp\jna--2025216854: 1
I found out that JNA needs to write some temp files in order to work, but Evosuite will block any atempt of file writing during test generation. I understand that this is a reasonable policy in most cases because you dont want Evosuite to write random files to your disk while generating tests for a saveFile() function, but in my case this shouldn't be a problem.
Is there a way to tell Evosuite to allow file writing during test generation or a different approach to generate tests for java programms using the JNA library?
I figured out how to run JNA without the need of writing temporary files thanks to cubrr.
copy the system specific jnidispatch.[dll, ...] file to a folder
add -Djna.boot.library.path=folder -Djna.nounpack=true to the command
Note: the jna.boot.library.path should only point to the containig folder, do not write folder/jnidispatch.
Solution to the initial question:
Setting the evosuite option -Dsandbox=false will remove most restrictions for test generation and finally allowed me to generate my tests!

Run matlab function in java class in absence of matlab environment

I want to use matlab function in java application. I create java package from my function by deploytool in matlab. Now, how can i use this package? Can only import the jar file created by deploytool in my java project and use its function?
After a lot of googling, I used this toturial but in the final step, i get error "could not load file".
Also i read about MatlabControl, but in this solution, we should have matlab environment in our system to java code running. But i will run my final app in systems that may not have matlab at all.
So i need a solution to run matlab function in java class even in absence of matlab environment.
Finally I solve my problem. the solution step by step is as follows:
write matlab function:
function y = makesqr(x)
y = magic(x);
Use deploytool in matlab and create java package.
3.create new java application in Eclipse and add main class. import javabuilde.jar and makesqr.jar:
import com.mathworks.toolbox.javabuilder.MWArray;
import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import makesqr.Class1;
and main.java:
public class main {
public static void main(String[] args) {
MWNumericArray n = null;
Object[] result = null;
Class1 theMagic = null;
try
{
n = new MWNumericArray(Double.valueOf(5),MWClassID.DOUBLE);
theMagic = new Class1();
result = theMagic.makesqr(1, n);
System.out.println(result[0]);
}
catch (Exception e)
{
System.out.println("Exception: " + e.toString());
}
finally
{
MWArray.disposeArray(n);
MWArray.disposeArray(result);
theMagic.dispose();
}
}
}
add javabuilder.jar and makesqr.jar to java build path of your project.
run it.
the Double.valueOf(3), define the input for our function and the output is as follows:
8 1 6
3 5 7
4 9 2
I didn't get properly your problem. Did you already compile the jar file from Matlab code and you are trying to use that, or you are at the last step of the tutorial?
If your answer is the latest case, most probably you forgot the "." before the class path.
From tutorial you linked:
You must be sure to place a dot (.) in the first position of the class path. If it not, you get a message stating that Java cannot load the class.
Also check if the matlab compiler path ("c:\Program Files\MATLAB\MATLAB Compiler Runtime\v82\toolbox\javabuilder\jar\javabuilder.jar" - in the tutorial) is correct for your system.

Using a Python Script in Java (Eclipse)

I've been looking to incorporate a Python Script a friend made for me into a Java application that I am trying to develop. After some trial and error I finally found out about 'Jython' and used the PythonInterpreter to try and run the script.
However, upon trying to run it, I am getting an error within the Python Script. This is odd because when I try run the script outside of Java (Eclipse IDE in this case), the script works fine and does exactly what I need it to (extract all the images from the .docx files stored in its same directory).
Can someone help me out here?
Java:
import org.python.core.PyException;
import org.python.util.PythonInterpreter;
public class SPImageExtractor
{
public static void main(String[] args) throws PyException
{
try
{
PythonInterpreter.initialize(System.getProperties(), System.getProperties(), new String[0]);
PythonInterpreter interp = new PythonInterpreter();
interp.execfile("C:/Documents and Settings/user/workspace/Intern Project/Proposals/Converted Proposals/Image-Extractor2.py");
}
catch(Exception e)
{
System.out.println(e.toString());
e.printStackTrace();
}
}
}
Java Error regarding Python Script:
Traceback (most recent call last):
File "C:/Documents and
Settings/user/workspace/Intern
Project/Proposals/Converted
Proposals/Image-Extractor2.py", line
19, in
thisDir,_ = path.split(path.abspath(argv[0]))
IndexError: index out of range: 0
Traceback (most recent call last):
File "C:/Documents and
Settings/user/workspace/Intern
Project/Proposals/Converted
Proposals/Image-Extractor2.py", line
19, in
thisDir,_ = path.split(path.abspath(argv[0]))
IndexError: index out of range: 0
Python:
from os import path, chdir, listdir, mkdir, gcwd
from sys import argv
from zipfile import ZipFile
from time import sleep
#A few notes -
#(1) when I do something like " _,variable = something ", that is because
#the function returns two variables, and I only need one. I don't know if it is a
#common convention to use the '_' symbol as the name for the unused variable, but
#I saw it in some guy's code in the past, and I started using it.
#(2) I use "path.join" because on unix operating systems and windows operating systems
#they use different conventions for paths like '\' vs '/'. path.join works on all operating
#systems for making paths.
#Defines what extensions to look for within the file (you can add more to this)
IMAGE_FILE_EXTENSIONS = ('.bmp', '.gif', '.jpg', '.jpeg', '.png', '.tif', '.tiff')
#Changes to the directory in which this script is contained
thisDir = getcwd()
chdir(thisDir)
#Lists all the files/folders in the directory
fileList = listdir('.')
for file in fileList:
#Checks if the item is a file (opposed to being a folder)
if path.isfile(file):
#Fetches the files extension and checks if it is .docx
_,fileExt = path.splitext(file)
if fileExt == '.docx':
#Creates directory for the images
newDirectory = path.join(thisDir, file + "-Images")
if not path.exists(newDirectory):
mkdir(newDirectory)
currentFile = open(file,"r")
for line in currentFile:
print line
sleep(5)
#Opens the file as if it is a zipfile
#Then lists the contents
try:
zipFileHandle = ZipFile(file)
nameList = zipFileHandle.namelist()
for archivedFile in nameList:
#Checks if the file extension is in the list defined above
#And if it is, it extracts the file
_,archiveExt = path.splitext(archivedFile)
if archiveExt in IMAGE_FILE_EXTENSIONS:
zipFileHandle.extract(archivedFile, newDirectory)
except:
pass
My guess is that you don't get command line arguments if the interpreter is called (well not that surprisingly, where should it get the correct values? [or what would be the correct value?]).
os.getcwd()
Return a string representing the current working directory.
Would return the working dir, but presumably that's not what you want.
Not tested, but I think os.path.dirname(os.path.realpath( __ file__)) should work presumably (Note: remove the space there; I should look at the formatting options in detail some time~)

Is *this* really the best way to start a second JVM from Java code?

This is a followup to my own previous question and I'm kind of embarassed to ask this... But anyway: how would you start a second JVM from a standalone Java program in a system-independent way? And without relying on for instance an env variable like JAVA_HOME as that might point to a different JRE than the one that is currently running. I came up with the following code which actually works but feels just a little awkward:
public static void startSecondJVM() throws Exception {
String separator = System.getProperty("file.separator");
String classpath = System.getProperty("java.class.path");
String path = System.getProperty("java.home")
+ separator + "bin" + separator + "java";
ProcessBuilder processBuilder =
new ProcessBuilder(path, "-cp",
classpath,
AnotherClassWithMainMethod.class.getName());
Process process = processBuilder.start();
process.waitFor();
}
Also, the currently running JVM might have been started with some other parameters (-D, -X..., ...) that the second JVM would not know about.
I think that the answer is "Yes". This probably as good as you can do in Java using system independent code. But be aware that even this is only relatively system independent. For example, in some systems:
the JAVA_HOME variable may not have been set,
the command name used to launch a JVM might be different (e.g. if it is not a Sun JVM), or
the command line options might be different (e.g. if it is not a Sun JVM).
If I was aiming for maximum portability in launching a (second) JVM, I think I would do it using wrapper scripts.
It's not clear to me that you would always want to use exactly the same parameters, classpath or whatever (especially -X kind of stuff - for example, why would the child need the same heap settings as its parents) when starting a secondary process.
I would prefer to use an external configuration of some sort to define these properties for the children. It's a bit more work, but I think in the end you will need the flexibility.
To see the extent of possible configuration settings you might look at thye "Run Configurations" settings in Eclipse. Quite a few tabs worth of configuration there.
To find the java executable that your code is currently running under (i.e. the 'path' variable in your question's sample code) there is a utility method within apache ant that can help you. You don't have to build your code with ant - just use it as a library, for this one method.
It is:
org.apache.tools.ant.util.JavaEnvUtils.getJreExecutable("java")
It takes care of the sort of special cases with different JVM vendors that others have mentioned. (And looking at the source code for it, there are more special cases than I would have imagined.)
It's in ant.jar. ant is distributed under the Apache license so hopefully you can use it how you want without hassle.
Here's a way that determines the java executable which runs the current JVM using ProcessHandle.current().info().command().
The ProcessHandle API also should allow to get the arguments. This code uses them for the new JVM if available, only replacing the current class name with another sample class. (Finding the current main class inside the arguments gets harder if you don't know its name, but in this demo it's simply "this" class. And maybe you want to reuse the same JVM options or some of them, but not the program arguments.)
However, for me (openjdk version 11.0.2, Windows 10), the ProcessInfo.arguments() is empty, so the fallback else path gets executed.
package test;
import java.lang.ProcessBuilder.Redirect;
import java.lang.management.ManagementFactory;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStartJvm {
public static void main(String[] args) throws Exception {
ProcessHandle.Info currentProcessInfo = ProcessHandle.current().info();
List<String> newProcessCommandLine = new LinkedList<>();
newProcessCommandLine.add(currentProcessInfo.command().get());
Optional<String[]> currentProcessArgs = currentProcessInfo.arguments();
if (currentProcessArgs.isPresent()) { // I know about orElse, but sometimes isPresent + get is handy
for (String arg: currentProcessArgs.get()) {
newProcessCommandLine.add(TestStartJvm.class.getName().equals(arg) ? TargetMain.class.getName() : arg);
}
} else {
System.err.println("don't know all process arguments, falling back to passed args array");
newProcessCommandLine.add("-classpath");
newProcessCommandLine.add(ManagementFactory.getRuntimeMXBean().getClassPath());
newProcessCommandLine.add(TargetMain.class.getName());
newProcessCommandLine.addAll(List.of(args));
}
ProcessBuilder newProcessBuilder = new ProcessBuilder(newProcessCommandLine).redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT);
Process newProcess = newProcessBuilder.start();
System.out.format("%s: process %s started%n", TestStartJvm.class.getName(), newProcessBuilder.command());
System.out.format("process exited with status %s%n", newProcess.waitFor());
}
static class TargetMain {
public static void main(String[] args) {
System.out.format("in %s: PID %s, args: %s%n", TargetMain.class.getName(), ProcessHandle.current().pid(),
Stream.of(args).collect(Collectors.joining(", ")));
}
}
}
Before ProcessHandle was added in Java 9, I did something like this to query the current JVM's command-line:
Let the user pass or configure a "PID to command-line" command template; under Windows, this could be wmic process where 'processid=%s' get commandline /format:list.
Determine PID using java.lang.management.ManagementFactory.getRuntimeMXBean().getPid().
Expand command template; execute; parse its output.

Categories