Время от времени вы смотрите на некоторый код и думаете, что он не может быть ошибочным. После того, как вы исключили простое программистское искажение / вражеское действие в коде (убедитесь, что вы читаете Java Puzzlers или аналогичные) или проблему с параллелизмом (прочитайте Java Concurrency или изучите превосходный курс Dr Heniz ), вам следует бездельничать и занять несколько дней. и затем начинаю думать о том, действительно ли JDK хочет тебя достать. Я не видел никого в дикой природе за свои 18 с лишним лет как программист на Java, так что это застало меня врасплох.
Если вы работаете с JDK 8 в крупномасштабном Swing-приложении, вы можете в конечном итоге увидеть следующее исключение, много раз. (Если вы не забыли урок, полученный в моем предыдущем блоге в вашем коде регистрации, в этом случае вы можете увидеть много ArrayOfOutBoundsException)
Caused by: java.lang.NullPointerException at javax.swing.text.GlyphView.getBreakSpot(GlyphView.java:799) at javax.swing.text.GlyphView.getBreakWeight(GlyphView.java:724) at javax.swing.text.FlowView$LogicalView.getPreferredSpan(FlowView.java:733) at javax.swing.text.FlowView.calculateMinorAxisRequirements(FlowView.java:233) at javax.swing.text.ParagraphView.calculateMinorAxisRequirements(ParagraphView.java:717) at javax.swing.text.BoxView.checkRequests(BoxView.java:935) at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568) at javax.swing.text.BoxView.calculateMinorAxisRequirements(BoxView.java:903) at javax.swing.text.BoxView.checkRequests(BoxView.java:935) at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:343) at javax.swing.text.BoxView.layout(BoxView.java:708) at javax.swing.text.BoxView.setSize(BoxView.java:397) ...
Эта ошибка особенно коварна, потому что требуется около десяти минут, чтобы показать себя, а иногда и вовсе. Если вы посмотрите на код для этого класса, то рассматриваемая строка, начинающаяся с «setsFrom = break», получает доступ только к двум локальным переменным, на обе из которых ранее ссылались в методе.
Segment s = getText(pstart, pend); s.first(); BreakIterator breaker = getBreaker(); breaker.setText(s); // Backward search should start from end+1 unless there's NO end+1 int startFrom = end + (pend > end ? 1 : 0); for (;;) { startFrom = breaker.preceding(s.offset + (startFrom - pstart)) + (pstart - s.offset); if (startFrom > start) { // The break spot is within the view bs[ix++] = startFrom; } else { break; } }
Самый прямой способ исключить ошибку JIT — отключить компиляцию только для этого единственного метода, вот пример; но вы можете узнать больше в документации по Java-инструменту командной строки .
javaThing -XX:CompileCommand=exclude,javax/swing/text/GlyphView,getBreakSpot
Когда этот параметр добавлен, проблема исчезнет. — поскольку мы исключили действия противника с помощью кода или проблемы параллелизма, мы можем быть более уверены, что это проблема JIT. Теперь, как часть регистрации ошибок, я вывел диагностику для этого единственного метода и обнаружил, что проблема не возникала, пока метод не был JITted в пятый раз.
javaThing -XX:CompileCommand=print,javax/swing/text/GlyphView,getBreakSpot
Вот некоторые диагностические результаты, показанные с помощью приведенной выше команды:
Compiled method (c2) 914078 33142 4 javax.swing.text.GlyphView::getBreakSpot (247 bytes) total in heap [0x00002aaab0749e10,0x00002aaab0750fe0] = 29136 relocation [0x00002aaab0749f38,0x00002aaab074a1e8] = 688 constants [0x00002aaab074a200,0x00002aaab074a2a0] = 160 main code [0x00002aaab074a2a0,0x00002aaab074cde0] = 11072 stub code [0x00002aaab074cde0,0x00002aaab074ce40] = 96 oops [0x00002aaab074ce40,0x00002aaab074ce58] = 24 metadata [0x00002aaab074ce58,0x00002aaab074d058] = 512 scopes data [0x00002aaab074d058,0x00002aaab074ea20] = 6600 scopes pcs [0x00002aaab074ea20,0x00002aaab0750c50] = 8752 dependencies [0x00002aaab0750c50,0x00002aaab0750c80] = 48 handler table [0x00002aaab0750c80,0x00002aaab0750e90] = 528 nul chk table [0x00002aaab0750e90,0x00002aaab0750fe0] = 336 OopMapSet contains 113 OopMaps #0 OopMap{[8]=Oop [32]=Oop [40]=Oop off=892} #1 OopMap{[32]=Oop [40]=Oop off=960} #2 OopMap{[32]=Oop [40]=Oop off=980} #3 OopMap{[32]=Oop [40]=Oop [48]=Oop off=1048} #4 OopMap{[32]=Oop [40]=Oop [48]=Oop off=1084} #5 OopMap{[0]=Oop [24]=Oop [48]=Oop [56]=Oop [80]=Oop off=2500} #6 OopMap{rbx=Oop rdi=Oop [32]=Oop [40]=Oop [112]=Oop off=2533} #7 OopMap{rbx=Oop rdi=Oop r14=Oop [32]=Oop [112]=Oop off=3081} #8 OopMap{rbx=Oop rdi=Oop r14=Oop [32]=Oop [40]=Oop [112]=Oop off=3190} #9 OopMap{[8]=Oop [32]=Oop [40]=Oop off=4408} #10 OopMap{[32]=Oop [40]=Oop [48]=Oop off=4640} #11 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=5232} #12 OopMap{rbp=Oop [0]=NarrowOop [32]=Oop off=5364} #13 OopMap{[32]=Oop [40]=Oop [48]=Oop off=5408} #14 OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop off=5436} #15 OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop off=5468} #16 OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop off=5524} #17 OopMap{rbp=Oop [32]=Oop [40]=Oop [48]=Oop [88]=Oop off=5552} #18 OopMap{[32]=Oop [40]=Oop [48]=Oop [64]=Oop [72]=Derived_oop_[64] [112]=Oop off=5608} #19 OopMap{[8]=Oop [32]=Oop off=5680} #20 OopMap{rbp=Oop off=5720} #21 OopMap{rbp=Oop off=5752} #22 OopMap{rbp=Oop [24]=NarrowOop [28]=NarrowOop [32]=Oop [40]=Oop [48]=Oop [56]=Oop [64]=Oop [88]=Oop off=5812} #23 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop [88]=Oop off=5960} #24 OopMap{[0]=Oop [24]=Oop [48]=Oop [56]=Oop [72]=Oop [88]=NarrowOop off=6056} #25 OopMap{[40]=Oop off=6088} #26 OopMap{[0]=Oop off=6120} #27 OopMap{[8]=Oop [24]=Oop [56]=Oop [72]=Oop [112]=Oop off=6216} #28 OopMap{[0]=Oop [32]=NarrowOop [40]=Oop off=6284} #29 OopMap{rbp=Oop [16]=Oop [40]=Oop [64]=Oop [112]=Oop off=6384} #30 OopMap{[0]=Oop off=6412} #31 OopMap{[0]=Oop [16]=Oop [32]=NarrowOop [40]=Oop [48]=Oop off=6488} #32 OopMap{rbp=Oop [16]=Oop [40]=Oop [48]=Oop off=6560} #33 OopMap{[32]=Oop [40]=Oop [48]=Oop [64]=Oop [112]=Oop off=6608} #34 OopMap{[8]=Oop [28]=NarrowOop [32]=Oop [40]=Oop [48]=Oop off=6768} #35 OopMap{rbp=NarrowOop [0]=Oop [16]=Oop [32]=Oop [40]=NarrowOop off=6860} #36 OopMap{[0]=Oop [16]=Oop [32]=NarrowOop [40]=Oop [48]=Oop off=6988} #37 OopMap{rbp=Oop [32]=Oop off=7024} #38 OopMap{rbp=NarrowOop [0]=Oop [24]=Oop [32]=Oop off=7260} #39 OopMap{rbp=NarrowOop [0]=Oop [24]=Oop [32]=Oop off=7344} #40 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [60]=NarrowOop [64]=Oop off=7452} #41 OopMap{rbp=NarrowOop [32]=Oop off=7476} #42 OopMap{rbp=NarrowOop [0]=Oop off=7524} #43 OopMap{[32]=Oop [40]=Oop [48]=Oop off=7588} #44 OopMap{[32]=Oop [40]=Oop [48]=Oop off=7616} #45 OopMap{[32]=Oop [40]=Oop [48]=Oop off=7632} #46 OopMap{rbp=NarrowOop [32]=Oop off=7676} #47 OopMap{rbp=NarrowOop [0]=Oop off=7724} #48 OopMap{[0]=Oop [16]=Oop [28]=NarrowOop [40]=Oop [48]=Oop [56]=NarrowOop [64]=Oop off=7868} #49 OopMap{[8]=Oop [28]=NarrowOop [32]=Oop [40]=Oop [48]=Oop [56]=Oop off=7916} #50 OopMap{rbp=Oop [16]=Oop [24]=NarrowOop off=8016} #51 OopMap{rbp=Oop [16]=Oop [28]=NarrowOop off=8080} #52 OopMap{rbp=NarrowOop [0]=Oop [24]=Oop [32]=Oop off=8152} #53 OopMap{rbp=Oop [8]=NarrowOop off=8212} #54 OopMap{rbp=NarrowOop [32]=Oop off=8236} #55 OopMap{rbp=Oop [16]=NarrowOop off=8272} #56 OopMap{rbp=NarrowOop [0]=Oop off=8320} #57 OopMap{rbp=Oop [12]=NarrowOop off=8360} #58 OopMap{rbp=NarrowOop [32]=Oop off=8400} #59 OopMap{rbp=Oop [12]=NarrowOop off=8460} #60 OopMap{rbp=NarrowOop [0]=Oop off=8508} #61 OopMap{rbp=Oop [24]=NarrowOop [40]=Oop off=8572} #62 OopMap{rbp=Oop off=8600} #63 OopMap{rbp=Oop [8]=Oop [28]=NarrowOop off=8640} #64 OopMap{rbp=Oop [8]=Oop [20]=NarrowOop [112]=Oop off=8704} #65 OopMap{rbp=Oop [16]=Oop [24]=Oop [48]=Oop off=8788} #66 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=8912} #67 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9036} #68 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9160} #69 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9284} #70 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9408} #71 OopMap{rbp=Oop [16]=Oop [24]=Oop [40]=Oop [64]=Oop off=9532} #72 OopMap{off=9556} #73 OopMap{off=9580} #74 OopMap{off=9604} #75 OopMap{[112]=Oop off=9628} #76 OopMap{rbp=Oop [8]=Oop [24]=Oop [32]=NarrowOop off=9696} #77 OopMap{rbp=Oop [8]=Oop [24]=NarrowOop off=9760} #78 OopMap{off=9784} #79 OopMap{off=9812} #80 OopMap{off=9836} #81 OopMap{off=9860} #82 OopMap{off=9884} #83 OopMap{off=9908} #84 OopMap{off=9932} #85 OopMap{off=9956} #86 OopMap{off=9980} #87 OopMap{off=10004} #88 OopMap{off=10028} #89 OopMap{rbp=Oop [16]=Oop [28]=NarrowOop off=10092} #90 OopMap{rbp=Oop [16]=Oop [24]=Oop [48]=Oop off=10176} #91 OopMap{off=10200} #92 OopMap{off=10224} #93 OopMap{off=10248} #94 OopMap{off=10272} #95 OopMap{off=10296} #96 OopMap{off=10320} #97 OopMap{off=10344} #98 OopMap{off=10368} #99 OopMap{off=10392} #100 OopMap{off=10416} #101 OopMap{off=10440} #102 OopMap{off=10464} #103 OopMap{off=10488} #104 OopMap{off=10512} #105 OopMap{off=10536} #106 OopMap{off=10560} #107 OopMap{off=10584} #108 OopMap{off=10608} #109 OopMap{off=10632} #110 OopMap{off=10656} #111 OopMap{off=10680} #112 OopMap{off=11028} java.lang.NullPointerException at javax.swing.text.GlyphView.getBreakSpot(GlyphView.java:799) at javax.swing.text.GlyphView.getBreakWeight(GlyphView.java:724) at javax.swing.text.html.InlineView.getBreakWeight(InlineView.java:150) at javax.swing.text.FlowView$LogicalView.getPreferredSpan(FlowView.java:733) at javax.swing.text.FlowView.calculateMinorAxisRequirements(FlowView.java:233) at javax.swing.text.ParagraphView.calculateMinorAxisRequirements(ParagraphView.java:717) at javax.swing.text.html.ParagraphView.calculateMinorAxisRequirements(ParagraphView.java:157) at javax.swing.text.BoxView.checkRequests(BoxView.java:935) at javax.swing.text.BoxView.getMinimumSpan(BoxView.java:568) at javax.swing.text.html.ParagraphView.getMinimumSpan(ParagraphView.java:270) at javax.swing.text.BoxView.calculateMinorAxisRequirements(BoxView.java:903)
Сейчас я все еще работаю с командой JDK для исправления этой проблемы; но я чувствую, что обнаружил полезный набор инструментов для предоставления некоторых доказательств того, что JIT-компилятор вызывает мой плохой день И что более важно, у меня есть обходной путь, чтобы я мог запускать свои тесты, пока это не будет решено.