I'm working on raycast, but I have a big problem. Here is the error message.
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f2a67b5345b, pid=19347, tid=139820316944128
#
# JRE version: OpenJDK Runtime Environment (7.0_79-b14) (build 1.7.0_79-b14)
# Java VM: OpenJDK 64-Bit Server VM (24.79-b02 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea 2.5.5
# Distribution: Custom build (Wed Apr 15 12:39:15 UTC 2015)
# Problematic frame:
# C [libgdx-box2d64.so+0x3a45b] void b2DynamicTree::RayCast<b2WorldRayCastWrapper>(b2WorldRayCastWrapper*, b2RayCastInput const&) const+0x3ab
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
You can look the log file here http://paste.ubuntu.com/11287130/
Here is my callback and splitObj.
private final RayCastCallback callback = new RayCastCallback() {
#Override
public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
//We can just slice the field and field is ChainShape
if (fixture.getShape() instanceof ChainShape) {
Body body = fixture.getBody();
List<Vector2> pointVec = rayCastMap.get(body);
if (pointVec == null) {
pointVec = new ArrayList<Vector2>();
rayCastMap.put(body, pointVec);
}
if (!pointVec.isEmpty() && !pointVec.get(0).equals(point)) {
pointVec.add(point.cpy());
splitObj(body, pointVec);
} else {
pointVec.add(point.cpy());
}
}
return 1;
}
};
private void splitObj(Body sliceBody, List<Vector2> splitedPoints) {
Vector2 a = splitedPoints.get(0);
Vector2 b = splitedPoints.get(1);
Array<Vector2> shape1Vertices = new Array<Vector2>();
shape1Vertices.addAll(a, b);
Array<Vector2> shape2Vertices = new Array<Vector2>();
shape2Vertices.addAll(a, b);
for (Vector2 vec : field.getVertices()) {
float determinant = det(a, b, vec);
if (determinant > 0) {
if (!shape1Vertices.contains(vec, false))
shape1Vertices.add(vec);
} else if (determinant < 0) {
if (!shape2Vertices.contains(vec, false))
shape2Vertices.add(vec);
}
}
GeometryUtils.arrangeClockwise(shape1Vertices);
GeometryUtils.arrangeClockwise(shape2Vertices);
FloatArray shape1 = arrayToFloatArray(shape1Vertices);
FloatArray shape2 = arrayToFloatArray(shape2Vertices);
FloatArray newShape;
float shape1Area = calculateArea(shape1);
float shape2Area = calculateArea(shape2);
box2dWorld.destroyBody(sliceBody);
ball.box2dBall.setActive(false);
float splicedArea;
if (det(a, b, ball.getPosition()) > 0) {
splicedArea = shape2Area * 100 / (shape1Area + shape2Area);
newShape = shape1;
} else {
splicedArea = shape1Area * 100 / (shape1Area + shape2Area);
newShape = shape2;
}
field.setIsSliced(true);
// setting the properties of the two newly created shapes
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(sliceBody.getPosition());
FixtureDef fixtureDef = new FixtureDef();
// creating the first shape
PolygonShape polygonShape = new PolygonShape();
polygonShape.set(newShape.toArray());
fixtureDef.shape = polygonShape;
sliceBody = box2dWorld.createBody(bodyDef);
sliceBody.createFixture(fixtureDef);
}
I want to slice an object(ChainShape) and there is a ball which can move around inside this chainshape.I listen touchDown , touchDragged and touchUp for input.
touchDown gets first point of the line for raycast , touchDragged gets second point of the line and touchUp is calling raycast like this one.
box2dWorld.rayCast(callback, p2, p1);
When I call that , sometimes it gives this fatal error.What is my problem? What can I do?
Usually if you see a SIGSEGV Java Runtime Environment error while working with box2d then it is related to the usage of an already destroyed body / joint etc.
Take a look at your code here you destroy a body:
box2dWorld.destroyBody(sliceBody);
Then some lines later you try to use that already destroyed body again (!):
bodyDef.position.set(sliceBody.getPosition());
You cannot use destroyed bodies anymore! Try to destroy bodies only after you are sure you are not going to use them anymore.
Related
Context
I am working on my Master Thesis using Intel SGX in order to use Enclave Code alongside a Java project.
The project uses Gradle for installation, and I have added a .jar containing a Class containing Native calls and the .so file containing the code for these calls.
I am currently only being able to open up an enclave and calculate an EC Curve for DH Key exchange, however, as the java code moves on, segfaults occur. These Segfaults however, dont occur inside the C code, as I am able to retrieve the correct and expected results from the native code in my java project. These segmentation faults usually happen there is heavy I/O workload (At least that is what I deduced so far), usually Sockets, which is something I use, since my thesis is in Distributed Systems.
C Code:
JNIEXPORT jint JNICALL Java_sgxUtils_SgxFunctions_jni_1initialize_1enclave
(JNIEnv *env , jobject,jint enclaveId, jbyteArray file_path){
if(file_path == NULL){
printf("NULL FILEPATH. error.");
return -1;
}
char token_path[MAX_PATH] = {'\0'};
sgx_launch_token_t token = {0};
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
int updated = 0;
//Get the id of a given Enclave:
global_eid = (int)enclaveId;
int length = snprintf(NULL , 0, "%d", enclaveId) + 1; //Gives the length of the Integer as a String.
char* id_ptr = (char*)malloc(length);
snprintf(id_ptr,length,"%d",enclaveId);
/* Step 1: try to retrieve the launch token saved by last transaction
* if there is no token, then create a new one.
*/
/* try to get the token saved in $HOME */
const char *home_dir = getpwuid(getuid())->pw_dir;
if (home_dir != NULL &&
(strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
/* compose the token path */
strncpy(token_path, home_dir, strlen(home_dir));
strncat(token_path, "/", strlen("/"));
char* correctName = (char*) malloc(length + sizeof(TOKEN_FILENAME) + 1);
memcpy(correctName,id_ptr,length);
strncat(correctName,TOKEN_FILENAME,sizeof(TOKEN_FILENAME)+1);
strncat(token_path,correctName,length + sizeof(TOKEN_FILENAME)+1);
// strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1);
// free(correctName);
} else {
/* if token path is too long or $HOME is NULL */
strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME));
}
FILE *fp = fopen(token_path, "rb");
if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) {
printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path);
}
if (fp != NULL) {
/* read the token from saved file */
size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp);
if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) {
/* if token is invalid, clear the buffer */
memset(&token, 0x0, sizeof(sgx_launch_token_t));
printf("Warning: Invalid launch token read from \"%s\".\n", token_path);
}
}
printf("\n");
/* Step 2: call sgx_create_enclave to initialize an enclave instance */
/* Debug Support: set 2nd parameter to 1 */
//Here we obtain the char* of the given Enclave file path:
size_t filename_size = env->GetArrayLength(file_path);
jbyte* jb_filePath = env->GetByteArrayElements(file_path,NULL);
char* enclave_filePath = (char*) malloc(filename_size);
memcpy(enclave_filePath,jb_filePath,filename_size);
ret = sgx_create_enclave(enclave_filePath, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL);
if (ret != SGX_SUCCESS) {
if (fp != NULL) fclose(fp);
return -1;
}
/* Step 3: save the launch token if it is updated */
if (updated == FALSE || fp == NULL) {
/* if the token is not updated, or file handler is invalid, do not perform saving */
if (fp != NULL) fclose(fp);
return 0;
}
/* reopen the file with write capablity */
fp = freopen(token_path, "wb", fp);
if (fp == NULL) return 0;
size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp);
if (write_num != sizeof(sgx_launch_token_t))
printf("Warning: Failed to save launch token to \"%s\".\n", token_path);
fclose(fp);
free(id_ptr);
// env->ReleaseStringUTFChars(file_path,enclave_filePath);
return 0;
}
JNIEXPORT jbyteArray JNICALL Java_sgxUtils_SgxFunctions_jni_1sgx_1begin_1ec_1dh(JNIEnv *env, jobject){
printf("Begin DH \n");
if(init_happened == 1){ //Verify if the Random generators were seeded.
sgx_status_t init_status;
init_mbed(global_eid,&init_status);
init_happened = 0;
//printf("Init happened inside enclave.");
}
unsigned char* public_ec_key = (unsigned char*)malloc(EC_KEY_SIZE); //32 bytes allocated. (256)
printf("Calculating EC_DH.\n");
//Start the ECDH Ecall.
sgx_status_t ecdh_status;
create_ec_key_pair(global_eid,&ecdh_status,public_ec_key,EC_KEY_SIZE); //Send the buffer and its size.
if(ecdh_status != SGX_SUCCESS){
printf("Failed. ec_key_pair returned %d\n",ecdh_status);
}
//Copy the information to a Jbyte in order to return in a JbyteArray:
jbyte* toCopy = (jbyte*)malloc(EC_KEY_SIZE * sizeof(jbyte));
memcpy(toCopy,public_ec_key,EC_KEY_SIZE);
//Return the Public Key:
jbyteArray result = env->NewByteArray(EC_KEY_SIZE);
env->SetByteArrayRegion(result,0,EC_KEY_SIZE,toCopy);
//Free the pointers and return the arrray.
free(public_ec_key);
free(toCopy);
printf("EC_DH Calculated.\n");
return result;
}
I will omit the large output from Valgrind, it is just a huge file with '?' every line, since SGX hides the Stack trace, giving me no info on the invalid reads/Writes.
Valgrind Output
==38490== Warning: client switching stacks? SP change: 0x6a937a0 --> 0x28789d48
==38490== to suppress, use: --max-stackframe=567240104 or greater
==38490== Warning: client switching stacks? SP change: 0x28789d48 --> 0x6a937a0
==38490== to suppress, use: --max-stackframe=567240104 or greater
==38490== Warning: client switching stacks? SP change: 0x6a97220 --> 0x28789d48
==38490== to suppress, use: --max-stackframe=567225128 or greater
==38490== further instances of this message will not be shown.
==38490==
==38490== Process terminating with default action of signal 11 (SIGSEGV)
==38490== Access not within mapped region at address 0x2
==38490== at 0x27CD0B05: sig_handler_sim(int, siginfo_t*, void*) (in /opt/intel/sgxsdk/lib64/libsgx_urts_sim.so)
==38490== If you believe this happened as a result of a stack
==38490== overflow in your program's main thread (unlikely but
==38490== possible), you can try to increase the size of the
==38490== main thread stack using the --main-stacksize= flag.
==38490== The main thread stack size used in this run was 8388608.
==38490==
==38490== HEAP SUMMARY:
==38490== in use at exit: 16,636,139 bytes in 39,334 blocks
==38490== total heap usage: 55,264 allocs, 15,930 frees, 71,819,001 bytes allocated
Java Code
private void initEnclave() {
this.logger.info("Starting InitEnclave");
enclave = new SgxFunctions(this.enclaveId);
try {
File pemFile = new File(HOME_DIR + "/" + this.enclaveId + ".pem");
if(!pemFile.exists()) {
pemFile = SgxFunctions.createPem(this.enclaveId);
}
File enclaveFile = new File(HOME_DIR + "/" + this.enclaveId + "enclave_signed.so");
if(!enclaveFile.exists()) {
enclave.createSignedEnclave(HOME_DIR, pemFile.getAbsolutePath(), enclaveId);
this.logger.info("Enclave signed");
}
else
this.logger.info("Enclave file exists. Starting enclave.");
logger.info("ABSOLUTE PATH: " + enclaveFile.getAbsolutePath());
byte[] enclaveFilePath = enclaveFile.getAbsolutePath().substring(0).getBytes(StandardCharsets.UTF_8);
byte[] correctPath = Arrays.copyOf(enclaveFilePath, enclaveFilePath.length+1);
correctPath[correctPath.length-1] = '\0';
int created = enclave.jni_initialize_enclave(enclaveId,correctPath);
if(created == 0)
this.logger.info("Enclave created.");
else
this.logger.info("Enclave failed to create.");
//
// //Create DH parameters:
this.dh_params = this.enclave.jni_sgx_begin_ec_dh(); //Begin the Enclave EC parameters for DH key exchange.
this.logger.info("EC-DH Parameters created for Key exchange.");
} catch (Exception e) {
e.printStackTrace();
}
}
If I comment out the 'begin_ec_dh()' Call, the program will not segfault. However, even when running this native call, the Enclave will return an acceptable result and I am able to use the result in my Java code no problem, but only up until a certain point where it segfaults for an unkown reason.
I suspect its obviously my code, but I have no idea what is going on.
Any help is appreciated, Thank you for your help and sorry for the long post.
Edit:
I have added a printf() in order to retrieve a Crash file from the JVM over the filename Pointer.
What I dont understand is that If you look at my C code, I have allocated exactly the Array Size that comes from java (And I have added the null terminator in my Java Code, which was previously the source of another segfault), any idea what is causing this? Seems like I am dereferencing an Invalid pointer, but why is it invalid?
JVM Crash File
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f9f51fd9627, pid=9910, tid=9911
#
# JRE version: OpenJDK Runtime Environment (17.0.3+7) (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1)
# Java VM: OpenJDK 64-Bit Server VM (17.0.3+7-Ubuntu-0ubuntu0.20.04.1, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C [libc.so.6+0x188627]
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/andrecruz/Tese/Con-BFT/build/install/library/core.9910)
#
# If you would like to submit a bug report, please visit:
# Unknown
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
--------------- S U M M A R Y ------------
Command Line: -Djava.security.properties=./config/java.security -Djava.library.path=./lib/ -Dfile.encoding=UTF-8 -XX:ErrorFile=/home/andrecruz/Tese/Con-BFT/ -XX:+ShowCodeDetailsInExceptionMessages -Dlogback.configurationFile=./config/logback.xml bftsmart.demo.map.MapServer 0 10
Host: Intel(R) Core(TM) i5-6440HQ CPU # 2.60GHz, 4 cores, 7G, Ubuntu 20.04.4 LTS
Time: Sun May 29 23:13:08 2022 WEST elapsed time: 2.134101 seconds (0d 0h 0m 2s)
--------------- T H R E A D ---------------
Current thread (0x00007f9f4c012b40): JavaThread "main" [_thread_in_native, id=9911, stack(0x00007f9f5061b000,0x00007f9f5071c000)]
Stack: [0x00007f9f5061b000,0x00007f9f5071c000], sp=0x00007f9f50718c28, free space=1015k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libc.so.6+0x188627]
C [libc.so.6+0x61d6f] _IO_printf+0xaf
j sgxUtils.SgxFunctions.jni_initialize_enclave(I[B)I+0
j bftsmart.tom.ServiceReplica.initEnclave()V+248
j bftsmart.tom.ServiceReplica.<init>(ILjava/lang/String;Lbftsmart/tom/server/Executable;Lbftsmart/tom/server/Recoverable;Lbftsmart/tom/server/RequestVerifier;Lbftsmart/tom/server/Replier;Lbftsmart/tom/util/KeyLoader;I)V+147
j bftsmart.tom.ServiceReplica.<init>(ILbftsmart/tom/server/Executable;Lbftsmart/tom/server/Recoverable;I)V+17
j bftsmart.demo.map.MapServer.<init>(II)V+35
j bftsmart.demo.map.MapServer.main([Ljava/lang/String;)V+34
v ~StubRoutines::call_stub
V [libjvm.so+0x83ae75]
V [libjvm.so+0x8cf4e9]
V [libjvm.so+0x8d2392]
C [libjli.so+0x4abe]
C [libjli.so+0x84ed]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j sgxUtils.SgxFunctions.jni_initialize_enclave(I[B)I+0
j bftsmart.tom.ServiceReplica.initEnclave()V+248
j bftsmart.tom.ServiceReplica.<init>(ILjava/lang/String;Lbftsmart/tom/server/Executable;Lbftsmart/tom/server/Recoverable;Lbftsmart/tom/server/RequestVerifier;Lbftsmart/tom/server/Replier;Lbftsmart/tom/util/KeyLoader;I)V+147
j bftsmart.tom.ServiceReplica.<init>(ILbftsmart/tom/server/Executable;Lbftsmart/tom/server/Recoverable;I)V+17
j bftsmart.demo.map.MapServer.<init>(II)V+35
j bftsmart.demo.map.MapServer.main([Ljava/lang/String;)V+34
v ~StubRoutines::call_stub
siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000020
Register to memory mapping:
RAX=0x0000000000000010 is an unknown value
RBX=0x00007f9f51ec7b43: <offset 0x0000000000076b43> in /lib/x86_64-linux-gnu/libc.so.6 at 0x00007f9f51e51000
RCX=0x000000000000000f is an unknown value
RDX=0x000000000000002f is an unknown value
RSP=0x00007f9f50718c28 is pointing into the stack for thread: 0x00007f9f4c012b40
RBP=0x00007f9f507191a0 is pointing into the stack for thread: 0x00007f9f4c012b40
RSI=0x00007f9f50719168 is pointing into the stack for thread: 0x00007f9f4c012b40
RDI=0x0000000000000020 is an unknown value
R8 =0x00000000ffffffff points into unknown readable memory: 00
R9 =0x0000000000000009 is an unknown value
R10=0x00007f9f50610099: <offset 0x0000000000007099> in /home/andrecruz/Tese/Con-BFT/build/install/library/lib/libSgx.so at 0x00007f9f50609000
R11=0x000000000000002f is an unknown value
R12=0x00007f9f5203e6a0: _IO_2_1_stdout_+0x0000000000000000 in /lib/x86_64-linux-gnu/libc.so.6 at 0x00007f9f51e51000
R13=0x00007f9f5061008f: <offset 0x000000000000708f> in /home/andrecruz/Tese/Con-BFT/build/install/library/lib/libSgx.so at 0x00007f9f50609000
R14=0x00007f9f507191b0 is pointing into the stack for thread: 0x00007f9f4c012b40
R15=0x0000000000000073 is an unknown value
# 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());
}
We are using Tess4J/Tesseract to perform OCR on a webapp. On Windows everything works fine but when deployed on a Linux machine(CentOS 6.8) the program crashes and automatically kill the Apache tomcat server.
We are read more than one file(different file) simultaneously.if we run the OCR it running approximately 1 minutes after it through fatal error. Can you please suggest how to resolve?
A fatal error has been detected by the Java Runtime Environment:
SIGSEGV (0xb) at pc=0x00007f7d5934ff90, pid=17649,
tid=140176377489152
JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27)
Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode linux-amd64 compressed oops)
Problematic frame:
C [libtesseract.so.3.0.2+0x22cf90] tesseract::HistogramRect(unsigned char const*, int, int, int, int, int, int, int*)+0x70
Failed to write core dump. Core dumps have been disabled. To enable core dumping, try ulimit -c unlimited before starting Java again
I fixed it by resizing the image to a fixed size (you could do a percentage resize I guess) in javacv before passing it to tess4j.
Example of my resize method.
public static IplImage resize(IplImage img_source){
IplImage resized = IplImage.create(600, 480, img_source.depth(), img_source.nChannels());
cvResize(img_source,resized);
return resized;
}
Then I do my tesseract extraction below:
public static String extract(BufferedImage bi, Rectangle r) throws CvHandler, IOException, TesseractException{
ITesseract tess = new Tesseract();
String tessPath = getTess();
tess.setPageSegMode(1);
tess.setLanguage("eng");
tess.setDatapath(tessPath);
tess.setOcrEngineMode(TessOcrEngineMode.OEM_DEFAULT);
tess.setTessVariable("load_system_dawg", "false");
tess.setTessVariable("load_freq_dawg", "false");
tess.setTessVariable("tessedit_create_hocr", "0");
tess.setTessVariable("tessedit_char_whitelist","ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
String result = "";
if (!r.getBounds().isEmpty()){
try{
result = tess.doOCR(bi, r);
}catch(TesseractException e){
throw new CvHandler(e.getMessage());
}
}else result = tess.doOCR(bi);
return result;
}
Helper method for converting IplImage to BufferedImage Source:
public static BufferedImage convertIplToBuffered(IplImage img){
OpenCVFrameConverter.ToIplImage grabberConverter = new OpenCVFrameConverter.ToIplImage();
Java2DFrameConverter paintConverter = new Java2DFrameConverter();
Frame frame = grabberConverter.convert(img);
BufferedImage img_result = paintConverter.getBufferedImage(frame,1);
return img_result;
}
I'm trying to run the unit tests in the tess4j distribution currently. And while running one of the unit tests, java crashed with the following error:
TessBaseAPIGetIterator
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6718f834, pid=5612, tid=3592
#
# JRE version: 7.0_17-b02
# Java VM: Java HotSpot(TM) Client VM (23.7-b01 mixed mode, sharing windows-x86 )
# Problematic frame:
# C [libtesseract302.dll+0xf834] tesseract::TessBaseAPI::Init+0x34
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# G:\Final year project\eclipse stuff\Testings\hs_err_pid5612.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Can i please get help? i'm fairly sure that the DLL file is not corrupt and neither is my harddisk. i'm using the Windows 8 OS and the latest version of eclipse to build the project.
The code is:
import java.io.File;
import net.sourceforge.tess4j.*;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.*;
import java.util.Arrays;
import javax.imageio.ImageIO;
import net.sourceforge.tess4j.TessAPI1.*;
import net.sourceforge.vietocr.ImageIOHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
public class TesseractExample{
String datapath = "G:\\Final year project\\eclipse stuff\\tessdemo\\tessdata";
String language = "eng";
String expOCRResult = "The (quick) [brown] {fox} jumps!\nOver the $43,456.78 <lazy> #90 dog";
TessAPI1.TessBaseAPI handle;
public void testResultIterator() throws Exception {
System.out.println("TessBaseAPIGetIterator");
String lang = "eng";
File tiff = new File("eurotext.tif");
BufferedImage image = ImageIO.read(new FileInputStream(tiff)); // require jai-imageio lib to read TIFF
ByteBuffer buf = ImageIOHelper.convertImageData(image);
int bpp = image.getColorModel().getPixelSize();
int bytespp = bpp / 8;
int bytespl = (int) Math.ceil(image.getWidth() * bpp / 8.0);
TessAPI1.TessBaseAPIInit3(handle, datapath, lang);
TessAPI1.TessBaseAPISetPageSegMode(handle, TessAPI1.TessPageSegMode.PSM_AUTO);
TessAPI1.TessBaseAPISetImage(handle, buf, image.getWidth(), image.getHeight(), bytespp, bytespl);
TessAPI1.TessBaseAPIRecognize(handle, null);
TessAPI1.TessResultIterator ri = TessAPI1.TessBaseAPIGetIterator(handle);
TessAPI1.TessPageIterator pi = TessAPI1.TessResultIteratorGetPageIterator(ri);
TessAPI1.TessPageIteratorBegin(pi);
System.out.println("Bounding boxes:\nchar(s) left top right bottom confidence font-attributes");
int height = image.getHeight();
do {
Pointer ptr = TessAPI1.TessResultIteratorGetUTF8Text(ri, TessAPI1.TessPageIteratorLevel.RIL_WORD);
String word = ptr.getString(0);
TessAPI1.TessDeleteText(ptr);
float confidence = TessAPI1.TessResultIteratorConfidence(ri, TessAPI1.TessPageIteratorLevel.RIL_WORD);
IntBuffer leftB = IntBuffer.allocate(1);
IntBuffer topB = IntBuffer.allocate(1);
IntBuffer rightB = IntBuffer.allocate(1);
IntBuffer bottomB = IntBuffer.allocate(1);
TessAPI1.TessPageIteratorBoundingBox(pi, TessAPI1.TessPageIteratorLevel.RIL_WORD, leftB, topB, rightB, bottomB);
int left = leftB.get();
int top = topB.get();
int right = rightB.get();
int bottom = bottomB.get();
System.out.print(String.format("%s %d %d %d %d %f", word, left, top, right, bottom, confidence));
System.out.println(String.format("%s %d %d %d %d", str, left, height - bottom, right, height - top)); // training box coordinates
IntBuffer boldB = IntBuffer.allocate(1);
IntBuffer italicB = IntBuffer.allocate(1);
IntBuffer underlinedB = IntBuffer.allocate(1);
IntBuffer monospaceB = IntBuffer.allocate(1);
IntBuffer serifB = IntBuffer.allocate(1);
IntBuffer smallcapsB = IntBuffer.allocate(1);
IntBuffer pointSizeB = IntBuffer.allocate(1);
IntBuffer fontIdB = IntBuffer.allocate(1);
String fontName = TessAPI1.TessResultIteratorWordFontAttributes(ri, boldB, italicB, underlinedB,
monospaceB, serifB, smallcapsB, pointSizeB, fontIdB);
boolean bold = boldB.get() == TessAPI1.TRUE;
boolean italic = italicB.get() == TessAPI1.TRUE;
boolean underlined = underlinedB.get() == TessAPI1.TRUE;
boolean monospace = monospaceB.get() == TessAPI1.TRUE;
boolean serif = serifB.get() == TessAPI1.TRUE;
boolean smallcaps = smallcapsB.get() == TessAPI1.TRUE;
int pointSize = pointSizeB.get();
int fontId = fontIdB.get();
System.out.println(String.format(" font: %s, size: %d, font id: %d, bold: %b," +
" italic: %b, underlined: %b, monospace: %b, serif: %b, smallcap: %b",
fontName, pointSize, fontId, bold, italic, underlined, monospace, serif, smallcaps));
} while (TessAPI1.TessPageIteratorNext(pi, TessAPI1.TessPageIteratorLevel.RIL_WORD) == TessAPI1.TRUE);
}
public static void main(String[] args) {
TesseractExample instance=new TesseractExample();
try {
instance.testResultIterator();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
Thank you!
Looks like handle has not been initialized.
handle = TessAPI1.TessBaseAPICreate();
My Processing code is below.
import hypermedia.video.*;
import processing.video.*;
import java.awt.Rectangle;
OpenCV opencv;
int width = 320;
int height = 240;
void setup() {
size( 320, 240 ); //set window size
opencv = new OpenCV( this ); //setup openCV
opencv.capture( width, height ); // open video stream
opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT );
}
void draw(){
opencv.read();
image(opencv.image(), 0, 0);
Rectangle[] faces = opencv.detect( 1.2, 2, OpenCV.HAAR_DO_CANNY_PRUNING, 40, 40 );
noFill();
stroke(255,0,0);
for( int i=0; i<faces.length; i++ ) {
rect( faces[i].x, faces[i].y, faces[i].width, faces[i].height );
}
}
This code works for few seconds then an exception occurs.
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d961b22, pid=232, tid=4008
#
# JRE version: 6.0_33-b03
# Java VM: Java HotSpot(TM) Client VM (20.8-b03 mixed mode windows-x86 )
# Problematic frame:
# V [jvm.dll+0xa1b22]
#
# An error report file with more information is saved as:
# C:\Documents and Settings\Administrator\Desktop\processing-2.0b7\hs_err_pid232.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
i think it is a memory allocation issue with opencv_core.CvMemStorage. this is a class that's not exposed in your library. i am having the same problem. I'm using javacv (directly, not javacvpro) because i want to run multiple haar cascades (you can load only one with javacvpro or the older hypermedia.video.*). if i run ALL of them on EACH frame, i'm good. if i run a different detector on each frame (and then cycle thru the detectors again), i get this error after a few cycles.
the snippet below FAILS, but it is what i want to do (process each subsequent frame with a different detector):
// Using JavaCV directly, not JavaCVPro!
import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.*;
import com.googlecode.javacv.*;
import com.googlecode.javacv.cpp.*;
String cascades[] = {
"haarcascade_eye.xml", // 0
"haarcascade_eye_tree_eyeglasses.xml", // 1
"haarcascade_frontalface_alt.xml" // 2
}
int detectors[] = {1,3};
// haar detectors to use
String cascPath = "C:/opencv/data/haarcascades/";
// preload multiple classifiers. can do this with javacvpro, not with javacv or hypermedia.video.*
void haarSetup() {
for (int i = 0; i < detectors.length; i++) {
String classifierFile = cascPath+cascades[detectors[i]];
classifier[i] =
new opencv_objdetect.CvHaarClassifierCascade(opencv_core.cvLoad(classifierFile));
}
storage = opencv_core.CvMemStorage.create();
opencv_core.cvClearMemStorage(storage); // is this needed? couldn't hurt, right?
}
// contains list of preloaded haar cascades. code not included here...
opencv_core.CvSeq features[] = new opencv_core.CvSeq[detectors.length];
int whichHaar = 0;
// run one cascade per frame, then cycle through them.
void processHaars(PImage piz) {
// convert to IplImage...
BufferedImage imgBuf = (BufferedImage) piz.getNative();
opencv_core.IplImage iplImgOut=opencv_core.IplImage.createFrom(imgBuf);
// do one haar cascade per invocation.
int ii = whichHaar;
features[ii] = opencv_objdetect.cvHaarDetectObjects(iplImgOut, classifier[ii], storage, 1.1, 3, opencv_objdetect.CV_HAAR_DO_CANNY_PRUNING);
whichHaar++;
if (whichHaar >= detectors.length){
whichHaar = 0;
// is THIS causing the problem??
opencv_core.cvClearMemStorage(storage);
}
}
this snippet WORKS forever, but i don't want what it does (run all detectors on a single frame):
void processHaars(PImage piz) {
// convert to IplImage...
BufferedImage imgBuf = (BufferedImage) piz.getNative();
opencv_core.IplImage iplImgOut=opencv_core.IplImage.createFrom(imgBuf);
for (ii=0; ii<detectors.length; ii++)
faces[ii] = opencv_objdetect.cvHaarDetectObjects(iplImgOut, classifier[ii], storage, 1.1, 3, opencv_objdetect.CV_HAAR_DO_CANNY_PRUNING);
opencv_core.cvClearMemStorage(storage);
}
If i find a full solution, I'll post it.