|
|
|
![]() |
|
Strumenti |
![]() |
#21 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
In questo caso stiamo parlando di variabili statiche, il cui ciclo di vita termina quando la classe (istanza di tipo Class) viene eliminato. Ciò avviene per 2 motivi: il ClassLoader di riferimento decide l' unload, opure il ClassLoader stesso è soggetto al GC perchè non più referenziato da nessuno. Questo non si applica quando ad essere utilizzato è il classloader primordiale.
|
![]() |
![]() |
![]() |
#22 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Quindi alla fine non dipende dal tipo di classloader utilizzato ma solo quando sei tu che manualmente decidi di rimuovere la classe rimuovendo tutto il classloader.
__________________
![]() |
|
![]() |
![]() |
![]() |
#23 | |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Quote:
In realtà l' operazione manuale di unload (ottenibile anche scaricando esplicitamente il CL)non è fatta esplicitamente dal ClassLoader perchè non necessaria, in quanto le classi (non caricate per default) di cui nessuna istanza esiste posso essere gestite dal GC. Una stessa classe, caricata con CL differenti, viene infatti trattata come classi distinte. Ultima modifica di nuovoUtente86 : 15-05-2010 alle 14:28. |
|
![]() |
![]() |
![]() |
#24 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Inoltre allontanandoci dall' esempio di inizio thread, potrebbero esserci altri motivi per cui una variabile statica potrebbe essere eliminata dal GC. Ad esempio in un servlet container potrebbero essere compiute operazioni di reload dal motore di gestiore delle servlet.
|
![]() |
![]() |
![]() |
#25 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Sant'Eufemio come la fate complicata
![]() 1. c'è una sola condizione che determina l'unload di una classe. Una sola ed è sempre quella. 2. il runnable non funzionerebbe, per una questione di rami e compilatori molto furbi. La questione della concorrenza c'entra e non c'entra nel senso che un singleton non ha alcuna particolarità rispetto alle normali questioni che sorgono in contesti concorrenti. Quando l'autore del thread studierà... i thread, vedrà problemi e soluzioni. Deve essere immutabile? no, se io voglio un singleton mutabile che faccio, mi attacco al tram? Circa lo scaricamento bisogna fare attenzione perchè è una di quelle cose un po' cervellotiche fatta in modo tale che il programmatore non se ne debba curare. Prima che sorga la questione dello scaricamento uno deve aver passato delle vere e proprio forche caudine (non basta un class loader ad hoc per rendere qualcosa scaricabile). Nel dubbio, buttate sempre l'occhio alle specifiche http://java.sun.com/docs/books/jls/t...tion.html#12.7
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#26 | ||
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Quote:
Ne parla, in ogni caso, anche la sun con riferimento alle vecchie versioni del linguaggio. http://java.sun.com/developer/techni...ng/singletons/ Quote:
Mi riferivo a qualcosa del genere: Codice:
public class Persistenza implements Runnable { private Set contenitore=new HashSet(); public synchronized void run(){ try{ wait(); } catch(InterruptedException e){} } public void aggiungi( Object o ){ contenitore.add(o ); } public void rimuovi( Object o ){ ( contenitore.remove(o ); } |
||
![]() |
![]() |
![]() |
#27 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Ma dalla versione 1.2 (Java 2) in poi il problema è stato risolto, e ora siamo ben + avanti. Avevo presupposto che stessimo parlando delle versioni attuali di java. Per quanto riguarda le servlet (oddio, in effetti io ricordavo che avvenisse per le JSP, ma non posso escludere che avvenga anche per le servlet), in quel caso non ti devi preoccupare perchè c'è un classloader separato per ogni jar e quindi il classloader utilizzato è quello che caricherà tutta la tua applicazione e quindi ci riconduce paradossalmente al caso in cui si utilizzi il classloader di default in cui la classe statica verrà rimossa quando viene rimosso il classloader, che ovviamente corrisponde alla fine della tua applicazione. Per cui non credo che all'atto pratico ci sia qualche situazione, con le versioni attuali di java, in cui la tecnica del runnable sia di qualche utilità.... ergo se attualmente la utilizzi a quanto ne so potresti risparmiarti righe di codice e (pochi) cicli di cpu dato che non dovrebbe cambiare nulla (a meno di qualche caso MOLTO particolare che ad ora mi sfugge e di cui ancora non abbiamo discusso). ...cmq non mi avete detto che ne pensate riguardo la mia rivisitazione del codice postato all'inizio del thread, se avete qualche proposta per migliorarlo.. ![]()
__________________
![]() |
|
![]() |
![]() |
![]() |
#28 | |||
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Quote:
Quote:
Quote:
Non mi piace, però, l' utilizzo del tipo Class come discriminate e delle classi concrete come tipizzazione dei reference nel metodo applicativo, o almeno non in quel modo (per quanto poi l' esempio è semplice):lo scopo di un factory è quello di celare la costruzione degli oggetti, garantendo un funzionamento trasparente (ad esempio un factory potrebbe fornire i codec per diversi formati. Il cliente del factory method deve essere in grado di riprodurre il file conoscendo solo l' interfaccia ritornata dal factory, senza aver bisogno di conoscere quale concretizzazione effettivamente lavora ), altrimenti se so quale classe istanziare (se espone un costruttore pubblico) posso costruirmi l' oggetto da me (tralasciando ora possibili ottimizzazioni). Diverso ad esempio sarebbe il caso di una classe con costruttori privati, per cui si puo chiedere al factory di fare il lavoro per noi, possibilmente passandogli oltre al tipo richiesto, altri dati necessari alla scelta del costruttore corretto da invocare. Per restare, ancora, sull' esempio avrei optato per l' utilizzo delle enumeration. |
|||
![]() |
![]() |
![]() |
#29 | |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quote:
Il fatto è che avete fatto un papocchio (termine tecnico), una specie di riassunto dell'altro thread lunghissimo thread su java in cui ne ho lette veramente di tutti i colori. In buona fede ovviamente, direi nell'encomiabile desiderio di condividere del sapere quindi tanto di cappello. Proviamo però a fare un po' di ordine, se ci state. Prima di tutto quand'è che 'ste classi vengono scaricate. E qui già abbiamo un bel problema. Il class unloading è opzionale. Che significa dire che il class unloading è opzionale, che conseguenze ha, che ce ne frega? Dire che il class unloading è opzionale significa che qualsiasi programma il cui funzionamento dipenda dallo scaricamento di una classe è errato. Perchè potrei sempre eseguirlo su una piattaforma che non usa il class unloading e restare fregato. Quindi noi che siamo bravi e lo sappiamo mai e poi mai useremo le proprietà del class unloading per far fare o non fare qualcosa al nostro programma. Nel caso in cui una certa implementazione di Java supporti lo scaricamento allora lo scaricamento è vincolato ad una precondizione, vale a dire che è possibile solo se si verifica uno e un solo fatto: che il class loader che ha caricato quella classe sia cestinabile dal garbage collector. Una classe può essere scaricata se e solo se il suo class loader è cestinabile. Questa è l'unica condizione, non ce ne sono altre. Sempre specifiche alla mano, mi raccomando: è l'unico modo per essere quasi sicuri. Dico quasi perchè a volte ci sono dei bei rebus anche lì dentro. Allora, in tanto la classe è scaricabile in quanto il suo class loader non sia più raggiungibile. La raggiungibilità si determina in base al flusso di esecuzione di tutti i thread: dal momento in cui nessuno può più accedere ad un certo riferimento in poi l'oggetto riferito cessa di essere raggiunbile e può essere cestinato. Naturalmente se fosse così facile saremmo qui coi calzoni corti il cerchio e la palla. L'implementazione è autorizzata ad eseguire tutte le trasformazioni del codice che non pregiudicano gli effetti collaterali derivanti dall'esecuzione delle istruzioni del programma nell'ordine in cui appaiono nel codice, secondo i diversi flussi di esecuzione. Che vuol dire? In soldoni che se ho un riferimento che punta sempre ad un certo oggetto non posso dire per ciò stesso che quell'oggetto non sarà mai cestinato. L'implementazione può fregarmi quell'oggetto da sotto il naso. Quando può farlo? Tutte le volte in cui la presenza o l'assenza di quell'oggetto non hanno effetti collaterali. Il runnable proposto da nuovoUtente86 fa difetto per una ragione simile. Lo anticipo ma sempre specifiche alla mano lo scaricamento di una classe è privo di effetti collaterali da cui consegue che un blocco di istruzioni il cui unico effetto sia quello di impedire lo scaricamento sia partimenti privo di effetti collaterali. Se ciò che non ha effetto è rimuovibile, il run del nostro Runnable potrebbe benissimo non essere mai eseguito. Ripetiamo ancora: quando il class loader è cestinabile allora, e solo allora, saranno cestinabili le classi. Non c'è la possibilità di un comportamento diverso. se l'avessimo non sarebbe più il Java che conosciamo dalle sue specifiche. Domanda: le specifiche dicono che in virtù di questa regola, il bootstrap loader risulta non essere mai cestinabile e quindi le classi che esso ha caricato sono parimenti eterne. Le specifiche non dicono "le classi caricate dal bootstrap loader non sono scaricabili" nè dicono "il bootstrap loader non è cestianbile". Dicono che in virtù del fatto che le classi siano scaricabili solo quando il loro classloader sia cestinabile risulta che il bootstrap loader non sia cestinabile nè scaricabili le classi che esso abbia caricato. Perchè?
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
![]() |
![]() |
![]() |
#30 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Effettivamente, le ottimizzazioni del compilatore/runtime possono rendere vano quel riferimento.
Il fatto che le classi caricate dal bootstrap loader non possano essere scaricate, dovrebbe dipendere dal fatto che il loader primordiale costituisce la root dell' albero di delegazioni e non ha parent se non l' istanza della JVM stessa. Mentre tutti gli altri loader definiti (che sono oggetti java comuni), ricevono (se non esplicitamente indicato) come genitore l' Application loader (che è un user-defined esso stesso) che poi è quello che carica, per default, le classi definite dall' utente. |
![]() |
![]() |
![]() |
#31 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Il senso è quello ma precisiamo che non sono le ottimizzazioni a cambiare le carte in tavolo, è proprio il linguaggio a dire che non si può legittimamente dedurre che capiti ciò che vorremmo usando quel runnable per quello scopo.
Circa il bootstrap loader non è un problema di delegati ma di raggiungibilità dei riferimenti. O il bootstrap loader è sempre raggiungibile (come dicono ad esempio le specifiche della JVM che però non sono parte delle specifiche del linguaggio) o esiste almeno un'istanza tra quelle caricate dal bootstrap loader che dobbiamo considerare sempre raggiungibile, il che è presumibilmente vero per Object di cui lo stesso boot strap loader, in quanto ClassLoader è istanza (sempre secondo il linguaggio). Propenderei per la seconda ipotesi. Circa la controproposta di Tigershark, è problematica, il che è bello perchè offre un sacco di spunti di discussione. Uno potrebbe dire che siccome i costruttori dei frutti sono pubblicamente accessibili non siano dei singleton: ne posso creare quanti ne voglio. Il problema è che una classe Java con un costruttore privato non è estendibile (al di fuori della classe in cui è dichiarata) ma è comunque istanziabile a piacimento. Non giurerei tuttavia che questa considerazione sia stata fatta. Non è thread-safe ma la questione è irrilevante: non ci sono particolarità riguardo all'uso concorrente di un singleton rispetto a quanto varrebbe per qualsiasi altro pattern. E' una factory? Per esserlo deve risolvere il problema dell'amorfismo dei costruttori. Io direi di no. E' vero che non ci sono "new" ma c'è una relazione di identità tra il tipo dell'istanza creata a la definizione della sua classe: se passo un Orange non c'è verso che possa darmi un sottotipo di Orange. Quindi si chiama Factory ma non è una factory. C'è un poi il macignone: clazz.newInstance() newInstance() è sempre un problema in Java perchè non c'è uno strumento sintattico che costringa una classe ad avere un costruttore vuoto. Impediamo gli errori runtime dovuti alle stringhe per introdurne errori runtime di una specie diversa. Si può invece obbligare un'istanza ad avere un metodo senza argomenti, quindi prima di arrenderci dovremmo provare con una cosa tipo: Codice:
interface Creator { IFruit create(); public static IFruit getFruit(Creator c) { usare c.create() che c'è per forza } Per il resto, il suo lavoro di contenitore di istanze condivise lo fa.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#32 | |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Quote:
|
|
![]() |
![]() |
![]() |
#33 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Sì, il mitico setAccessible. Il security manager non ci aiuta perchè siamo di fronte ad una libreria. Forse si potrebbe fare qualcosa con le classi locali. Si può istanziare riflessivamente una classe locale? Non ho mai indagato. In teoria se non è sintetica si dovrebbe poter fare.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#34 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
però probabilmente creando un security manager ad-hoc, più restrittivo, si potrebbe neutralizzare il setAccessible.
|
![]() |
![]() |
![]() |
#35 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Il problema è che è una libreria, non un programma. Io programmatore piglio la libreria VeryCleverSingletonFactory XYZ per usarla nel mio programma, se voglio posso sempre creare istanze dei singleton, anche se non dovrei.
Nulla di straordinario in sè, non è raro che un linguaggio abbia un limite rispetto alla capacità di rappresentare certi fenomeni. Ma un problema di un certo interesse che ne sorge è: qual'è il limite dello sforzo che devo fare per aderire ad una certa rappresentazione nei casi in cui sia certa l'impossibilità di riprodurla esattamente? Detto altrimenti, se un singleton non deve essere istanziabile al di fuori della factory e io so già che non potrò mai impedire in termini assoluti l'istanziabilità, ha senso star lì a disquisire di costruttori pubblici e privati? A naso uno direbbe che la differenza tra un costruttore pubblico e uno privato vi sia, se non altro perchè il secondo non è invocabile salvo artifici riflessivi. E tuttavia il singleton non vuole qualcosa di "difficilmente istanziabile al di fuori di", vuole qualcosa di non istanziabile. E' un caso di approssimazione irrazionale.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#36 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Ma dotando la classe candidata a singleton di un campo privato statico da usare come counter delle istanze create e codificando nel costruttore privato un controllo su quel campo (che viene autoincrementato ad ogni invocazione del costruttore) che lancia un'eccezione (o peggio uccide la virtual machine
![]() Ok, avevo voglia di scrivere la mia boiata ![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
#37 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
L' utilizzo di unaa exception potrebbe tamponare il problema. Da valutare eventuali effetti collaterali su costruzioni lecite.
|
![]() |
![]() |
![]() |
#39 | |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Quote:
|
|
![]() |
![]() |
![]() |
#40 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Il ragionamento che fai è giusto: l'uso di setAccessible può essere ristretto dalle politiche di sicurezza.
L'obiezione è questa: le restrizioni di sicurezza sono un'opzione di esecuzione del programma. Non ci sono restrizioni di sicurezza applicabili quando io programmatore vado ad usare una certa libreria. Cioè io dico: metto questo costruttore a private così il programmatore che userà questa libreria non potrà istanziare la mia classe. Tu prendi e usi setAccessible. Io che ho scritto la libreria posso obbligare il tuo uso di setAccessible a rilasciare un'eccezione di sicurezza? Direi di no. Non posso evitare che si verifichi ma neppure posso garantire che capiti.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:29.