JNI code fails to call C function on Linux but not Windows - java

I have the following Java code generated using SWIG. Although SWIG was used to generate the code knowledge of SWIG should not be needed to understand this question
User facing Java code:
public class UuidUtil implements OCUuidUtilConstants {
public static Uuid generateUuid() {
long cPtr = UuidUtilJNI.generateUuid();
return (cPtr == 0) ? null : new Uuid(cPtr, true);
}
}
The UuidUtilJNI.generateUuid() is defined as follows
Java code calling JNI code
public class UuidUtilJNI {
public final static native long generateUuid();
}
The SWIG generated JNI C wrapper code uuid_wrap.c
uuid_t * jni_gen_uuid()
{
printf("Inside jni_gen_uuid\n");
uuid_t *value = (uuid_t *)malloc(sizeof(uuid_t));
printf("Calling gen_uuid\n");
gen_uuid(value);
return value;
}
SWIGEXPORT jlong JNICALL Java_UuidUtilJNI_generateUuid(JNIEnv *jenv, jclass jcls) {
jlong jresult = 0 ;
uuid_t *result = 0 ;
(void)jenv;
(void)jcls;
result = (uuid_t *)jni_gen_uuid();
*(uuid_t **)&jresult = result;
return jresult;
}
partial C code for gen_uuid(uuid_t *uuid) function uuid.c
void gen_uuid(uuid_t *uuid)
{
printf("Inside gen_uuid\n");
/* code to set the uuid to type 4 UUID according to RFC4122 */
}
I am testing it as follows:
#Test
public void generateAndConvert() {
Uuid testUuid = UuidUtil.generateUuid();
assertNotNull(testUuid);
// other test code left out for readability
}
When the test is run on Windows the code works as expected.
When I try and run the same code on Linux the test hangs.
It prints 2 of the 3 print staments found in the code.
Inside jni_gen_uuid
Calling gen_uuid
the line Inside gen_uuid is never called when the test is run on a Linux machine (Fedora 30).
My first thought was that there was some sort of mismatch in the output of the object files causing the wrapper code to fail when calling the uuid code. I have compared the build flags used to build uuid.c and uuid_wrap.c code and they are using the same flags with the exception that some of the build warning are shut off for the wrapper code because its generated by a tool and not intended to
be modified by me.
I don't really know where else to look.
I have checked the uuid.o file using nm and objdump as best I can tell it has the gen_uuid symbol.
I have not been able to properly attach gdb to the running sample so not sure if that would provide any useful information.
Any suggestions that may help find the issue?

Unfortunately this solution was very specific to my code.
When I wrote that the print statement
printf("Inside gen_uuid\n");
/* code to set the uuid to type 4 UUID according to RFC4122 */
was never called I was wrong. The text was just not flushed to the screen. Adding fflush(stdout); after the print statement would have shown that indeed the gen_uuid function was being called.
As noted in the question this code generates a type 4 UUID which is a random UUID.
The code that generates random numbers is OS specific. Before the random number can be read the random number generator must be initialized. On Linux this is done by grabbing a file descriptor to /dev/urandom on Windows it is done by seeding srand() function.
Linux would segfault when generating the random number if random_init was not called. Windows on the other hand would produce a number even if it were not seeded.
The solution was to call randomInit() before calling generateUuid() in the unit test.
If you are a developer exploring a similar failure and are using printf debugging to check if a line of code was reached then make sure the print statement is flushed to the screen before concluding that a line of code is not being reached.

Related

Read c++ console output from method call using Java

