J2ME obfuscated app stacktrace - java
I'm debugging J2ME (written in eclipse) code on nokia N95 (wasn't written by me) trying to find error and printing out stacktrace gave me this:
03:08:479 TSKR. Error:
java.lang.NullPointerException: 0
- java.lang.String.<init>(), bci=6
- v.b(), bci=9
- v.e(), bci=805
- v.e(), bci=3
Could anyone please help me to understand that? Which line , where to look for and is there a way to understand it or at least get some valuable and usefull information.
Thank you
UPDATE
Sorry.. Here's the function that throws error:
public void bluetoothFileProcessBytes(){//--------tracing out of memory error
try{
partCurrentLoop++;
fileCurrentLoop++;
debug("Loop " + fileCurrentLoop + " of " + fileTotalLoops);
bluetoothUpdateBytes(fileDataString.length());
guiUpdateProgressBar(true, partCurrentLoop, partTotalLoops);
// LOOP Step 2: If there is no byte[] created for storing the bytes, create it.
if (fileBytesIsEmpty) {
if (partCurrentNumber == partTotalNumber)
{
fileBytes = new byte[fileSize % (loopsPerHttpComm * BYTES_PER_LOOP)];
}
else fileBytes = new byte[loopsPerHttpComm * BYTES_PER_LOOP];
}
fileBytesIsEmpty = false;
//LOOP Step 3: fill in the byte array with data from StringBuffer
for (int i = 0; i < fileDataString.length(); i++)
{
j = i + (partCurrentLoop - 1) * BYTES_PER_LOOP;
c = fileDataString.charAt(i);
fileBytes[j] = (byte) c;
}
c=0;
j=0;
i=0;
//LOOP Step 4: Send the email if the byte array is full with a new HttpComm Thread
if ((fileCurrentLoop % loopsPerHttpComm == 0
|| fileCurrentLoop == fileTotalLoops) && checkHttpCommStatus()) {
// update partName and httpCommStatus
String partName = fileName + " .part " + partCurrentNumber;
httpCommStatus = HTTP_RUNNING;
if (fileCurrentLoop == fileTotalLoops) { // FILE_END
debug("New HttpComm Thread: FILE END");
httpCommUpdateBytes(fileBytes.length);//<===================remove
httpCommSucceeded();//<====================================remove
/*new Thread(new HttpFileEnd(this, fileBytes, toAddress, fromAddress, fromName, digidownMAC, partName, fileName, fileSize, digidownSoftwareVersion, partCurrentNumber, //<===============uncomment
partTotalNumber, DigidownApp.textObject.getActiveLanguage())).start();*/
} else { // FILE_PART
//debug("Step 5");//<--------------------------------------------------------------------------------<-remove
debug("New HttpComm Thread: FILE PART: " + partName);
debug(">>>>>SEEEENDIIIING!<<<<<<<<");//<===========remove
httpCommUpdateBytes(fileBytes.length);//<================remove
httpCommSucceeded();//<==============================remove
/*new Thread(new HttpFilePart(this, fileBytes, toAddress, fromAddress, fromName,//<===============uncomment
digidownMAC, partName, fileSize, digidownSoftwareVersion,
partCurrentNumber, DigidownApp.textObject.getActiveLanguage())).start();*/
// Updating the new partTotalLoops
if (partCurrentNumber == partTotalNumber){
partTotalLoops = fileTotalLoops - (loopsPerHttpComm * (partCurrentNumber - 1));
} else partTotalLoops = loopsPerHttpComm;
partCurrentNumber++;
partCurrentLoop = 0;
}
fileBytesIsEmpty = true;
}
// Leave the loop if failed
if (!errorHandlerActivated) {
if (fileCurrentLoop < fileTotalLoops)
{
try{
bluetoothIOStream.getFileBytes();//-throws null pointer exception !
}catch(RuntimeException ea){debug("Wammaaa!!! " + ea.toString());
ea.printStackTrace();}
}
else if(fileCurrentLoop == fileTotalLoops && checkHttpCommStatus())
{ bluetoothIOStream.getFileEnd(); }
}
}
catch(RuntimeException e1)
{
Alert alert = new Alert("Fckn error!", e1.toString(), null, null);
alert.setTimeout(Alert.FOREVER);
debug("Error:");
System.err.println();
e1.printStackTrace();
//throw e1;
}
}
..and the stack trace of unobfuscated app; this time it was null pointer exception after
// Leave the loop if failed:
02:57:382 TSKR. Loop 972 of 1349
02:57:383 BIOS. Rec 978
02:57:588 TSKR. Loop 973 of 1349
02:57:590 BIOS. Rec 979
02:57:815 TSKR. Wammaaa!!! java.lang.NullPointerException: 0
java.lang.NullPointerException: 0
- java.lang.String.<init>(), bci=6
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.readLineAsString(), bci=9
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=844
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getFileBytes(), bci=3
- net.digidown.m.digidown.TaskRunner.bluetoothFileProcessBytes(), bci=430
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=857
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getFileBytes(), bci=3
- net.digidown.m.digidown.TaskRunner.bluetoothFileProcessBytes(), bci=430
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=857
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getFileBytes(), bci=3
- net.digidown.m.digidown.TaskRunner.bluetoothFileProcessBytes(), bci=430
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=857
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getFileBytes(), bci=3
- net.digidown.m.digidown.TaskRunner.bluetoothFileProcessBytes(), bci=430
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=857
Goes like that for a while and then..:
- net.digidown.m.digidown.TaskRunner.bluetoothDoCommand_file(), bci=227
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=829
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getFileSettings(), bci=9
- net.digidown.m.digidown.TaskRunner.bluetoothTask(), bci=90
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=513
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getTask(), bci=2
- net.digidown.m.digidown.TaskRunner.bluetoothTask(), bci=172
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=513
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getTask(), bci=2
- net.digidown.m.digidown.TaskRunner.bluetoothConnected(), bci=89
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=444
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.getVariable(), bci=426
- net.digidown.m.digidown.bluetooth.BluetoothIOStream.run(), bci=366
- java.lang.Thread.run(), bci=11
03:01:211 TSKR. Finished Task
03:01:212 BIOS. Rec 6
03:01:356 BIOS. task = >
03:01:357 TSKR. :: Got Task: (0x3e)
03:01:358 TSKR.
03:01:359 TSKR. ERROR HANDLER: 116 - Bluetooth communication error
03:01:389 BIOS. Initiated
03:01:389 BIOS. About to read
03:01:394 BIOS. Phone(InitiateDigidownError) received: '0x3e 0xea Data CK'
03:01:397 BIOS. About to writeLine 'error'
03:01:468 BIOS. quitStatus = QUIT_STATUS
Your problem seems to be obfuscation.
The build process of your eclipse application probably uses a tool like proguard to increase the performance and decrease the size of the application .jar file that will be deployed in the field.
One of the thing obfuscation does is rewrite class and method names into much smaller names, hence the completely unintelligible last 3 lines of your stack trace.
You need to produce an unobfuscated .jar file to use when you want to debug your application.
(at least until you find an issue that only happens on the obfuscated version of your application. it happens)
Eclipse should allow you to turn obfuscation off (or reduce it to its lowest level) by modifying your project properties. Failing that, manually and temporarily hacking the ant .xml files used to build your .jar file will do the trick.
Obfuscation parameters should include the name of your MIDlet class so that its startApp() method is not renamed.
Your problem may be solve in two ways:
Run your application without obfuscation. So the output shows exact method names.
Put System.out.println('method_name::sample_tag') in your method and lines that the problem may be from them. Then in the output you can trace your execution and you can find the point that the problem occurs.
Related
java.nio.ByteBuffer wrap method partly working with sbt run
I have an issue where I read a bytestream from a big file ~ (100MB) and after some integers I get the value 0 (but only with sbt run ). When I hit the play button on IntelliJ I get the value I expected > 0. My guess was that the environment is somehow different. But I could not spot the difference. // DemoApp.scala import java.nio.{ByteBuffer, ByteOrder} object DemoApp extends App { val inputStream = getClass.getResourceAsStream("/HandRanks.dat") val handRanks = new Array[Byte](inputStream.available) inputStream.read(handRanks) inputStream.close() def evalCard(value: Int) = { val offset = value * 4 println("value: " + value) println("offset: " + offset) ByteBuffer.wrap(handRanks, offset, handRanks.length - offset).order(ByteOrder.LITTLE_ENDIAN).getInt } val cards: List[Int] = List(51, 45, 14, 2, 12, 28, 46) def eval(cards: List[Int]): Unit = { var p = 53 cards.foreach(card => { println("p = " + evalCard(p)) p = evalCard(p + card) }) println("result p: " + p); } eval(cards) } The HandRanks.dat can be found here: (I put it inside a directory called resources) https://github.com/Robert-Nickel/scala-texas-holdem/blob/master/src/main/resources/HandRanks.dat build.sbt is: name := "LoadInts" version := "0.1" scalaVersion := "2.13.4" On my windows machine I use sbt 1.4.6 with Oracle Java 11 You will see that the evalCard call will work 4 times but after the fifth time the return value is 0. It should be higher than 0, which it is when using IntelliJ's play button.
You are not reading a whole content. This val handRanks = new Array[Byte](inputStream.available) allocates only as much as InputStream buffer and then you read the amount in buffer with inputStream.read(handRanks) Depending of defaults you will process different amount but they will never be 100MB of data. For that you would have to read data into some structure in the loop (bad idea) or process it in chunks (with iterators, stream, etc). import scala.util.Using // Using will close the resource whether error happens or not Using(getClass.getResourceAsStream("/HandRanks.dat")) { inputStream => def readChunk(): Option[Array[Byte]] = { // can be done better, but that's not the point here val buffer = new Array[Byte](inputStream.available) val bytesRead = inputStream.read(buffer) if (bytesRead >= 0) Some(buffer.take(bytesRead)) else None } #tailrec def process(): Unit = { readChunk() match { case Some(chunk) => // do something process() case None => // nothing to do - EOF reached } } process() }
ASE is terminating this process when trying to install the jar file (Msg 5702, Level 10, State 1)
I have an SAP ASE 16 server on a Windows OS. I have enabled the java service: sp_configure 'enable java' Parameter Name Default Memory Used Config Value Run Value Unit Type -------------- ----------- ----------- ------------ ------------ ------ ------ enable java 0 0 1 1 switch static Rows affected (1) Time (0.094 s) I have created a basic class to test the service (JDBCExamples.java): import java.sql.*; // JDBC public class JDBCExamples { public static void main(String args[]){ if (args.length != 2) { System.out.println("\n Usage: " + "name secondName \n"); return; } try { String name = args[0]; String secondName = args[1].toLowerCase(); System.out.println("\n HOLA " + name + " " + secondName +" FUNCIONO!!!\n"); } catch (Exception e) { System.out.println("\n Exception: "); e.printStackTrace(); } } } I have the class file JDBCExamples.class and I make a file JDBCExamples.jar. When I try to install the jar file it shows the error message: instjava -f JDBCExamples.jar -SDEFAULT -Uuser -Ppassword -Ddatabase -new Server Message: - Msg 5702, Level 10, State 1: ASE is terminating this process. I don't see any in log database. Any idea what the problem is? Update: I posted the same problem in https://answers.sap.com/questions/13241081/ase-is-terminating-this-process-when-trying-to-ins.html In this post suspect the issue is caused by an ASE bug fixed in PL06: 2687973 - NTPCI__exit(1); Native Thread failed to unwind - SAP ASE http://service.sap.com/sap/support/notes/2687973 I have a trial version and I can not download a newer patch (PL06 at least but recommend PL09 as most recent) Does anyone have this patch?
R, Java, RCaller
So i'm trying to use RCaller to do the following (in psuedo-code): x=simarray(..) // in java 'send x to R' run y = rlogcon(40000, sort(x)) //in R, rlogcon is part of rlogcondens and the function produces a numeric vector of length 40000 //send y to java and hold it in a double matrix. this is what i've got in my main function (i've adapted one of the examples I found, but I must have made a mistake/misunderstood something. I tested the example on my machine, and it worked as expected): RCaller caller = new RCaller(); RCode code = new RCode(); double[] x = a.simarraysimbeta(5, 1, 100, 30, 40); //some method savesample("simarraysimbeta.txt",x); //testing, it works. caller.setRscriptExecutable("C:\\Program Files\\R\\R-3.1.0\\bin\\Rscript.exe"); code.addDoubleArray("X", x); code.addRCode("library(logcondens)"); //rlogcon is part of logcondens library code.addRCode("ols <- rlogcon(40,000, sort(X))"); caller.setRCode(code); caller.runAndReturnResult("ols"); double[] residuals = caller.getParser().getAsDoubleArray("X_star"); and the following relevent imports: import rcaller.RCaller; import rcaller.RCode; import rcaller; I get the following error: Exception in thread "main" rcaller.exception.ParseException: Can not handle R results due to : rcaller.exception.ParseException: Can not parse output: The generated file C:\Users\jo\AppData\Local\Temp\Routput8804446513483695061 is empty here is the output: concat<-function(to,...){ to<-paste(to,toString(...),sep=""); return(to); } cleanNames<-function(names){ cleanNames<-paste(unlist(strsplit(names,"\\.")),collapse="_"); Exception in thread "main" rcaller.exception.ParseException: Can not handle R results due to : rcaller.exception.ParseException: Can not parse output: The generated file C:\Users\jo\AppData\Local\Temp\Routput8804446513483695061 is empty cleanNames<-paste(unlist(strsplit(cleanNames,"<")),collapse=""); at rcaller.RCaller.runAndReturnResult(RCaller.java:409) cleanNames<-paste(unlist(strsplit(cleanNames,">")),collapse=""); at dissertation.Dissertation.main(Dissertation.java:709) cleanNames<-paste(unlist(strsplit(cleanNames," ")),collapse=""); cleanNames<-paste(unlist(strsplit(cleanNames,"\\(")),collapse=""); cleanNames<-paste(unlist(strsplit(cleanNames,"\\)")),collapse=""); cleanNames<-paste(unlist(strsplit(cleanNames,"\\[")),collapse=""); cleanNames<-paste(unlist(strsplit(cleanNames,"\\]")),collapse=""); cleanNames<-paste(unlist(strsplit(cleanNames,"\\*")),collapse=""); return(cleanNames); } makevectorxml<-function(code,objt,name=""){ xmlcode<-code; if(name==""){ varname<-cleanNames(deparse(substitute(obj))); }else{ varname<-name; } obj<-objt; n <- 0; m <- 0 mydim <- dim(obj) if(!is.null(mydim)){ n <- mydim[1]; m <- mydim[2]; }else{ n <- length(obj); m <- 1; } if(is.matrix(obj)) obj<-as.vector(obj); if(typeof(obj)=="language") obj<-toString(obj); if(typeof(obj)=="logical") obj<-as.character(obj); if(is.vector(obj) && is.numeric(obj)){ xmlcode<-paste(xmlcode,"<variable name=\"",varname,"\" type=\"numeric\" n=\"", n, "\" m=\"", m, "\">",sep=""); for (i in obj){ xmlcode<-paste(xmlcode,"<v>",sep=""); xmlcode<-paste(xmlcode,toString(i),sep=""); xmlcode<-paste(xmlcode,"</v>",sep=""); } xmlcode<-paste(xmlcode,"</variable>\n",sep=""); } if(is.vector(obj) && is.character(obj)){ xmlcode<-paste(xmlcode,"<variable name=\"",varname,"\" type=\"character\">\n",sep=""); for (i in obj){ xmlcode<-paste(xmlcode,"<v>",sep=""); xmlcode<-paste(xmlcode,toString(i),sep=""); xmlcode<-paste(xmlcode,"</v>",sep=""); } xmlcode<-paste(xmlcode,"</variable>\n"); } return(xmlcode); } makexml<-function(obj,name=""){ xmlcode<-"<?xml version=\"1.0\"?>\n"; xmlcode<-concat(xmlcode,"<root>\n"); if(!is.list(obj)){ xmlcode<-makevectorxml(xmlcode,obj,name); } else{ objnames<-names(obj); for (i in 1:length(obj)){ xmlcode<-makevectorxml(xmlcode,obj[[i]],cleanNames(objnames[[i]])); } } xmlcode<-concat(xmlcode,"</root>\n"); return(xmlcode); } X<-c(##100 doubles); library(logcondens) ols <- rlogcon(40,000, sort(X)) cat(makexml(obj=ols, name="ols"), file="C:/Users/##/AppData/Local/Temp/Routput8804446513483695061")
40,000 shold be 40000 in your code.
There are two ways in which a file remains empty: there is an error in R code the result is NULL or NA I recommend you to use tryCach in R ols <- tryCatch({ rlogcon(40,000, sort(X)) }, error = function(e) { -1 }) And at the end if ols equlas -1, you'll know that there was an error in R
Calling R from Java using RServe weird error
I have this code : import org.rosuda.REngine.Rserve.RConnection; public class TestProgram { public static void main(String[] args) { try { RConnection rConnection = new RConnection(); // make a new local connection on default port (6311) rConnection.eval("for(i in 1:.Machine$integer.max){}"); System.out.println("Done!"); } catch(Exception e) { System.out.println(e.toString()); } } } I get this exception : org.rosuda.REngine.Rserve.RserveException: eval failed, request status: error code: 127 If I change : rConnection.eval("for(i in 1:.Machine$integer.max){}"); to rConnection.eval("for(i in 1:777){}"); it does work :-) Does anyone know what's going on ? P.S I started Rserve from R ( same machine ) using : >library(Rserve) >Rserve() > sessionInfo() R version 3.0.1 (2013-05-16) Platform: x86_64-w64-mingw32/x64 (64-bit) locale: [1] LC_COLLATE=English_United States.1252 [2] LC_CTYPE=English_United States.1252 [3] LC_MONETARY=English_United States.1252 [4] LC_NUMERIC=C [5] LC_TIME=English_United States.1252 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] Rserve_1.7-3 loaded via a namespace (and not attached): [1] tools_3.0.1 OS is Windows 8. I did not try this on Linux.
You should check the return from the eval function to see if it extends try-error. If it does then print it to debug string to get the error message. The section below was taken from the Rserve documentation. This will give you the error message that caused the 127. You should also probably use parseAndEval rather than just eval. http://www.rforge.net/Rserve/faq.html c.assign(".tmp.", myCode); REXP r = c.parseAndEval("try(eval(parse(text=.tmp.)),silent=TRUE)"); if (r.inherits("try-error")) System.err.println("Error: "+r.toString()) else { // success .. } You might also want to check this link in case it is a restriction of your R environment. R - Big Data - vector exceeds vector length limit EDIT: Fixing Chris Hinshaw's answer c.assign(".tmp.", myCode); REXP r = c.parseAndEval("try(eval(parse(text=.tmp.)),silent=TRUE)"); if (r.inherits("try-error")) System.err.println("Error: " + r.asString()) else { // success .. } Note that the println should be using asString(), not toString()
How to get the line number in error in java?
I know that the line in error is to_return = find(list,false); How can I get the line number of this line when there is NullPointerException type of error? Or in line number in general? I tried few things. The closest is this one Called.getLineNumber() which gives me the line number of StackTraceElement Called = new Throwable().fillInStackTrace().getStackTrace()[0]; public TestObject[] myfind(Subitem list )throws Exception{ TestObject[]to_return=null; try { to_return = find(list,false); } catch (RationalTestException ex) { //logStoreException(ex); StackTraceElement Called = new Throwable().fillInStackTrace().getStackTrace()[0]; StackTraceElement Calling = new Throwable().fillInStackTrace().getStackTrace()[1]; throw new Exception (this.add_debugging_info(Called, Calling, ex.getMessage())); } catch (NullPointerException npe) { StackTraceElement Called = new Throwable().fillInStackTrace().getStackTrace()[0]; StackTraceElement Calling = new Throwable().fillInStackTrace().getStackTrace()[1]; logStoreException(npe); System.out.println("Line number: "+npe.getStackTrace()[0].getLineNumber()); System.out.println("Line number2: "+Integer.toString(Called.getLineNumber())); System.out.println(this.add_debugging_info(Called, Calling, npe.getMessage())); throw new Exception (this.add_debugging_info(Called, Calling, npe.getMessage())); } catch (Exception ex) { StackTraceElement Called = new Throwable().fillInStackTrace().getStackTrace()[0]; StackTraceElement Calling = new Throwable().fillInStackTrace().getStackTrace()[1]; throw new Exception (this.add_debugging_info(Called, Calling, ex.getMessage())); } finally { //unregisterAll(); //unregister(to); return to_return; } }
If you just want the current stack trace, use Thread.currentThread().getStackTrace() If you want to force the JVM to fill in the stack traces, please set the option -XX:-OmitStackTraceInFastThrow on your JVM.
When running in Eclipse, to get the line number itself, you need to get the StackTrace array and call getLineNumber() on it. The following worked for me in my Utils class, isSessionConnectible method: ... catch (ClassFormatError cfe) { logger.error("Problem ClassFormatError connecting. " + cfe.getMessage() + " " + cfe.getCause()); int size = cfe.getStackTrace().length - 1; logger.error(" Root cause: " + cfe.getStackTrace()[size].getMethodName() + " " + cfe.getStackTrace()[size].getClassName()); if (size>1) { logger.error(" Penultimate cause: method=" + cfe.getStackTrace()[size-1].getMethodName() + " class=" + cfe.getStackTrace()[size-1].getClassName() + " line=" + cfe.getStackTrace()[size-1].getLineNumber()); } Result when thrown: 2018-07-06 12:00:12 ERROR Utils:319 - Problem ClassFormatError connecting to Hibernate. Absent Code attribute in method that is not native or abstract in class file javax/transaction/SystemException null 2018-07-06 12:00:12 ERROR Utils:322 - Root cause: main <mypackage>.Utils 2018-07-06 12:00:12 ERROR Utils:324 - Penultimate cause: method=isSessionConnectible class=<mypackage>.Utils line=306 BTW, in Eclipse, make sure that Window --> Preferences --> Java --> Compiler has the checkbox marked at "Add line number attributes to generated class files".