Newsgroup: it.comp.java
Titolo: fermi tutti: garbage collector troppo efficiente!

secondo voi qual è il metodo migliore per evitare che il garbage 
collector faccia il suo lavoro nel caso di variabili statiche?
Facciamo un esempio: un utente avvia un'applicazione che usa alcune 
variabili statiche. L'utente fa qualche chiamata e le variabili, essendo 
statiche, vengono aggiornate senza ripartire da zero tutte le volte. Ora 
l'utente va a pranzo e lascia l'applicazione aperta. Al suo ritorno il 
garbage colletor avrà già fatto pulizia delle variabili statiche 
perdendo delle informazioni preziose per l'utente.
A questo punto le strategie posso essere differenti. Una potrebbe essere 
  quella di lasciare un thread attivo che non faccia fondamentalmente 
nulla se non ciclare in modo da lasciare tutto il tempo un riferimento 
attivo all'applicazione, ma risulta essere pesante dopo poco (la 
macchina dopo qualche minuto perde un sacco di prestazione cosa che mi 
fa pensare ad un pesante spreco di risorse). Un'altra potrebbe essere 
salvare in qualche modo lo stato dell'applicazione su disco, ma il 
ripristino potrebbe essere pesante perchè l'applicazione in questione è 
piuttosto grossa.
Cosa avreste fatto voi? Esiste - oppure - una qualche chiamata al 
garbage colletor che gli dica "non toccare queste risorse"?
curioso di leggere le vostre risposte,
  padreTony

 collector faccia il suo lavoro nel caso di variabili statiche?
Io non farei uso massivo di variabili static, se non per costanti final o
come strumento per i singleton.
Userei normalmente Oggetti , di cui hai il controllo.
Nicola
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

   padreTony
Più che altro sarei curioso di sapere da dove ti è arrivata questa idea...
-- 
Fermiamo Scientology prima che sia troppo tardi!!!
http://xenu.com-it.net
 - 
http://xenu.freewinds.cx/
(per rispondere personalmente leva IlDitoDalCulo)

 
devo sviluppare un'applicazione che consenta la cooperazione tra utenti 
sulla base di un modello. una specie di simulazione interattiva insomma.
l'applicazione è realizzata su web e usa java e svg per la grafica.
succede proprio come per il nostro utente immaginario che se lancio 
l'applicazione e vado a farmi un pò di cavoli miei, quando torno trovo 
tutto resettato perchè alla prima richiesta qualsiasi che eseguo scatta 
un eccezione che non c'è nessuno ad ascoltarmi dall'altra parte.
Ho supposto fosse un problema di gc perchè tempo fa, per gioco, creai un 
piccolo sito con del codice java che realizzava la classica form di un 
sondaggio come quelle che si trovano comunemente sul web. Avevo usato 
delle variabili statiche che mantenevano il valore percentuale dei voti. 
Ebbene, se dopo un pò di votazioni mi fermavo ed aspettavo, quando poi 
riandavo a votare scoprivo che i contatori erano stati azzerati: le 
variabili erano state cancellate e alla nuova richiesta ricreate.
padreTony

 padreTony
Non è che invece andava in time-out qualcosa?
Il gc non dovrebbe fare le cose che tu gli imputi, e a meno di 
ottimizzazioni particolari non dovresti neppure interessartene. Chiamare 
metodi come gc.pulisciOra() (non esiste eh! ;-)  ),  non influenza la 
semantica del tuo programma ma solo le prestanzioni. Quindi forse il 
problema sta nel codice, o nelle configurazioni delle sessioni e dei 
relativi time-out credo...
(non sono un guru cmq...quindi ti ho detto solo quello che credo). 

 perdendo delle informazioni preziose per l'utente.
