-4

While using compareIgnoreCase I get NegativeArraySizeException / 'NullPointerException' ( Running in a Java 7 JRE).

Caused by: java.lang.NegativeArraySizeException
    at java.lang.String.toCharArray(String.java:2748)
    at sun.text.normalizer.NormalizerImpl.canonicalDecomposeWithSingleQuotation(NormalizerImpl.java:2506)
    at java.text.RBTableBuilder.build(RBTableBuilder.java:107)
    at java.text.RBCollationTables.<init>(RBCollationTables.java:83)
    at java.text.RuleBasedCollator.<init>(RuleBasedCollator.java:300)
    at java.text.RuleBasedCollator.<init>(RuleBasedCollator.java:281)
    at java.text.Collator.getInstance(Collator.java:276)

and

Caused by: java.lang.NullPointerException
    at java.lang.String.length(String.java:623)
    at java.text.RBTableBuilder.build(RBTableBuilder.java:84)
    at java.text.RBCollationTables.<init>(RBCollationTables.java:83)
    at java.text.RuleBasedCollator.<init>(RuleBasedCollator.java:300)
    at java.text.RuleBasedCollator.<init>(RuleBasedCollator.java:281)
    at java.text.Collator.getInstance(Collator.java:276)

These seem to happen in String.compareIgnoreCase and String.equalsIgnoreCase

Sample code:

  public static int compareIgnoreCase(Locale locale, String a, String b) {
    if (a != null && a.length() == 0) {
      a = null;
    }
    if (b != null && b.length() == 0) {
      b = null;
    }
    //
    if (a == b) {
      return 0;
    }
    if (a == null) {
      return -1;
    }
    if (b == null) {
      return 1;
    }
    Collator collator = Collator.getInstance(locale);
    collator.setStrength(Collator.SECONDARY);
    return collator.compare(a, b);
  }

Which got called by:

  public static int compareIgnoreCase(String a, String b) {
    return compareIgnoreCase(NlsUtility.getDefaultLocale(), a, b);
  }

NlsUtility.getDefaultLocale:

  public static Locale getDefaultLocale() {
    Locale locale = LocaleThreadLocal.get();
    if (locale == null) {
      locale = Locale.getDefault();
    }
    return locale;
  }

It appears the problem has returned, followed by a JVM crash. I'm not sure how to solve this:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f1dabb9d4f0, pid=4290, tid=139765228910336
#
# JRE version: Java(TM) SE Runtime Environment (7.0_80-b15) (build 1.7.0_80-b15)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.80-b11 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x7ee4f0]  nmethod::can_unload(BoolObjectClosure*, OopClosure*, oopDesc**, bool)+0x70
#
# 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:
# /tmp/hs_err_pid4290.log
Compiled method (c2) 191914528 4305  s!         java.text.Collator::getInstance (157 bytes)
 total in heap  [0x00007f1da19f7f90,0x00007f1da19fa8f8] = 10600
 relocation     [0x00007f1da19f80b0,0x00007f1da19f8290] = 480
 constants      [0x00007f1da19f82a0,0x00007f1da19f82c0] = 32
 main code      [0x00007f1da19f82c0,0x00007f1da19f9980] = 5824
 stub code      [0x00007f1da19f9980,0x00007f1da19f9a40] = 192
 oops           [0x00007f1da19f9a40,0x00007f1da19f9b30] = 240
 scopes data    [0x00007f1da19f9b30,0x00007f1da19fa3d0] = 2208
 scopes pcs     [0x00007f1da19fa3d0,0x00007f1da19fa690] = 704
 dependencies   [0x00007f1da19fa690,0x00007f1da19fa6a8] = 24
 handler table  [0x00007f1da19fa6a8,0x00007f1da19fa8d0] = 552
 nul chk table  [0x00007f1da19fa8d0,0x00007f1da19fa8f8] = 40
