Bienvenido
Invitado
Únete a nosotros!
El registro es completamente gratuito y
podrás acceder a todas las partes de la web
Crear una cuenta
|
|
|
|
Login:
Usuario:
Contraseña:
|
|
|
|
|
|
|
Administradores |
No Conectado |
l0kit0 |
|
No Conectado |
cristian |
|
No Conectado |
lucho |
|
No Conectado |
janus |
|
No Conectado |
chgvisual |
|
No Conectado |
Ecthelyon |
|
|
|
|
|
|
Colaboradores |
No hay
Colaboradores conectados |
|
|
|
|
Miembros: |
Conectados |
Miembros: |
Miembros: |
0 |
Invitados: |
Invitados: |
5 |
Total: |
Total: |
5 |
|
|
|
|
|
Miembros Online |
No
hay miembros conectados |
|
|
Oh, esos pobres pícaros que están en las grandes ciudades
de a política mundial, hombres jovenes, dotados, torturados por
la ambición, que consideran su deber decir su palabra acerca de
todos los sucesos -!y siempre sucede algo!
-- Friedrich Nietzsche |
|
|
Foros de eXactas.org
No estás conectado |
|
|
|
|
duilio
Moderador
Mensajes: 118
Registrado: 5/6/2004
Estado: Desconectado
|
enviado el
27/11/2005 a las 00:04 |
Un
tiempo atrás un compañero de LCC me comentó que en
su lugar de trabajo, donde tienen algunos servidores corriendo
aplicaciones Java,
debían reiniciar éstos todas las noches, pues iban
aumentando crecientemente su uso de la memoria,
ralentizando el sistema hasta un nivel que los volvía poco
usables.
En aquel momento imaginé que la causa se encontraría en
algunos programas nativos (no-Java)
invocados mediante JNI de una manera incorrecta, con lo cual la
solución pasaría por programar correctamente estos
wrappers.
Sin embargo un programa Java
puro también puede malgastar memoria,
como se verá a continuación.
Una aparición común de este fenómeno se da cuando
se mantiene una colección de ciertos datos asociados a objetos
transitorios mediante un mapeo (HashMap). Por ejemplo, un servidor que
escucha en un puerto y quiere mapear cada socket creado al abrir una
conexión con un determinado usuario, para facilitar
procesamientos posteriores:
code:
import java.util.*;
import java.net.*;
class User {
private String name;
public User(String name) { this.name = name; }
}
class SocketManager {
private Map<Socket,User> m = new HashMap<Socket,User>();
public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
public void removeUser(Socket s) {
m.remove(s);
}
}
public class Leaky1
{
public static void main (String[] args)
{
ServerSocket serverSocket;
Socket clientSocket;
SocketManager socketManager = new SocketManager();
String userName;
int userId = 1;
try {
serverSocket = new ServerSocket(1025);
while (true) {
clientSocket = serverSocket.accept();
userName = "Testa" + userId;
System.out.println ("New user " + userName);
socketManager.setUser(clientSocket, new User(userName));
// here you will do something useful, probably launching
// a thread for doing the job
clientSocket.close();
userId++;
}
}
catch (Exception e) {
System.exit(1);
}
}
}
Aquí el servidor escucha en el puerto 1025 en todas las
interfaces locales. El ejemplo es un poco irreal pues se crea un
usuario nuevo cada vez que se abre una conexión, en un sistema
con validación, por ejemplo, la lista de usuarios estará
precargada, y he allí el punto fundamental (el tiempo de vida de
los User).
Si bien el garbage collector debería limpiar los sucesivos clientSocket
devueltos por accept() (ya que al retornar accept() un
nuevo Socket, sobreescribe el anterior, perdiendo la referencia), esto
no sucede así, pues el socket sigue referenciado en el mapeo.
Sin embargo el programa ya no utilizará dicho socket, y aunque
intentara hacerlo no podría, pues no tiene una referencia a
él.
Hay que notar que el garbage collector no comete ningún error:
no recoge los objetos clientSocket pues aún no ha
terminado su tiempo de vida (que es el tiempo de todo el programa!),
aunque sí es cierto que desde el punto de vista lógico
del programa, los clientSocket cuyas referencias se van
perdiendo, han terminado su vida útil. Moraleja: (vida
de un objeto) == (vida útil de un objeto) es algo que hay que
verificar, no necesariamente vale siempre.
En el programa anterior, lo que quisiéramos es que una vez
cerrado el Socket cliente y perdida su referencia, su memoria
estuviera lista para ser reutilizada. Esto se puede lograr usando una WeakHashMap
en lugar de la HashMap, un mapeo construído con
referencias débiles. Una referencia débil permite
referenciar un objeto, pero sin garantías de que éste no
será recogido por el GC. Es decir que antes de utilizar el
objeto mediante la referencia débil, se deberá chequear
siempre que la misma no sea null, algo engorroso, pero es una
molestia que se puede minimizar con un buen diseño, y que
será mejor que tener que reiniciar la aplicación
regularmente.
Utilizando una WeakHashMap en el programa anterior, todos los objetos
serán recolectados luego de terminada su vida útil. Por
supuesto otra solución, de hecho la primera que se le ocurre a
alguien acostumbrado a programar gestionando la memoria
explícitamente, es utilizar SocketManager.remove(clientSocket) en
el momento oportuno. Sin embargo esto puede ser no trivial en una
aplicación real (en una escenario fuertemente concurrente), y
además el ejemplo pretende mostrar lo siguiente: que aún
cuando se esté programando en un entorno con memoria
gestionada, se deberán conocer los límites y la forma en
que se lleva a cabo dicha gestión, ya que el GC por sí
solo no puede garantizar completamente una utilización correcta
de la memoria.
Saludos,
Duilio.
[Editado el 27/11/2005 por duilio]
|
|
|
cristian
Administrador
Mensajes: 114
Registrado: 10/4/2004
Estado: Desconectado
|
enviado el 1/12/2005 a las 00:24 |
Muy
interesante, un caso patológico para pizarrón. Pero no
será que el garbage collector detecta una referencia a un
"objeto tan inutil" que no vale la pena gastar cpu ni siquiera para
borrarlo?.
____________________
Cristian Rosa
|
|
|
Académico--------------------
> Novedades > Ciencias Exactas, Ingeniería y
Agrimensura > ACMLA
> Computación Cuántica
> Ciencia Política y Relaciones Internacionales >
Ciencias Médicas > Ciencias Bioquímicas y
Farmacéuticas > Arquitectura, Planeamiento y
Diseño > Derecho > Odontología
> Ciencias Agrarias > Ciencias Veterinarias >
Ciencias Económicas y Estadística
> Universidad Austral - Encuentros
> Universidad Austral - Examenes
> Universidad Austral - Cursado
> Universidad Austral - El ágora >
Psicología > Humanidades y Artes >
Comunicacion Social > Politécnico Superior >
Superior de Comercio General-------------------- >
Discusión General > eXactas > Arte y
Cultura > Música
> Literatura
> Cine y Teatro > Computación >
Software libre > eXactas::Proyectos |
|