property - Alcance de las propiedades del sistema Java
system.getproperty java (7)
En Java utilizamos el método System.setProperty () para establecer algunas propiedades del sistema. De acuerdo con este artículo, el uso de las propiedades del sistema es un poco complicado.
System.setProperty () puede ser una llamada malvada.
- Es 100% hostil a los hilos
- Contiene variables super-globales
- Es extremadamente difícil depurar cuando estas variables cambian misteriosamente en tiempo de ejecución.
Mis preguntas son las siguientes:
¿Qué tal el alcance de las propiedades del sistema? ¿Son específicos para todas y cada una de las máquinas virtuales o tienen una "naturaleza Súper Global" que comparte el mismo conjunto de propiedades en todas y cada una de las instancias de máquinas virtuales? Supongo que la opción 1
¿Hay alguna herramienta que pueda usarse para supervisar los cambios de tiempo de ejecución para detectar los cambios en las propiedades del sistema? (Solo por la facilidad de detección de problemas)
Cuando inicia una nueva JVM, hace una copia de las variables del entorno y las utiliza para todo el ciclo de vida de la misma. Entonces, si haces cambios a ese entorno, permanecerían confinados a él. El extraño comportamiento que he encontrado y sobre el que estoy investigando es ligeramente diferente: si comienzo una JVM declarando algunas de las variables de entorno (argumento -D en la línea cmd) que afectan el comportamiento de las bibliotecas que uso en mis aplicaciones. Pero si, dentro del código java (donde están visibles), les hago cambios, parece que estos cambios no afectan el comportamiento de las bibliotecas. ¡Lo extraño es que estamos en la misma JVM!
Hay una copia de las propiedades por VM. Tienen los mismos problemas que otras estáticas (incluidos los singletons).
Supongo que, como hackeo, llamas a System.setProperties
a una versión de Properties
que responde de manera diferente según el contexto (hilo, pila de llamadas, hora del día, etc.). También podría registrar cualquier cambio con System.setProperty
. También puede establecer un SecurityManager
registra las comprobaciones de seguridad para los permisos relevantes.
Las propiedades del sistema son por proceso. Esto significa que son más globales que los campos estáticos, que son por clase cargador. Entonces, por ejemplo, si tiene una sola instancia de Tomcat ejecutando varias aplicaciones de Java, cada una de las cuales tiene una clase com.example.Example
con un campo estático llamado globalField
, entonces las aplicaciones compartirán las propiedades del sistema, pero com.example.Example.globalField
se puede establecer en un valor diferente en cada aplicación web.
No dice cuál es su motivación para usar las propiedades del sistema.
Utilizamos Spring para nuestra configuración y establecemos propiedades iniciales usando un archivo de propiedades que se inyecta en el XML. Los cambios en la configuración mientras se ejecuta la aplicación se realizan utilizando JMX.
Hay, por supuesto, muchas otras maneras de cambiar la configuración en Java usando el archivo de propiedades, la configuración basada en xml, etc.
Sí, las "propiedades del sistema" son por VM (aunque hay varias propiedades "mágicas" que contienen información sobre el sistema host, por ejemplo: "os.name", "os.arch", etc.).
En cuanto a su segunda pregunta: no conozco esta herramienta, pero si le preocupa que las propiedades del sistema se modifiquen, podría usar un SecurityManager especial para evitar (y quizás incluso rastrear) los cambios en la propiedad del sistema.
Su alcance es la JVM en ejecución, pero a menos que tengas algunos problemas con el cargador de clases esotérico, una variable estática con un objeto de propiedades hará lo mismo, y con la oportunidad de sincronizar o hacer cualquier otra cosa que necesites.
Alcance de las propiedades del sistema
Al menos al leer las Especificaciones API para el método System.setProperties
, no pude obtener una respuesta si las propiedades del sistema son compartidas por todas las instancias de la JVM o no.
Para averiguarlo, escribí dos programas rápidos que establecerán la propiedad del sistema a través de System.setProperty
, usando la misma clave, pero diferentes valores:
class T1 {
public static void main(String[] s) {
System.setProperty("dummy.property", "42");
// Keep printing value of "dummy.property" forever.
while (true) {
System.out.println(System.getProperty("dummy.property"));
try {
Thread.sleep(500);
} catch (Exception e) {}
}
}
}
class T2 {
public static void main(String[] s) {
System.setProperty("dummy.property", "52");
// Keep printing value of "dummy.property" forever.
while (true) {
System.out.println(System.getProperty("dummy.property"));
try {
Thread.sleep(500);
} catch (Exception e) {}
}
}
}
(¡Tenga en cuenta que ejecutar los dos programas anteriores hará que entren en un ciclo infinito!)
Resulta que, al ejecutar los dos programas usando dos procesos java
separados, el valor de la propiedad establecida en un proceso JVM no afecta el valor del otro proceso JVM.
Debo añadir que estos son los resultados para usar JRE de Sun 1.6.0_12, y este comportamiento no está definido al menos en las especificaciones de API (o no he podido encontrarlo), los comportamientos pueden variar.
¿Hay alguna herramienta para monitorear los cambios de tiempo de ejecución?
No que yo sepa. Sin embargo, si uno necesita verificar si hubo cambios en las propiedades del sistema, puede retener una copia de las Properties
a la vez y compararla con otra llamada a System.getProperties
; después de todo, Properties
es una subclase de Hashtable
, por lo que la comparación se realizaría de manera similar.
A continuación se muestra un programa que muestra una forma de verificar si ha habido cambios en las propiedades del sistema. Probablemente no sea un método elegante, pero parece hacer su trabajo:
import java.util.*;
class CheckChanges {
private static boolean isDifferent(Properties p1, Properties p2) {
Set<Map.Entry<Object, Object>> p1EntrySet = p1.entrySet();
Set<Map.Entry<Object, Object>> p2EntrySet = p2.entrySet();
// Check that the key/value pairs are the same in the entry sets
// obtained from the two Properties.
// If there is an difference, return true.
for (Map.Entry<Object, Object> e : p1EntrySet) {
if (!p2EntrySet.contains(e))
return true;
}
for (Map.Entry<Object, Object> e : p2EntrySet) {
if (!p1EntrySet.contains(e))
return true;
}
return false;
}
public static void main(String[] s)
{
// System properties prior to modification.
Properties p = (Properties)System.getProperties().clone();
// Modification of system properties.
System.setProperty("dummy.property", "42");
// See if there was modification. The output is "false"
System.out.println(isDifferent(p, System.getProperties()));
}
}
¿Propiedades no es seguro para subprocesos?
Hashtable
es seguro para subprocesos , por lo que esperaba que las Properties
lo fueran y, de hecho, las especificaciones de API para la clase Properties
confirman:
Esta clase es segura para subprocesos: varios subprocesos pueden compartir un único objeto de
Properties
sin necesidad de sincronización externa., Formulario serializado