Il garbage collector non può fare pulizia di alcuna variabile.
Quello che fa il garbage collector è disallocare gli oggetti che non
sono più referenziati da alcuna variabile, sia essa statica o meno.
Se effettivamente nella tua applicazione le variabili statiche vengono
reinizializzate il motivo va cercato da tutt'altra parte, non nel
lavoro del garbage collector.
In un'altro post hai parlato del fatto che e' possibile forzare il gc a
ripulire la memoria. In realtà questo non e' vero. Quello che puoi
fare è suggerire al GC di pulire, ma nulla ti garantisce che lo faccia
effettivamente.
Inoltre ho visto che parli di applicazioni web.
Sei sicuro che il problema stia nelle variabili statiche e non in
attributi di sessione? La sessione ha un timeout e quando questo scade
viene buttata via insieme al suo contenuto.
Andrea

 padreTony
Ora ci siamo. All'interno di applicazioni web non devi usare variabili
statiche, usa piuttosto gli attributi. Questo perchè non puoi mai sapere
quanti e quali siano i container che stanno usufruendo della tua classe o
della tua pagina JSP... addirittura potrebbero essere in esecuzione due
container diversi all'interno della stessa JVM (difficile ma possibile).
Usanto gli attributi invece, affidi la gestione della visibilità al
container, che può decidere il modo migliore per conservare i tuoi valori.
Puoi impostare i tuoi attributi in diversi posti (dipende dall'uso che ne
fai):
1) a livello di Web Application:
http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletContext.html
Puoi usare i metodi setAttribute/getAttribute di ServletContext per
impostare attributi visibili da tutte le servlet e pagine jsp nella stessa
Web Application. Questi attributi rimangono validi finchè la WebApplication
rimane attiva, che corrisponde il più delle volte al ciclo di vita
dell'intero server.
2) a livello di sessione:
http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpSession.html
Quando inizi ad usare i metodi di questa interfaccia (a te servono sempre
setAttribute/getAttribute), il container genere automaticamente un cookie
che verrà ritrasmesso dal browser dell'utente a ogni chiamata diretta alla
tua Web Application. Gli attributi salvati qui sono visibili da tutte le
servlet/jsp nella stessa Web Application, ma riguarderanno sempre e solo il
browser che ha generato la sessione.
3) a livello di richiesta:
http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html
Gli attributi salvati qui sono validi soltanto per l'intera durata della
transazione HTTP, quindi sono visibili alla servlet/pagina jsp invocata, e
per tutte le servlet/pagine jsp che saranno richiamate in sequenza con
forward/include:
http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/RequestDispatcher.html
Vedi un po' quello che ti piace di più


 perdendo delle informazioni preziose per l'utente.
Il garbage collector non può fare pulizia di alcuna variabile.


 
non dovrebbe esseri nulla che possa andare in time-out, avrebbe potuto 
solo la sesisone ma me ne sono guardato bene dal consentirlo: la sesione 
non scade mai!
il modo per dire al gc "pulisci ora" c'è ed è semplicemente:
java.lang.Runtime.getRuntime().gc();
dopo questa linea di codice il gc ha fatto le sue pulizie! :)
Dici bene che non modifica la semantica ed è meglio perchè se ora 
stessimo veramente parlando di semantica vorrebbe dire che siamo davanti 
un problema molto più grosso. Spero che invecela cosa possa risolversi 
in modo meno gravoso..
   padreTony

 java.lang.Runtime.getRuntime().gc();
Dalla documentazione del metodo gc:
----------------------------------------------
Runs the garbage collector. Calling this method suggests that the Java
virtual
machine expend effort toward recycling unused objects in order to make
the
memory they currently occupy available for quick reuse. When control
returns
from the method call, the virtual machine has made its best effort to
recycle
all discarded objects.
----------------------------------------------
"suggests" e "best effort" significa che non hai nessuna garanzia sul
fatto che la memoria sia stata effettivamente liberata.
Quando si dice che l'esecuzione della gc non modifica la semantica
dell'applicativo significa che l'esecuzione procede nello stesso esatto
modo sia che questa operazione venga fatta sia che non venga fatta.
L'unica cosa che può cambiare sono le prestazioni.
Quando dici "il gc mi reinizializza le variabili statiche" stai dicendo
che l'esecuzione del gc cambia la semantica del tuo programma.
Ovviamente tale affermazione è necessariamente falsa (a meno che
quelli della sun non abbiano fatto qualche cavolata di dimensioni
immani, e permettimi di dubitarne): il tuo problema non può in alcun
modo dipendere dal gc.
A questo punto direi che, se vuoi un aiuto piu' efficace, e' il momento
di descrivere meglio quello che ti succede (magari postando un esempio
di codice).
Andrea


