IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

allocation/unallocation buffer curieuses..


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut allocation/unallocation buffer curieuses..
    Salut à tous, pb simple que j'ai résolu mais j'aimerais comprendre le pourquoi, je vous le soumets.

    j'ai un serveur qui écoute sur un port donné et qui launch un thread dédié au channel ouvert le temps de la transaction puis qui disparait. J'avais remarqué une fuite donc j'ai bien regardé mon code mais comme je n'avais rien trouvé ni jamais le temps je l'ai laissé tourner avec un reinit vers les 1 heure du matin mais bon pas satisfaisant du tout donc les vacances sont là pour clarifier le truc, et je trouve mais la raison me semble curieuse.

    Le code de lancement du serveur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    public void run()
    {
      // LISTEN ON PORT ------------------------------------------
      String msg = "Server calculation";
      boolean hasclient;
      try
        {
          SS = new ServerSocket(nuport);
          SS.setSoTimeout(time2wait);      // raised a SocketTimeoutException every 500 ms
        }
      catch (IOException ioe)
        {
          msg += ": can't listen on port " + Integer.toString(nuport);
          Sys.outMSGln(msg);
          Sstatus = SRVR_STOPPED;
          return;
        }
     
      msg += ": listen on port " + Integer.toString(nuport);
      Sys.outMSGln(msg);
     
      // RUN MAIN LOOP ------------------------------------------
      started = true;
      stopserver = false;
      Sstatus = SRVR_RUNNING;
     
      Sys.outMSGln(Sname+": main loop started");
      hasclient=false;
      while (!stopserver)
        {
          // Wait for a client
                  while (!hasclient && !stopserver)
                   {
                      try
                      {
                         Sclient= SS.accept();
                         hasclient=(Sclient!=null);
                       }
                       catch (SocketTimeoutException ste)  // exception result from setSoTimeout() function
                       { 
                       }
                        catch (IOException ioe)
                        { 
                          stopserver=true;
                       }
                   }
     
          if (stopserver) break;
     
          XCLI CLI=null;
          try
            {
              CLI = new XCLI (this, SS, Sclient);
              CLI.start();
            }
          catch (Exception e)
            {
            }
        }
     
      try { SS.close(); }    catch(IOException e) {}
     
      started = false;
      Sys.outMSGln(Sname+": main loop stopped");
    }
    ...
    Le code de lancement du client
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    class XCLI extends XThreadBase implements KONSTANT
    {
      final int           MAXREAD = 16384;
      byte               gbuffer[];         // used temporarily by each parameters
     
      public XCLI   ( XSERVER Server, 
                      ServerSocket SSserver, 
                      Socket SClient
                     )
      {
        super (Server, SSserver, SClient);
        gbuffer     = new byte[MAXREAD];
      }
     
      void run()
      {
        /**/
        doCalculations ();
        //gbuffer=null; // if I omit this reset a mem leake appears ??
        /** /
        doCalculations2 ();
        /**/
      }
     
      void doCalculations ()
      {
        // using gbuffer defined/declared above
        ...
      }
     
      void doCalculations2 ()
      {
        byte lbuffer[]     = new byte[MAXREAD];
        ...
      }
     
      protected void finalize()
      { 
        gbuffer=null;// no impact
      }
     
    }
    j'ai donc déclaré dans le client un buffer de byte local au thread que j'utilise dans doCalculations() :
    1. Si j'utilise doCalculations() la mémoire se bouffe à la vitesse grand v au bout de quelques milliers de connections. En mettant la ligne buffer=null; tout va mieux, en la mettant dans le finalize du thread cela ne régle rien non plus
    2. Si j'utilise un buffer local (docalculations2()), tout est au poil d'entrée sans reset de buffer bizarre n'est-il pas ?

    Cela voudrait il dire qu'il reste une référence 'vivante' de gbuffer donc du thread alors que la fonction alloue sur la stack le lbuffer, pourtant je n'ai pas de fuite de handle et j'ai mis un compteur de finalize() dans le thread et il y en a autant de créés que de détruits ????

    vos avis Messieurs ...

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Il faudrait voir la class XCLI complète et ses parent aussi. Vu ton comportement et tes chipotages sur le buffer, j'en concluerais que

    1) tu sort bien de ton run
    2) il reste des références à ta classe quelque part (sous forme de listener ou autres que tu aurais enregistré quelque part)

    Généralement, pour traquer rapidement un memory leak et pas y passer 3 semaines, on utilise un profiler. Tu lui demande une mapping de ta heap, tu regarde toutes les références indirectes vers ton thread et à partir de là, tu trouve assez vite qui a oublié de lacher ton thread

  3. #3
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut
    merci de ton intérêt.
    tu as raison j'aurais du y penser, je v jeter un coup d'oeil du côté de jconsole et jvisualvm
    thank's

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Moi c'est ce commentaire qui me fait tilter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    byte               gbuffer[];         // used temporarily by each parameters
    Si c'est temporaire pourquoi l'utiliser comme attribut d'instance ???


    Si ce buffer n'est utilisé que localement, autant l'utiliser comme un paramètre local et éviter de le conserver inutilement !

    a++

  5. #5
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut
    thank's adiGuba tu as tout a fait raison et le fait de le mettre en local règle le problème mais c surtout que sur l'instance il faut que je mette le buffer à null pour éviter le mem leak et rien en local car justement en sortant la référence est obligat annulée cela sous entend qu'il existe encore un lien vivant sur l'instance que je ne trouve pas. Le thread est bien mort (finalize() est exécutée), il faut que je cherche encore. Par contre corollaire il faut que je regarde si il n'existe pas un article qui traite des références sur le site... y a "encore" un truc qui m'échappe....
    merci à vous 2 pour vos remarques/suggestions/..

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Il faudrait avoir plus de code pour t'aider plus, mais en règle général plus tu restreints la porté des variables, plus tu facilites le travail du GC puisque la durée de vie de la variable est plus courte.


    Enfin finalize() indique simplement que l'instance de ton Thread va être supprimé. Mais rien ne garantie que ce soit le cas de tous ses attributs d'instances (il pourrait très bien être référencé ailleurs). De plus ta méthode finalize() est inutile et même contre-performante dans ce cas précis.
    Il est complètement inutile d'utiliser finalize() pour mettre à null les variables d'instances ! Le GC sait très bien faire cela ! La méthode finalize() doit uniquement être utilisé pour des ressources externes non-géré par le GC (fichier, socket, ...).
    Et c'est contre-performant car l'exécution de finalize() peut retarder la vrai libération de l'objet, car le GC devra s'assurer à nouveau que l'objet soit toujours inaccessible...


    Citation Envoyé par r2d2abc Voir le message
    Par contre corollaire il faut que je regarde si il n'existe pas un article qui traite des références sur le site... y a "encore" un truc qui m'échappe....
    Ce doit être traité dans les cours, mais je ne pense pas qu'il y ai de tutoriel spécifique...

    Qu'est-ce qui t'échappe ???


    a++

Discussions similaires

  1. Réponses: 0
    Dernier message: 17/12/2014, 14h34
  2. [DATA] Fonction CAT et "buffer allocated"
    Par alers dans le forum SAS Base
    Réponses: 3
    Dernier message: 27/11/2014, 14h17
  3. Buffer et allocation mémoire
    Par Magohamoths dans le forum C#
    Réponses: 4
    Dernier message: 11/10/2012, 14h01
  4. Affichage en passant par un buffer...
    Par Sirotilc dans le forum MFC
    Réponses: 5
    Dernier message: 27/05/2002, 21h00
  5. Alpha blending et Z-buffer directx 8
    Par Cesar4 dans le forum DirectX
    Réponses: 1
    Dernier message: 23/05/2002, 12h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo