0
static Number parse(String s) { if (s == null || s.trim().length() == 0) { return 0; } return Long.parseLong(s); } 

This piece of code intermittently throws java.lang.NumberFormatException: For input string: "".

Running on Java version 11.0.20+8-LTS-sapmachine.

How is empty string passed into parseLong? I understand s.trim() and s are different instances but doesn't s.trim().length() != 0 infer s is non-empty?

UPDATE: Apologies, I had left out the fact that I am parsing with a DecimalFormat instance (naively thought it did not matter).

static java.text.DecimalFormat df = new java.text.DecimalFormat("#"); static Number parse(String s) throws java.text.ParseException { if (s == null || s.trim().length() == 0) { return 0; } return df.parse(s); } 

This code throws java.lang.NumberFormatException: For input string: "" from time to time on a live server. Stack trace:

java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:702) at java.lang.Long.parseLong(Long.java:817) at java.text.DigitList.getLong(DigitList.java:195) at java.text.DecimalFormat.parse(DecimalFormat.java:2121) at java.text.NumberFormat.parse(NumberFormat.java:429) 
11
  • 2
    What is the value of s when this error is thrown? Commented Sep 15, 2023 at 14:57
  • 2
    Can't reproduce with the empty string (""); if I pass the empty string to parse, I correctly get 0. Just because a string renders like the empty string does not mean that it is the empty string; it may contain invisible zero-width Unicode characters (such as a zero-width space), which trim doesn't trim. Commented Sep 15, 2023 at 15:03
  • 1
    Welcome. Best for getting useful advice is follow the Help guidance to provide a minimum executable example of the problem. nb: one method to debug this is to trap NumberException in a debugger so you can inspect the value of s that caused it. It's fairly likely that what you think is happening is not really. Commented Sep 15, 2023 at 16:27
  • 1
    I don't see how this would happen considering you test s.trim().length(). Are you sure the NumberFormatException stems from this code? Commented Sep 15, 2023 at 16:33
  • 1
    String.valueOf(BigDecimal) cannot return null and cannot return a blank String. You shouldn’t even need to test for those values. Try adding System.out.println(s.length()); right before you call Long.parseLong. That will tell us whether your string is really empty. Commented Sep 15, 2023 at 16:44

2 Answers 2

0
public static Number parse(String s) throws NumberFormatException { if (s == null || s.isBlank()) { return 0; } return Long.parseLong(s); } 
Sign up to request clarification or add additional context in comments.

Comments

0

Looking into DigitList class, s definitely is not the input string here. The DigitList's use of StringBuffer tempBuffer is not thread-safe.

private StringBuffer getStringBuffer() { if (tempBuffer == null) { tempBuffer = new StringBuffer(MAX_COUNT); } else { tempBuffer.setLength(0); } return tempBuffer; } 

tempBuffer.setLength(0) is what is causing the empty input string. DecimalFormat.digitList and DigitList.tempBuffer are both class members and I am using a singleton DecimalFormat instance creating a race condition.

I am able to reproduce the problem with this line of code

IntStream .range(1, Runtime.getRuntime().availableProcessors() * 3) .parallel() .forEach(s -> parse("123")); 

Without the parallel() mode, the issue does not occur.

Having found the root of the issue, I also found this question is essentially a duplicate of https://stackoverflow.com/a/4021932/22569932 where good explanation and solution are provided.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.