J'exécute un programme dans lequel j'ai écrit Java dans Eclipse. Le programme a un niveau de récursion très profond pour les très grandes entrées. Pour les plus petites entrées, le programme fonctionne correctement, mais lorsque les grandes entrées sont étant donné, j'obtiens l'erreur suivante:
Exception in thread "main" Java.lang.StackOverflowError
Peut-on résoudre ce problème en augmentant la taille de la pile Java) et, le cas échéant, comment procéder de cette manière dans Eclipse?
Mise à jour:
@ Jon Skeet
Le code parcourt de manière récursive un arbre d'analyse afin de constituer une structure de données. Ainsi, par exemple, le code utilisera un nœud dans l’arbre d’analyse et s’appellera lui-même aux deux enfants du nœud, en combinant leurs résultats pour obtenir le résultat global de l’arbre.
La profondeur totale de la récursivité dépend de la taille de l'arbre d'analyse, mais le code semble échouer (sans pile plus grande) lorsque le nombre d'appels récursifs entre dans les milliers.
De plus, je suis presque sûr que le code n'échoue pas à cause d'un bogue car il fonctionne pour de petites entrées.
Ouvrez le Run Configuration pour votre application (Run/Run Configurations ...), puis recherchez l'entrée de l'application dans 'Application Java').
L'onglet arguments a une zone de texte arguments Vm, entrez -Xss1m
(ou un paramètre plus grand pour la taille maximale de la pile). La valeur par défaut est 512 Ko (Sun JDK 1.5 - ne sait pas si cela varie entre les fournisseurs et les versions).
Cela peut être curable en augmentant la taille de la pile - mais une meilleure solution serait de trouver un moyen d’éviter autant de récursions. Une solution récursive peut toujours être convertie en une solution itérative - ce qui permettra à votre code de s’adapter à des entrées plus volumineuses de manière beaucoup plus propre. Sinon, vous allez vraiment deviner la quantité de pile à fournir, ce qui peut même ne pas être évident à partir de l'entrée.
Etes-vous absolument sûr que cela échoue à cause de la taille de l'entrée plutôt que d'un bug dans le code, au fait? Quelle est la profondeur de cette récursion?
EDIT: OK, après avoir vu la mise à jour, je voudrais personnellement essayer de la réécrire pour éviter d’utiliser la récursivité. Ayant généralement un Stack<T>
de "faire encore" est un bon point de départ pour supprimer la récursivité.
Ajouter le drapeau -Xss1024k
dans les VM arguments.
Vous pouvez également augmenter la taille de la pile dans mb
en utilisant -Xss1m
par exemple .
j'ai également le même problème lors de l'analyse des fichiers de définition de schéma (XSD) à l'aide de la bibliothèque XSOM,
j'ai pu augmenter la mémoire de pile jusqu'à 208Mb alors il a montré heap_out_of_memory_error
pour lequel je n'ai pu augmenter que jusqu'à 320 Mo.
la configuration finale était -Xmx320m -Xss208m
_ mais encore une fois, il a fonctionné pendant un certain temps et a échoué.
Ma fonction imprime de manière récursive l’ensemble de l’arborescence de la définition du schéma, étonnamment le fichier de sortie traversé 820 Mo pour un fichier de définition de 4 Mo (bibliothèque Aixm) qui utilise à son tour 50 Mo de bibliothèque de définition de schéma (ISO gml).
avec cela, je suis convaincu que je dois éviter la récursivité, puis commencer l’itération et une autre manière de représenter la sortie, mais j’ai peu de difficulté à convertir toute cette récursivité en itération.
Vous devez disposer d’une configuration de lancement dans Eclipse pour pouvoir ajuster les paramètres de la machine virtuelle Java.
Après avoir exécuté votre programme avec F11 ou Ctrl-F11, ouvrez les configurations de lancement dans Exécuter -> Exécuter les configurations ... et ouvrez votre programme sous "Applications Java". Sélectionnez le volet Arguments dans lequel vous trouverez "arguments de la machine virtuelle".
C'est ici que -Xss1024k
va.
Si vous souhaitez que la configuration de lancement soit un fichier dans votre espace de travail (afin que vous puissiez cliquer avec le bouton droit de la souris et l'exécuter), sélectionnez le volet Commun, cochez la case Enregistrer sous -> Fichier partagé et accédez à l'emplacement où vous souhaitez lancer le fichier. Je les ai généralement dans un dossier séparé, car nous les archivons dans CVS.
Quand l'argument -Xss
ne fait pas le travail, essayez de supprimer les fichiers temporaires de:
c:\Users\{user}\AppData\Local\Temp\.
Cela a fait le tour pour moi.
Observez le parcours de Morris dans l’ordre dans l’ordre, qui utilise un espace constant et qui tourne dans O(n) (jusqu’à 3 fois plus longtemps que votre parcours récursif normal - mais vous économiserez énormément sur l’espace). Les nœuds sont modifiables, vous pouvez donc enregistrer le résultat calculé du sous-arbre lorsque vous revenez à sa racine (en écrivant directement dans le nœud).