A rafforzare tutte le cose ( sensate ) che hanno detto tutti, per quanto ne
so io il GC dovrebbe agire ad intervalli molto ma molto piu' brevi di quelli
che descrivi tu, che mi pare parlavi di 2 spaghi o la telefonata con la
sorella.
cya Nicola


ho riletto le vostre risposte e mi torna tutto quello che avete detto. 
Così ho riguardato qualcosa e.. avevo dimenticato di annullare il time 
out della sessione! eh eheh..
Spero di far bene decidendo che la sessione non debba scadere. Penso sia 
meglio che gestisca io la cosa a mano (tipo "l'utlimo che esce chiude la 
porta"), perchè se qualcuno rimane loggato il sistema deve poter andare 
avanti in qualunque momento. Cosa ne dite?
comunque sia grazie a tutti per l'aiuto!!
   padreTony


te copoooooooooooooooooooo ;-) 


Come gia' ti disse qualcun altro la cosa e' estremamente pericolosa. La
spiegazione e' semplicissima, in quanto una web app in stato "normale" sta
attiva anche un anno, il che significa che se anche si collegano 5 utenti al
giorno ne hai gia' + di 1500. Insomma la tua webapp diventa una bomba ad
orologeria.
ciao Nicola


 avanti in qualunque momento. Cosa ne dite?
Che fai malissimo dato che chi esce di solito non chiude la porta.
Voglio dire che se uno chiude il browser la sessione rimane aperta, dato 
che questo non segnala di certo la cosa al server. L'unico modo per 
assicurarsi che una sessione venga prima o poi chiusa e' utilizzare il 
timeout.
Ovviamente bisogna in tal caso gestire il fatto che se la sessione scade 
e qualcuno prova ad utilizzare quella sessione, bisognera' dargli una 
risposta sensata (tipo: "la tua sessione č scaduta: ripetere il login").
Andrea

 avanti in qualunque momento. Cosa ne dite?
Stai usando la sessione per cose per cui non è stata pensata.
Nella sessione dovresti tenere solo informazioni riguardanti l'utente, e
niente che possa essere bloccante. Probabilmente dovresti usare al posto
della sessione il context dell'applicazione.
uL 
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it



Leggi il mio ultimo post riguardo agli attributi impostabili su
contesto/sessione/richiesta. Dovrebbe esserti naturale il capire qual'è il
posto migliore dove inserire le tue variabili...


 
Penso che la cosa migliore sia impostare un time out nullo a livello di 
servlet context ed uno alto (tipo un paio d'ore) a livello di session 
http. Voglio inserire poi un controllo sulle sessioni in modo da 
ivalidare quelle "ripetute" nel caso in cui un utente per qualche motivo 
cerchi di rientrare con una sessione già "usata"
Grazie a tutti per i consigli
   padreTony

 padreTony
Tony, ormai ti abbiamo preso tutti a cuore.
Non ti preoccupare di mettere il controllo. Da volerle lasciare aperte fino
al 2010 ora vuoi controllarle una per una.
La sessione resta attiva fino a quando il client ( che usa un browser ) non
chiude tutte le sue finestre del browser ( o spegne la macchina). Se apre
100 finestre la session e' sempre la stessa. mentre se esce e rientra dal
browser avra' una nuova session e ci penssara' il fido GattoTom a eliminare
la precedente.
cya Nicola
