Je pense que les autres ont fait un bon travail en expliquant pourquoi la cnt > 0, mais il n'y a pas assez de détails concernant les raisons de la cnt = 4, et pourquoi cnt varie considérablement entre les différents paramètres. Je vais tenter de combler ce vide ici.
Laissez
- Soit X le total de la taille de la pile
- M l'espace de pile utilisé lorsque nous entrons principal de la première fois
- R l'espace de pile chaque fois que nous entrons dans la principale
- P la pile de l'espace nécessaire pour exécuter
System.out.println
Quand nous recevons dans la principale, l'espace est X-M. Chaque appel récursif prend R plus de mémoire. Donc, pour 1 appel récursif (1 de plus que l'original), l'utilisation de la mémoire est M + R. Supposons que StackOverflowError est jeté après C réussie appels récursifs, c'est-à M + C * R <= X et M + C * (R + 1) > X. Au moment de la première StackOverflowError, il y a X - M - C * R de la mémoire à gauche.
Pour être en mesure d'exécuter System.out.prinln
, nous avons besoin de P la quantité d'espace restant sur la pile. Si il se trouve que X - M - C * R >= P, 0 sera imprimé. Si P nécessite plus d'espace, alors nous retirer des images à partir de la pile, gagnant de la R de la mémoire au détriment de la cnt++.
Lors de l' println
est enfin en mesure d'exécuter, X - M - C - cnt) * R >= P. si P est grand pour un système particulier, puis cnt sera grand.
Regardons cela avec quelques exemples.
Exemple 1: Supposons Que
- X = 100
- M = 1
- R = 2
- P = 1
Alors C = floor((X-M)/R) = 49, et cnt = plafond((P - (X - M - C*R)/R) = 0.
Exemple 2: Supposons que
- X = 100
- M = 1
- R = 5
- P = 12
Alors C = 19, et cnt = 2.
Exemple 3: Supposons que
- X = 101
- M = 1
- R = 5
- P = 12
Alors C = 20, et cnt = 3.
Exemple 4: Supposons que
- X = 101
- M = 2
- R = 5
- P = 12
Alors C = 19, et cnt = 2.
Ainsi, nous voyons que le système (M, R et P) et de la taille de la pile (X) affecte la cnt.
Comme une note de côté, il n'a pas d'importance combien d'espace catch
nécessite pour commencer. Tant qu'il n'y a pas assez d'espace pour catch
, alors cnt ne sera pas augmenter, donc il n'y a pas d'effets externe.
MODIFIER
Je reprends ce que j'ai dit à propos de catch
. Elle joue un rôle. Supposons qu'il nécessite T quantité d'espace pour commencer. cnt commence à cran lorsque l'espace restant est supérieur à T, et println
s'exécute lorsque l'espace restant est supérieur à T + P. Cela ajoute une étape supplémentaire pour les calculs et autres brouille jusqu'à la déjà boueux analyse.
MODIFIER
J'ai enfin trouvé le temps de lancer quelques expériences pour sauvegarder ma théorie. Malheureusement, la théorie ne semble pas correspondre avec les expériences. Ce qui se passe en réalité est très différente.
L'expérience de l'installation:
Ubuntu 12.04 server avec java par défaut et default-jdk. Xss départ à 70 000 à 1 octet des augmentations de 460 000.
Les résultats sont disponibles sur: https://www.google.com/fusiontables/DataSource?docid=1xkJhd4s8biLghe6gZbcfUs3vT5MpS_OnscjWDbM
J'ai créé une autre version où répété chaque point de données est supprimé. En d'autres termes, seuls les points qui sont différentes de la précédente sont indiquées. Cela rend plus facile de voir les anomalies. https://www.google.com/fusiontables/DataSource?docid=1XG_SRzrrNasepwZoNHqEAKuZlHiAm9vbEdwfsUA