4

In Java, I make the call:

String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
    .split(SINGLE_NEW_LINE)[0];
System.out.println("Trying to get integer value of '" + chunkSizeAsString + "'");
Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109

And get output:

Trying to get integer value of '8d'
Exception in thread "Thread-2" java.lang.NumberFormatException: For input string: "8d"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:481)
    at java.lang.Integer.valueOf(Integer.java:556)
    at ProxyWorker.handleRequest(ProxyWorker.java:109)
    at ProxyWorker.run(ProxyWorker.java:41)
    at java.lang.Thread.run(Thread.java:745)

So basically, I am calling Integer.valueOf("8d", 16) and receiving a NumberFormatException. I've seen lots of examples where the OP had forgotten to specify the correct radix, or the resulting number was outside the bounds of and Integer, Long, etc. But 0x8d = 141, which is comfortably within the bounds of an Integer.

So my question is, why is this happening, and how might I fix it?

N.B. As you can see, I am getting chunkSizeAsString ("8d") through a parsing monstrosity, and suspect there might be invisible characters involved. I have checked for "\u200e" and"\u200f" as mentioned here, and "\\p{C}" as mentioned here using the following addition above line 109:

chunkSizeAsString = chunkSizeAsString.replaceAll("\u200e", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("\u200f", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("[^\\p{Print}]", ""); 

But this has not changed the output.

Edit: I am using jdk1.7.0_7, and the vendor is 'Oracle Corporation'. Thanks fge.

Edit 2: Updated jdk to 1.7u79 and realized I need to get the java vendor from the server where I am running and testing, not my home dev environment:

java version "1.7.0_79"

OpenJDK Runtime Environment (fedora-2.5.5.0.fc20-x86_64 u79-b14)

OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)

Edit 3: Following suggestions, I have done some sanity tests:

  • Tests that check Integer.valueOf("8d", 16) and Integer.parseInt("8d", 16) pass
  • chunkSizeAsString.equals("8d") is True
  • chunkSizeAsString.length() = 2
  • integer values of the characters are 56 and 100, which are the ASCII codes for "8" and "d", all respectively
Community
  • 1
  • 1
Tait
  • 61
  • 6
  • 3
    Which version of Java (vendor, revision etc)? Also, try and dump all characters from the string – fge Apr 26 '15 at 21:46
  • I have tried iterating through all the characters in `chunkedSizeAsString` , quoting each one (so I'd see unprintable characters). Only '8' and 'd' were found. – Tait Apr 26 '15 at 22:03
  • Can you try with a more recent version of the JDK? 7u7 is not exactly "fresh"... – fge Apr 26 '15 at 22:07
  • Run `chunkSizeAsString` through something like this in your environment, see if you see something odd. http://repl.it/lED/1 – jdphenix Apr 26 '15 at 22:09
  • @jdphenix, tried it, nothing odd (just '56 100'). To fge, working on it – Tait Apr 26 '15 at 22:17
  • What about `replaceAll()` with `[^0-9a-fA-F]` , I know this is a kludge at this point, but... – jdphenix Apr 26 '15 at 22:33
  • 2
    Weird. How about a sanity check: add the string constant `"8d"` to your code, send that through the same parsing code to see if it works, and do an `equals(chunkSizeAsString, "8d")`. That'll at least tell you if it's the string you read, or some unexpected parsing behavior. Also, you mention both `chunkSizeAsString` and `chunkedSizeAsString`. Is that a typo in this question, or do you have two variables sitting around in the code? – Andrew Janke Apr 26 '15 at 22:43
  • That is a typo, thank you. – Tait Apr 26 '15 at 22:52
  • Is there any chance either of those characters "8d" is not a normal ascii character? Try printing them as ints, eg `System.out.println((int)str.charAt(0));`, to be sure – Bohemian Apr 26 '15 at 23:02
  • Can you try adding `System.out.println(chunkSizeAsString.length())` as a sanity check? – durron597 Apr 26 '15 at 23:07
  • @fge, I am now using the latest jdk I can given the server I need to run the code on (1.7u79), the problem persists. To others, I tried your sanity checks: Tests on `Integer.valueOf("8d", 16)` and `Integer.parseInt("8d", 16)` behave as expected. `chunkSizeAsString.equals("8d")` is True. `chunkSizeAsString.length()` = 2. And the integer values of the characters are 56 and 100 respectively, just as they should be. – Tait Apr 26 '15 at 23:26

3 Answers3

3

After attempting to debug this at some length, and, given your updates, and your stack trace (the fact that you are on a worker thread), I am convinced that you are somehow confusing your attempts to debug with a multithreading issue.

Change your code to this:

private final AtomicInteger attemptCounter = new AtomicInteger(0);

void whateverYourMethodIsCalled(String responseString) {
    int attemptId = attemptCounter.incrementAndGet();
    System.out.format("Beginning attempt: %d%n", attemptId);
    String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
        .split(SINGLE_NEW_LINE)[0];
    System.out.format("In attempt %d, trying to get integer value of '%s', which is length %d%n",
         attemptId, chunkSizeAsString, chunkSizeAsString.length());
    Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109
    System.out.format("Ending attempt: %d%n", attemptId);
}

What's most likely happening is that you are getting a first attempt in that works correctly, passes your debugging cases, and then a later processed String is the one that throws the error.


Response to comment: What seemed to be happening is that the original asker was processing lots of data with lots of cases. In one particular case, he was getting the invisible character, but that wasn't the first time the problem was happening, and he was confusing the issue with which particular case was the one that was throwing the problem. By isolating which piece of parsed data was producing the problem, @Tait was able to debug / parse exactly what was causing it without being thrown off by false positive cases.

durron597
  • 31,968
  • 17
  • 99
  • 158
  • @Tait @durron597 Guys, could you please elaborate, what actually happened? Exception `java.lang.NumberFormatException: For input string: "8d"` was thrown - why? How was that possible, even keeping in mind the multithreading? – AlexW Apr 27 '15 at 08:02
1

After reading all these comments, the only helpful advice here can be - just debug it. Have no fear, press F7 (or whatever) and go into the implementation of Integer.valueOf(), it's quite straightforward, you will immediately see what went wrong.

AlexW
  • 896
  • 7
  • 9
  • I think this is a good suggestion, even though it was not the culprit in this case. – Tait Apr 27 '15 at 00:08
0

.valueOf uses .parseInt underneath, you could do int chunkSize = Integer.parseInt(chunkSizeAsString, 16);