Compiled method (c2) 191914528 4305  s!         java.text.Collator::getInstance (157 bytes)
 total in heap  [0x00007f1da19f7f90,0x00007f1da19fa8f8] = 10600
 relocation     [0x00007f1da19f80b0,0x00007f1da19f8290] = 480
 constants      [0x00007f1da19f82a0,0x00007f1da19f82c0] = 32
 main code      [0x00007f1da19f82c0,0x00007f1da19f9980] = 5824
 stub code      [0x00007f1da19f9980,0x00007f1da19f9a40] = 192
 oops           [0x00007f1da19f9a40,0x00007f1da19f9b30] = 240
 scopes data    [0x00007f1da19f9b30,0x00007f1da19fa3d0] = 2208
 scopes pcs     [0x00007f1da19fa3d0,0x00007f1da19fa690] = 704
 dependencies   [0x00007f1da19fa690,0x00007f1da19fa6a8] = 24
 handler table  [0x00007f1da19fa6a8,0x00007f1da19fa8d0] = 552
 nul chk table  [0x00007f1da19fa8d0,0x00007f1da19fa8f8] = 40
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
  • You get exception (that is IMHO self explainable and clear) because of bug in your code. If you cannot find the reason yourself try to post a minimal code snapshot that reproduces the problem. – AlexR Aug 17 '16 at 10:02
  • *Somedays, it appears java Strings seem to stop working right, throwing the odd exceptions.* Why is that odd? To err is human. Always check the exception messages, and you can even search them in the Web. In most cases, you find a relevant link to SO or documentation right away. – Wiktor Stribiżew Aug 17 '16 at 10:02
  • Caused by: java.lang.NegativeArraySizeException, think about – Abdelhak Aug 17 '16 at 10:02
  • 2
    What value are you passing in for the `locale` variable? I think this error happens if the `locale` variable is either null, or not a valid locale. – Dawood ibn Kareem Aug 17 '16 at 10:12
  • @DavidWallace Locale.forLanguageTag("nl-BE") – Christina Korosec Aug 17 '16 at 10:16
  • Thank you for the help everyone. I'm trying to see where the bug is in my code, but I'm not sure how a String without a char-array could exist, or how you could instantiate a String with a negative length. I'm also failing to reproduce this in a debug environment, and it stopped happening in the original environment as soon as I attached a debugger. – Christina Korosec Aug 17 '16 at 10:24
  • 3
    I can't reproduce your error with this code, passing the locale that you've named. Are you sure that you're passing that locale, and not some other one? Perhaps you could use your debugger to examine the value of `locale` just before the call to `Collator.getInstance`. – Dawood ibn Kareem Aug 17 '16 at 10:24
  • 1
    OK, I've just read your last comment. I'm wondering if attaching the debugger is affecting the locale somehow. You could try running without the debugger, but put the line `System.out.println(LocaleData.getCollationData(locale).getString("Rule"));` before the call to `Collator.getInstance`. If this shows null, then there's a problem with the locale data in your Java runtime, and you should probably move to a later Java build. – Dawood ibn Kareem Aug 17 '16 at 10:29
  • @DavidWallace The issue stopped occuring in the application, without restarting or otherwise affecting it, and without changing the code. I'm not sure how this happened... This is the confusing part. I cannot reproduce it anymore. – Christina Korosec Aug 17 '16 at 10:31
  • The Locale is provided by any external reference? – crm86 Aug 17 '16 at 10:32
  • 1
    Well, internally, locales are kept in a cache. Maybe that cache got corrupted somehow. Kind of impossible to do a post-mortem at this point. I don't think anyone here can be of any further help to you, sorry. – Dawood ibn Kareem Aug 17 '16 at 10:33
  • @DavidWallace Thank you for your help. Looks like it's going to be difficult to find out what caused this or how to prevent it in the future. – Christina Korosec Aug 17 '16 at 10:42
  • Apparently the JVM can segfault on the same method call. We're not using any JNI so the call fails in a native part of the JVM. Maybe the memory is being corrupted somehow? This is beyond my area of expertise. Added the error log from the JVM to the question. – Christina Korosec Aug 19 '16 at 18:49

2 Answers2

0

You have to check you locale before call to Collator.getInstance(locale);

Check if it is null, with invalid length() or valid locale. Try debugging your application. This will give you some advice of what is happening there.

Obviously, you compareIgnoreCase raises an exception (Nullpointer) but I suggest to debug you application because this is due to a code failure in your checks or maybe during the Collator.getInstance()...

keuleJ
  • 3,418
  • 4
  • 30
  • 51
crm86
  • 1,394
  • 1
  • 21
  • 44
  • The locale is set by using Locale.forLanguageTa‌​g("nl-BE") Right before the method call, there is a null check. If the locale is null, it uses Locale.getDefault Edit: I'm not sure how a successfully instantiated Locale object would have an "invalid length" – Christina Korosec Aug 17 '16 at 10:18
  • Do you have LOGs that could give us some info to help you? – crm86 Aug 17 '16 at 10:27
  • The Nullpointer is actually raised at java.lang.String.length(String.java:623) – Christina Korosec Aug 17 '16 at 10:44
  • 1
    I think it starts in java.text.Collator.getInstance(Collator.java:276). I am reading about forLanguageTa‌g("...") and maybe your Locale instance is not well-formed for something weird. I am sorry but I could not extract more info.. – crm86 Aug 17 '16 at 10:48
  • There are only three locales possible in the application: nl-BE, fr-BE, Locale.getDefault. I'm not sure what's so odd about these three. They're valid locales. And the exception stopped happening without any intervention in the code. – Christina Korosec Aug 17 '16 at 10:56
  • Is this about Eclipse NlsUtility.getDefaultLocale()?. If possible, change it to: NlsLocale.CURRENT and see what happens https://www.eclipse.org/forums/index.php/t/1075295/ – crm86 Aug 17 '16 at 11:05
  • NlsUtility is from Eclipse Scout, not standard Eclipse. We're using Eclipse Scout 3.10. The question you linked to is about migration to version 6. NlsLocale.CURRENT doesn't exist before version 6. – Christina Korosec Aug 17 '16 at 11:07
  • There are not more ideas..sorry for the unhelpful answer. – crm86 Aug 17 '16 at 11:16
  • Thanks for all of your help. Looks like memory corruption in the JVM so this goes beyond my area of expertise. – Christina Korosec Aug 19 '16 at 19:07
0

it appears this bug is making the JVM segfault. You could look at How do I debug Segfaults occurring in the JVM when it runs my code? if you have a similar problem.

Community
  • 1
  • 1