Currently, I am trying to read the console output of my program when there is a method call. How it works is, my Java program calls the JNI wrapper to invoke the C++ method call. My C++ is using std::cout. The payload.invoke will invoke my c++ library API. Inside the c++ API there are a few cout statements. That is the statement I want to read it as a variable in Java.
The current PrintStream only supports out, print, println and printf.Each time when there is a method call, there are bunch of logs being printed out in command prompt. Now, I would like my java program to read those output which my C++ prints out.
This is my current Java code:
public void execute() {
try {
Matcher m = Pattern.compile("([^()]*)[(]([^()]*)[)]").matcher(getPayloadString());
m.find();
boolean passed;
if (m.group(2).isEmpty()) {
// this is where it invoke the method
passed = (boolean) payload.invoke(testcase);
System.out.println("Boolean is: " + passed + "\n");
}else {
passed = (boolean) payload.invoke(testcase, ObjectCreator.convertParameters(m.group(2)));
System.out.println("Boolean2 is: " + passed + "\n");
}
String output = passed ? "PASS" : "FAIL";
// I want to use the console output string variable here -> xxxx
TestCase.printResult(payload.getName(), output, m.group(2), xxxx, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
Are there any ways to do it? Previously I tried using one of the tutorial from here. but that seems not working. Can someone help me out with this please. Thanks in advance.
If you have full control of the .cpp codebase it is possible for you to change the std::cout to become a ostream& instead.
By referencing a base class you can easily switch the implementation.
Do a JNI-Stream whichh extends the ostream& and just overwrite the operators you need to send JNI wrapped callbacks to java.
Then depending on if you run native or Java style use your JNI-Stream instead of the std::cout.
I would do something as seen in the link below to package and send the data to Java:
JNI - How to callback from C++ or C to Java?
that is my 2 cents.
Read carefully the JNI tutorial.
https://www.baeldung.com/jni
Follow the tutorial.
Basically you need to create a java class with a static block to load the C++ library:
static {
System.loadLibrary("native");
}
Then you can create your own static java method and invoke a method on the library.
If what you need is read the output from a system call, it's a different matter.
This can help you:
Java Runtime.getRuntime(): getting output from executing a command line program

How to Pass Sig from Alloy to Java and execute alloy model from Java

I have built an alloy model where I have put all my system logic. I want to do a large scale analysis. For doing that, my logic is to use Java to read the data file, then pass those data to Alloy to check whether those met the constraint I defined in the Alloy or not. To do that, my logic is to create sig object using those data and pass those to Alloy.
As my system model is complex, I am trying to summarize my problem using the following code-
sig A{
val: Int
}
sig B{
chunk: Int
}
fact {
A.val > 10 && A.val < 15
}
Now, I want to pass the following sig object and run command from Java.
sig C{
name: String
}
run {} for 4
How can I pass that code? I am following this link https://github.com/ikuraj/alloy/blob/master/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java . But not able to figure it out.
There is currently a branch pkriens/api in progress that makes this quite easy. Look at the testcases in the classic test project.
We're working on integrating this in the master branch soon (before the end of 2019).

How does Android MediaCodec create a decoder?

I've noticed that java/android/media has a method called createDecoderByType() that is supposed to return a MediaCodec object. However, when I look at the MediaCodec.java source code on GoogleGit, I can't really see how the actual decoder is generated. Here is the code for that method:
public static MediaCodec createDecoderByType(String type) {
return new MediaCodec(type, true /* nameIsType */, false /* encoder */);
}
Then when I look at the constructor to see what is returned, this is what I see:
private MediaCodec(
String name, boolean nameIsType, boolean encoder) {
native_setup(name, nameIsType, encoder);
}
Okay, great. Let's look at native_setup(). Here's the definition:
private native final void native_setup(
String name, boolean nameIsType, boolean encoder);
That function appears to have no body!
At first I assumed that this meant the method would be defined in a child class. But I am seeing this method called directly on MediaCodec itself in other functioning source code.
So my question is: Is there any way I can trace down and see how Android creates a decoder of a given type depending on the environment and parameters? I seem to have hit a dead end, and no amount of Googling is giving me any helpful results.
Just found the answer to this the minute after I posted it...of course. The issue is with the native keyword. From GeeksforGeeks:
The native keyword is applied to a method to indicates that the method is implemented in native code using JNI (Java Native Interface).
This means that it can be written in another language such as C or C++, or invoke hardware stuff. The MediaCodec JNI code that I was looking for is here.

JNI error in CallObjectMethod/CallObjectMethodV: Ineligible receiver

I have a C routine that is calling a Java module through the JNI invocation interface. I've been having an issue where the call to the Java method has been returning a NULL string when using the C module and the JNI, but when I use Java at the command line, the Java module returns an error and a default value.
Here is the data returned when I bypass the C code and call the Method through Java at the command line
$ java ClassName "This" "is" "my" "test" "string"
Exception on SomethingElse.Method: [Function: DifferentMethod]ExceptionClassException: ExceptionClassExceptionException: [Function: CFBDynamicMessage::getCodePage]codePageBytes is NULL, for UTF-8
Returned String -- data I'm trying to get
0.0| |0.0| |0.0|| |0.0|0| |0.0| | ||0.0|0|0|0|0|0|0|0|0|0|0||
I need to get the returned string, even in the event of an error on the java side. To try to see what is going on in the C and JNI, I turned up the debugging level for the JNI:
options[1].optionString = "-Xdebug"; /* print JNI-related messages */
options[2].optionString = "-Xlog:all";
// this next line allows us to continue processing after the Java
// error. Unfortunately the code then SegFaults further on.
options[3].optionString = "-Xcheck:jni:nonfatal";
options[4].optionString = "-verbose:jni";
The JNI starts the JVM, finds the class and the method and builds the Java string I need to pass to the method, but when I try to execute the method, I get the following errors:
JVMJNCK048E JNI error in CallObjectMethod/CallObjectMethodV: Ineligible receiver
JVMJNCK080E Error detected in the outermost frame of an attached thread
JVMJNCK023E JNI error detected. Continuing...
Segmentation fault (core dumped)
Here is the C Code (I am cutting out some error checking and whitespace for brevity):
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
cls = (*env)->FindClass(env, "GenericClassName");
mid = (*env)->GetMethodID(env, cls, "execute", "(Ljava/lang/Object;)Ljava/lang/Object;");
jstr = (*env)->NewStringUTF( env, "This|is|my|test|string|");
// This next line is the one that throws the ineligible receiver error
jstring resultStr = (*env)->CallObjectMethod(env, cls, mid, jstr);
// ExceptionOccurred(env) is false; no errors are displayed
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
(*env)->ExceptionClear(env);
}
const char *nativeString = (*env)->GetStringUTFChars(env, resultStr, JNI_FALSE);
// This next line calls the SegFault
fprintf(stdout, "%s\n", *nativeString);
I've used gdb to look at the core dump created by the SegFault and here are the what I think are the pertinent results:
print nativeString
$1 = 0x8dfaa80 "[Ljava.lang.Class;#34ca34ca"
print *nativeString
$2 = 91 '['
here is the definition of the java method I'm calling:
public Object execute (Object args) throws Exception { ... }
Any help or insight you can provide with this issue will be greatly appreciated. When I try to Google for the ineligible receiver error, I get a bunch of links about football, but nothing in the JNI or Java in general. I've spent the last few days scouring the Stack Overflow website, and although there were some promising questions asked, they were all related to Android and didn't provide any additional assistance in resolving my issue.
As two final notes, even if you can't help, thanks for reading this far and my environment is a 64bit RHEL server, but the C code and the JVM are both running as 32bit applications.
TL;DR - C is calling a Java Method through the JNI and I am getting an error code (JNI error in CallObjectMethod/CallObjectMethodV: Ineligible receiver) that results in Google telling me all about all the sports I can't watch because I'm working on this issue.
You're supplying a class instead of an object. So you're trying to call Class<GenericClassName>.execute(Object arg). You need an instance of the class.

Supressing console (disp) output for compiled MATLAB > Java program (using MATLAB Compiler)

Edit 2 After recieving a response from Mathworks support I've answered the question myself. In brief, there is an options class MWComponentOptions that is passed to the exported class when instantiated. This can, among other things, specify unique print streams for error output and regular output (i.e. from disp()-liked functions). Thanks for all the responses none the less :)
====================================================================
Just a quick question - is there any way to prevent MATLAB code from outputting to the Java console with disp (and similar) functions once compiled? What is useful debugging information in MATLAB quickly becomes annoying extra text in the Java logs.
The compilation tool I'm using is MATLAB Compiler (which I think is not the same as MATLAB Builder JA, but I might be wrong). I can't find any good documentation on the mcc command so am not sure if there are any options for this.
Of course if this is impossible and a direct consequence of the compiler converting all MATLAB code to its Java equivalent then that's completely understandable.
Thanks in advance
Edit This will also be useful to handle error reporting on the Java side alone - currently all MATLAB errors are sent to the console regardless of whether they are caught or not.
The isdeployed function returns true if run in a deployed application (with e.g. MATLAB Compiler or Builder JA) and false when running in live MATLAB.
You can surround your disp statements with an if isdeployed block.
I heard back from a request to Mathworks support, and they provided the following solution:
When creating whatever class has been exported, you can specify an MWComponentOptions object. This is poorly documented in R2012b, but for what I wanted the following example would work:
MWComponentOptions options = new MWComponentOptions();
PrintStream o = new PrintStream(new File("MATLAB log.log"));
options.setPrintStream(o); // send all standard dips() output to a log file
// the following ignores all error output (this will be caught by Java exception handling anyway)
options.setErrorStream((java.io.PrintStream)null);
// instantiate and use the exported class
myClass obj = new myClass(options);
obj.myMatlabFunction();
// etc...
Update
In case anyone does want to suppress all output, casing null to java.io.PrintStream ended up causing a NullPointerException in deployment. A better way to suppress all output is use to create a dummy print stream, something like:
PrintStream dummy = new PrintStream(new OutputStream() {
public void close() {}
public void flush() {}
public void write(byte[] b) {}
public void write(byte[] b, int off, int len) {}
public void write(int b) {}
} );
Then use
options.setErrorStream(dummy);
Hope this helps :)
Another possible hack if you have a stand-alone application and don't want to bother with classes at all:
Use evalc and deploy your func name during compile:
function my_wrap()
evalc('my_orig_func(''input_var'')');
end
And compile like
mcc -m my_wrap my_orig_func <...>
Well, it is obviously yet another hack.

Categories