このゆらぎを再現できない方へ。layer
メソッドが確実に をスローする開始値を見つけますStackOverflowError
。この値が実際のしきい値に近いほど良いです。次に、ループ内からこのメソッドを呼び出します (私のマシン上maxLayer = 11500
):
int i = 11500;
while (true) {
System.out.println(i);
triangleFract(i++);
}
投げStackOverflowError
ます。この値を少し減らします (5 ~ 10% で十分なようです)。
int i = 10500;
while (true) {
System.out.println(i);
triangleFract(i++);
}
私のマシンでは、これはエラーをスローせず、正常にジャンプし11500
ます。実際には までは問題なく動作し16000
ます。
したがって、それが何であれ、おそらくJVMの最適化が含まれます。でプログラムを実行しようとしました -XX:+PrintCompilation
。ループ中に JIT がどのように機能するかを見ました。
117 1 java.lang.String::hashCode (64 bytes)
183 2 java.lang.String::charAt (33 bytes)
189 3 sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (553 bytes)
201 4 java.math.BigInteger::mulAdd (81 bytes)
205 5 java.math.BigInteger::multiplyToLen (219 bytes)
211 6 java.math.BigInteger::addOne (77 bytes)
215 7 java.math.BigInteger::squareToLen (172 bytes)
219 8 java.math.BigInteger::primitiveLeftShift (79 bytes)
224 9 java.math.BigInteger::montReduce (99 bytes)
244 10 sun.security.provider.SHA::implCompress (491 bytes)
280 11 sun.nio.cs.UTF_8$Encoder::encodeArrayLoop (490 bytes)
282 12 java.lang.String::equals (88 bytes) 11400
289 13 java.lang.String::indexOf (151 bytes)
293 14 java.io.UnixFileSystem::normalize (75 bytes)
298 15 java.lang.Object::<init> (1 bytes)
298 16 java.util.jar.Manifest$FastInputStream::readLine (167 bytes)
299 17 java.lang.CharacterDataLatin1::getProperties (11 bytes)
300 18 NormalState::triangleFract (74 bytes)
308 19 java.math.BigInteger::add (178 bytes)
336 20 java.lang.String::lastIndexOf (151 bytes)
337 21 java.lang.Number::<init> (5 bytes)
338 22 java.lang.Character::digit (6 bytes)
340 23 java.lang.Character::digit (168 bytes)
342 24 java.lang.CharacterDataLatin1::digit (85 bytes)
343 25 java.math.BigInteger::trustedStripLeadingZeroInts (37 bytes)
357 26 java.lang.String::substring (83 bytes)
360 27 java.lang.String::lastIndexOf (10 bytes)
360 28 java.lang.String::lastIndexOf (29 bytes)
361 29 java.math.BigInteger::<init> (24 bytes)
361 30 java.lang.Integer::parseInt (269 bytes)
361 31 java.math.BigInteger::<init> (8 bytes)
362 32 java.math.BigInteger::<init> (347 bytes)
404 33 java.math.BigInteger::multiply (72 bytes)
404 34 java.math.BigInteger::add (123 bytes)
コンパイルでしょうか?コンパイルを遅らせて、影響ができるだけ遅くなるようにしましょう。-XX:CompileThreshold
私はflag で遊んでみましたが、すぐに値 ( -XX:CompileThreshold=1000000
) が見つかりました。これはループを飛び越えさせません11500
。
アップデート
コンパイルのしきい値を微調整することなく、最終的に再現しました。私にとっては、IDE(IntelliJ IDEA)でプログラムを実行したときにのみ発生するようです。したがって、IDEA のランチャーと関係がある可能性があります。そのコマンド ラインをコピーし、小さなスクリプトで使用しました。
for I in `seq 1 100`; do
java ... com.intellij.rt.execution.application.AppMain \
Triangle 2>&1| grep Stack; done | wc -l
そして、私が発見したことは、通常、100 未満 (95-98) を出力することです。これは、手動で行ったときに見たものと一致しています。ランチャーをスキップすると:
for I in `seq 1 100`; do
java \
Triangle 2>&1| grep Stack; done | wc -l
常に 100 が出力されます。