Ich verwende einen regulären Ausdruck, um Schlüssel-Wert-Paare aus beliebig langen Eingabezeichenfolgen zu extrahieren, und habe einen Fall ausgelöst, in dem für eine lange Zeichenfolge mit sich wiederholenden Mustern ein Stapelüberlauf verursacht wird.Java-Muster verursacht Stapelüberlauf
Der KV-Parsing-Code sieht etwa so aus:
public static void parse(String input)
{
String KV_REGEX = "((?:\"[^\"^ ]*\"|[^=,^ ])*) *= *((?:\"[^\"]*\"|[^=,^\\)^ ])*)";
Pattern KV_PATTERN = Pattern.compile(KV_REGEX);
Matcher matcher = KV_PATTERN.matcher(input);
System.out.println("\nMatcher groups discovered:");
while (matcher.find())
{
System.out.println(matcher.group(1) + ", " + matcher.group(2));
}
}
Einige fiktive Beispiele für Ausgabe:
String input1 = "2012-08-09 09:10:25,521 INFO com.a.package.SomeClass - Everything working fine {name=CentOS, family=Linux, category=OS, version=2.6.x}";
String input2 = "2012-08-09 blah blah 09:12:38,462 Log for the main thread, PID=5872, version=\"7.1.8.x\", build=1234567, other=done";
parse(input1)
Aufruf erzeugt:
{name, CentOS
family, Linux
category, OS
version, 2.6.x}
parse(input2)
Aufruf erzeugt:
PID, 5872
version, "7.1.8.x"
build, 1234567
other, done
Dies ist in Ordnung (sogar mit ein wenig String-Verarbeitung für den ersten Fall erforderlich). Wenn jedoch einen sehr langen (mehr als 1.000 Zeichen) Classpath Zeichenfolge, die zuvor erwähnte Klasse Überlauf auftritt, mit folgenden Ausnahme zu analysieren versuchen (Start):
Exception in thread "main" java.lang.StackOverflowError
at java.util.regex.Pattern$BitClass.isSatisfiedBy(Pattern.java:2927)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$8.isSatisfiedBy(Pattern.java:4783)
at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
...
Die Zeichenfolge zu lang sind hier zu setzen, aber es hat die folgende, leicht reproduzierbar und sich wiederholende Struktur:
java.class.path=/opt/files/any:/opt/files/any:/opt/files/any:/opt/files/any
wer die Frage muss nur anhängen :/opt/files/any
ein paar Dutzend mal auf die obige Zeichenfolge reproduzieren will. Nach dem Erstellen einer Zeichenfolge mit ungefähr 90 Kopien von ":/opt/files/any" in der Klassenpfadzeichenfolge tritt der Stapelüberlauf auf.
Gibt es eine allgemeine Möglichkeit, dass die obige KV_REGEX
Zeichenfolge geändert werden könnte, so dass das Problem nicht auftritt und die gleichen Ergebnisse erzeugt werden?
Ich lege explizit generische oben, im Gegensatz zu Hacks, die (zum Beispiel) vor dem Analysieren nach einer maximalen Stringlänge suchen.
Die Brutto fix ich mit, einem echten anti-Muster kommen konnte, ist
public void safeParse(String input)
{
try
{
parse(input);
}
catch (StackOverflowError e) // Or even Throwable!
{
parse(input.substring(0, MAX_LENGTH));
}
}
Komischerweise es in ein paar Runs arbeitet ich es versucht, aber es ist nicht etwas, geschmackvoll genug zu empfehlen . :-)
Herzlichen Glückwunsch zum Überschreiten der Grenzen. – kosa
Danke! Ich würde jederzeit eine Lösung für eine Belohnung akzeptieren! :-) Was genau war das Limit gebrochen? – PNS
Was soll dieser Teil zusammenpassen? Es sieht überhaupt nicht korrekt aus. '[^ =,^\\) ^]'. – Keppil