I am getting this error when I execute C++ code from Java. I placed cout statements in C++ code to identify if C++ part got executed completely and found that C++ code is working fine but when its reaching java side I am getting the below exception.
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fd5894aeaea, pid=8998, tid=0x00007fd58a01e700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_101-b13) (build 1.8.0_101-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C [libc.so.6+0x88aea] strlen+0x2a
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/user1/workspace/ImageProcessor/hs_err_pid8998.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
My Java class is
public class ShingleCoOrdJNA extends Structure {
public static class ByReference extends ShingleCoOrdJNA implements Structure.ByReference {}
public static class ByValue extends ShingleCoOrdJNA implements Structure.ByValue {}
public Point.ByValue ShiP1;
public Point.ByValue ShiP2;
public Point.ByValue ShiP3;
public Point.ByValue ShiP4;
//public Point.ByReference vDamagePts;
public StringByReference vDamagePts;
public boolean bIsGood;
public float fDamagePercentage;
public ShingleCoOrdJNA()
{
this.bIsGood = true;
this.fDamagePercentage = 0;
}
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[] { "ShiP1","ShiP2","ShiP3","ShiP4","vDamagePts","bIsGood","fDamagePercentage"});
}
}
StringByReference class is
public class StringByReference extends ByReference {
public StringByReference() {
this(0);
}
public StringByReference(int size) {
super(size < 4 ? 4 : size);
getPointer().clear(size < 4 ? 4 : size);
}
public StringByReference(String str) {
super(str.length() < 4 ? 4 : str.length() + 1);
setValue(str);
}
private void setValue(String str) {
getPointer().setString(0, str);
}
public String getValue() {
return getPointer().getString(0);
}
}
From java I am calling like this.
ShingleCoOrdJNAList.ByReference shingleCoordList = new ShingleCoOrdJNAList.ByReference();
shingleCoordList.shingleCoords = new ShingleCoOrdJNA.ByReference();
IntByReference size = new IntByReference();
TestImgProcInterface.INSTANCE.callPerformShingleDetection(newMat.getNativeObjAddr(), pointList, 4, shingleCoordList, size, false, true);
System.out.println(shingleCoordList.size());
C++ function
extern "C" void callPerformShingleDetection(Mat &FrameMat, struct PointListJNA pointList, int pointSize, struct ShingleCoOrdJNAList &damagePts, int &damagePtsSize, bool bShowResult, bool bDoDamageAnalysis) {
vector<cv::Point> vPolyList;
Point pXY;
for(int i=0;i<pointSize;i++) {
pXY.x = pointList.points[i].x;
pXY.y = pointList.points[i].y;
vPolyList.push_back(pXY);
}
vector<ShingleCoOrd> vShingleList;
PerformShingleDetection(FrameMat, vPolyList, vShingleList, bShowResult, bDoDamageAnalysis);
std::cout << "Image processing completed" << endl;
damagePts = {};
damagePts.size = vShingleList.size();
damagePts.shingleCoords = (ShingleCoOrdJNA*)malloc(sizeof(ShingleCoOrdJNA) * vShingleList.size());
std::cout << "ShingleCoordJNA memmory allocated" << endl;
for(int j=0;j<vShingleList.size();j++) {
damagePts.shingleCoords[j].ShiP1 = getJNAPoint(vShingleList[j].ShiP1);
damagePts.shingleCoords[j].ShiP2 = getJNAPoint(vShingleList[j].ShiP2);
damagePts.shingleCoords[j].ShiP3 = getJNAPoint(vShingleList[j].ShiP3);
damagePts.shingleCoords[j].ShiP4 = getJNAPoint(vShingleList[j].ShiP4);
damagePts.shingleCoords[j].bIsGood = vShingleList[j].bIsGood;
damagePts.shingleCoords[j].fDamagePercentage = vShingleList[j].fDamagePercentage;
/*damagePts.shingleCoords[j].vDamagePts = (Points*)malloc(sizeof(Points) * vShingleList[j].vDamagePts.size());
for(int m=0;m<vShingleList[j].vDamagePts.size();m++) {
damagePts.shingleCoords[j].vDamagePts[m] = getJNAPoint(vShingleList[j].vDamagePts[m]);
}*/
std::cout << "Damage String making" << endl;
damagePts.shingleCoords[j].vDamagePts = (char*)malloc(921600*sizeof(char));
std::stringstream s;
for(int m=0;m<vShingleList[j].vDamagePts.size();m++) {
s << s << vShingleList[j].vDamagePts[m].x << "," << vShingleList[j].vDamagePts[m].y << "#";
}
strcpy (damagePts.shingleCoords[j].vDamagePts, s.str().c_str());
std::cout << "Damage" << damagePts.shingleCoords[j].vDamagePts << endl;
}
std::cout << "Size of shingle detected" << vShingleList.size() << endl;
}
Related
I'm building an in-process JNI library fuzzer using Frida and I think I got everything to work except for multidimensional arrays.
When testing on Linux_64, I'm not able to even create a valid hook for a function which takes multidimensional arrays. No matter what I try I'm getting something like:
Exception in thread "main" java.lang.NoClassDefFoundError: [L[I;
at CallCrashingFun.crashingMethod_dbarr(Native Method)
at CallCrashingFun.main(CallCrashingFun.java:100)
Caused by: java.lang.ClassNotFoundException: [I
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
My hooking script looks similar to this:
var t_class = Java.use("CallCrashingFun")
var method_name = "crashingMethod_dbarr"
t_class[method_name].implementation = function(dbint) {
console.log("Hook works!")
}
/* Also tried with params
t_class[method_name].overload.apply(t_class[method_name], param_types).implementation = function(dbint) {
console.log("Hook works!")
}*/
/* This however doesn't crash
var imp_cp = t_class[method_name].implementation
t_class[method_name].implementation = imp_cp
*/
The Java code I use for tests:
System.loadLibrary("native");
int arr[] = {2,2,2};
int[][] dbarr = {arr};
new CallCrashingFun().crashingMethod_dbarr(dbarr);
private native void crashingMethod_dbarr(int[][] dbarr);
The JNI C++ code:
JNIEXPORT void JNICALL Java_CallCrashingFun_crashingMethod_1dbarr
(JNIEnv *env, jobject thisObject, jobjectArray dbtab) {
int i, j;
std::cout << "DbArray: " << "[" << std::endl;
jsize len = (env)->GetArrayLength(dbtab);
for (i=0; i<len; i++) {
std::cout << "[";
jintArray insArr = (jintArray) (env)->GetObjectArrayElement(dbtab, i);
jsize inlen = (env)->GetArrayLength(insArr);
jint *body = (env)->GetIntArrayElements(insArr, 0);
for (j=0; j<inlen; j++) {
std::cout << body[i] << ",";
}
std::cout << "]" << std::endl;
}
std::cout << "]" << std::endl;
}
Java version that I'm using:
$ /usr/bin/java --version
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
openjdk 11.0.17 2022-10-18
OpenJDK Runtime Environment Temurin-11.0.17+8 (build 11.0.17+8)
OpenJDK 64-Bit Server VM Temurin-11.0.17+8 (build 11.0.17+8, mixed mode)
Frida server version:
frida-server-16.0.8-linux-x86_64
Without hook the function works correctly:
DbArray: [
[2,2,2,]
]
How can I get this hook to work?
I am trying to call the following java method from C++
final String[] games = GameLoader.listGames();
where GameLoader was imported with import player.GameLoader;. The GameLoader class exists within a jar file. I am trying to use JNI to load the jar file from C++ and then call the above method. The following is my C++ code which I have tried to extend from this SO post.
#include <iostream>
#include <string.h>
#include <jni.h>
#include <stdlib.h>
using namespace std;
#define PATH_SEPARATOR ';'
#define USER_CLASSPATH "Ludii-0.3.0.jar"
#define GAME_LOADER "player/GameLoader"
JNIEnv *env;
JavaVM *jvm;
jint res;
void initJVM() {
#ifdef JNI_VERSION_1_2
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString =
"-Djava.class.path=" USER_CLASSPATH;
vm_args.version = 0x00010002;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
#else
JDK1_1InitArgs vm_args;
char classpath[1024];
vm_args.version = 0x00010001;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Append USER_CLASSPATH to the default system class path */
sprintf(classpath, "%s%c%s",
vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
vm_args.classpath = classpath;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
#endif /* JNI_VERSION_1_2 */
}
void closeJVM() {
jvm->DestroyJavaVM();
}
int main() {
initJVM();
jclass gameLoader = env->FindClass(GAME_LOADER);
//final String[] games = GameLoader.listGames();
jmethodID mid = env->GetMethodID(gameLoader,"listGames","()[Ljava/lang/String;");
jobjectArray stringArray = (jobjectArray) env->CallObjectMethod(gameLoader,mid);
closeJVM();
}
I am able to successfully create the JVM and the code compiles however at runtime I get the error
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f0e835619d7, pid=3504, tid=0x00007f0e84028740
#
# JRE version: OpenJDK Runtime Environment (8.0_222-b10) (build 1.8.0_222-8u222-b10-1ubuntu1~16.04.1-b10)
# Java VM: OpenJDK 64-Bit Server VM (25.222-b10 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V [libjvm.so+0x6849d7]
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/alex/jni_examples/hs_err_pid3504.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
Aborted (core dumped)
I think that the error is related to the CallObjectMethod call but I'm not sure.
Also I am using Java 8
EDIT:
It looks like mid evaluated to 0 which means that the method was not found. I guess this is the problem however I'm not sure why it wasn't found. This was checked with
int main() {
initJVM();
jclass gameLoader = env->FindClass("player/GameLoader");
//final String[] games = GameLoader.listGames();
if(gameLoader == NULL)
{
cout << "Could not load class!" << endl;
return 1;
}
jmethodID mid = env->GetMethodID(gameLoader,"listGames","()[Ljava/lang/String;");
if(mid == NULL)
{
cout << "Could not load method!" << endl;
return 1;
}
jobjectArray stringArray = (jobjectArray) env->CallObjectMethod(gameLoader,mid);
if(stringArray == NULL)
{
cout << "Could not load object!" << endl;
return 1;
}
closeJVM();
}
ANOTHER EDIT:
So it looks like the problem was that listGames() should be found with GetStaticMethodID rather than GetMethodID and it should be called with CallStaticObjectMethod rather than CallObjectMethod. Thank you.
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x5f0c25fe, pid=14780, tid=11168
#
# JRE version: Java(TM) SE Runtime Environment (7.0_80-b15) (build 1.7.0_80-b15)
# Java VM: Java HotSpot(TM) Client VM (24.80-b11 mixed mode, sharing windows-x86 )
# Problematic frame:
# C [ZBRGraphics.dll+0x25fe]
I keep getting this error when using the Zebra printer DLL in Java program.
public class Tester {
public static void main(String[] args) {
ZBRGraphics zGraphics = ZBRGraphics.INSTANCE;
String text = "Print this";
byte[] textB = text.getBytes(StandardCharsets.UTF_8);
String font= "Arial";
byte[] fontB = text.getBytes(StandardCharsets.UTF_8);
System.out.println(zGraphics.ZBRGDIDrawText(0, 0, textB, fontB, 12, 1, 0x0FF0000, 0));
}
}
public interface ZBRGraphics extends Library {
ZBRGraphics INSTANCE = (ZBRGraphics) Native.loadLibrary("ZBRGraphics", ZBRGraphics.class);
int ZBRGDIDrawText(int x, int y, byte[] text, byte[] font, int fontSize, int fontStyle, int color, int err);
}
I have the DLL in C:\Windows\System32 and in my 32 bit Java .
I'm using a 64 bit machine as my laptop for development.
If my google-fu skills are any good, you appear to be interfacing with the Zebra printer's API. According to the "ZXP1 & ZXP3 Software Developers Reference Manual" (found here), the Java mapping of the function is incorrect.
This is the actual C function prototype:
int ZBRGDIDrawText(
int x,
int y,
char *text,
char *font,
int fontSize,
int fontStyle,
int color,
int *err
)
As you can see, err is not an int, but a pointer to one. Also, since text and font are strings, you can just use a String as the Java type. Additionally, the API docs say that the return value is an int with either 1 for success or 0 for failure, meaning that you can use a boolean for ease of use.
The following Java mapping should be correct:
boolean ZBRGDIDrawText(
int x,
int y,
String text,
String font,
int fontSize,
int fontStyle,
int color,
IntByReference err
);
and you might use it like so:
IntByReference returnCode = new IntByReference(0);
boolean success = zGraphics.ZBRGDIDrawText(
0,
0,
"Print this",
"Arial",
12,
1,
0x0FF0000,
returnCode
);
if (success) {
System.out.println("success");
} else {
System.out.println("ZBRGDIDrawText failed with code " + returnCode.getValue());
}
I am trying to call non static method from java to C++ using JNI
My Java Code is here:
public class hellojava
{
public static void main(String args[])
{
System.out.println("Hello World!");
System.out.println("This is the main function from the HelloWorld java class.");
}
public void message()
{
System.out.println("call from object");
}
}
And my C++ code is here:
#include <stdio.h>
#include <jni.h>
JNIEnv* create_vm(JavaVM ** jvm) {
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options;
options.optionString = "-Djava.class.path=/home/../nonstaticJavaMethods/";
//Path to the java source code
vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;
int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
if(ret < 0)
printf("\nUnable to Launch JVM\n");
return env;
}
int main(int argc, char* argv[])
{
JNIEnv *env;
JavaVM * jvm;
env = create_vm(&jvm);
if (env == NULL)
return 1;
//jclass clsH=NULL;
jmethodID midMain = NULL;
jstring square;
jclass clsH = env->FindClass("helloWorld");
jmethodID constructor = env->GetMethodID(clsH, "<init>", "void(V)");
jobject object = env->NewObject(clsH, constructor);
//Obtaining Method IDs
if (clsH != NULL)
{ midMain = env->GetMethodID(clsH, "message", "void(V)");
env->CallVoidMethod(clsH, midMain, object,NULL);
}
else
{
printf("\nUnable to find the requested class\n");
}
//Release resources.
int n = jvm->DestroyJavaVM();
return 0;
}
My code compiles but it is giving me runtime error. Following is the error
A fatal error has been detected by the Java Runtime Environment:
SIGSEGV (0xb) at pc=0x00007fdf3f5126bb, pid=11302, tid=140596827092800
JRE version: OpenJDK Runtime Environment (7.0_55-b14) (build 1.7.0_55-b14)
Java VM: OpenJDK 64-Bit Server VM (24.51-b03 mixed mode linux-amd64 compressed oops)
Problematic frame:
V [libjvm.so+0x5c46bb] alloc_object(_jclass*, Thread*)+0x1b
Failed to write core dump. Core dumps have been disabled. To enable core dumping,
try
"ulimit -c unlimited" before starting Java again
An error report file with more information is saved as
/home/../nonstaticJavaMethods/hs_err_pid11302.log
Aborted!
Additionally to immibis' answer, i also think the call
jclass clsH = env->FindClass("helloWorld");
isn't returning anything, as your class is called
public class hellojava
So your application is probably seg-faulting in GetMethodID() or NewObject()
void(V) is not a valid method descriptor.
Because there is no method called <init> with the descriptor void(V) (which there can't be, because it's invalid), GetMethodID returns 0. Then you try to create a new object using this invalid method ID.
The method descriptor for a method that takes no arguments and returns void (which a constructor is) is ()V.
What is the best way to go about creating a program that would change the desktop wallpaper periodically? I would also like to create a GUI around the program. I am a Computer Science student, and as such I know basic programming in Java, and C++ among others. This will be done on Windows 7 OS.
What would be the best language to use for a project like this?
Ideally I would like to use the system clock to trigger the change. Is this possible?
Am I in over my head?
Any answers will be very much appreciated. Thank you.
In Java :
import java.util.*;
public class changer
{
public static native int SystemParametersInfo(int uiAction,int uiParam,String pvParam,int fWinIni);
static
{
System.loadLibrary("user32");
}
public int Change(String path)
{
return SystemParametersInfo(20, 0, path, 0);
}
public static void main(String args[])
{
String wallpaper_file = "c:\\wallpaper.jpg";
changer mychanger = new changer();
mychanger.Change(wallpaper_file);
}
}
In Win32 C++, You can use SetTimer to trigger a change.
#define STRICT 1
#include <windows.h>
#include <iostream.h>
VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
LPWSTR wallpaper_file = L"C:\\Wallpapers\\wallpaper.png";
int return_value = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, wallpaper_file, SPIF_UPDATEINIFILE);
cout << "Programmatically change the desktop wallpaper periodically: " << dwTime << '\n';
cout.flush();
}
int main(int argc, char *argv[], char *envp[])
{
int Counter=0;
MSG Msg;
UINT TimerId = SetTimer(NULL, 0, 2000, &TimerProc); //2000 milliseconds
cout << "TimerId: " << TimerId << '\n';
if (!TimerId)
return 16;
while (GetMessage(&Msg, NULL, 0, 0))
{
++Counter;
if (Msg.message == WM_TIMER)
cout << "Counter: " << Counter << "; timer message\n";
else
cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
DispatchMessage(&Msg);
}
KillTimer(NULL, TimerId);
return 0;
}
This is a reasonably straightforward project, and can be done easily with any language that can call Win32 API functions (C++, for example). The non-obvious function to change the wallpaper is SystemParametersInfo with the SPI_SETDESKWALLPAPER flag. You give it a file name of a new image, and the wallpaper changes.