Archivos por Etiqueta: java

Java: Getting Memory Usage with MemoryMXBean

Estoy madurando una idea y me he encontrado con una de las muchas perlas de JMX de Java, la MemoryMXBean:

MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
System.out.println("HeapUsage: " + mbean.getHeapMemoryUsage());
System.out.println("NonHeapUsage: " + mbean.getNonHeapMemoryUsage());

El resultado:

HeapUsage: init = 16777216(16384K) used = 7772720(7590K) 
           committed = 16252928(15872K) max = 1037959168(1013632K)

NonHeapUsage: init = 2359296(2304K) used = 15099032(14745K) 
              committed = 15327232(14968K) max = -1(-1K)

Referencias:
java.lang.management.ManagementFactory

Java: Skeleton for Workers / Batch processing

Un pequeño esqueleto que persigue:

  1. Que no se coma la CPU.
  2. Que no se coma el espacio el disco soltando trazas de fallo.
  3. Que ante una excepcion “extraña” no se muera el worker.
@Override
public void run() {
	int c = 0;
	while (!isShutdown()) {
		if ((++c % 10000) == 0) { // Anti cpu eater
			intrSleep(1);
		}
		try {
			// ... do things
		} catch (ControlledException e) {
			// ... do things
			log.error("ControlledException: " + e.toString(), e);
			intrSleep(100); // Anti disk space eater
		} catch (Exception e) {
			// ... last resort
			log.error("Unknown Exception: " + e.toString(), e);
			intrSleep(100); // Anti disk space eater
		}
	}
}
private static void intrSleep(final long millis) {
	try {
		Thread.sleep(millis);
	} catch (InterruptedException e) {
		Thread.currentThread().interrupt();
	}
}

Java: JavaStack artifacts Available in Maven Central

Ya se han liberado los primeros artefactos (librerías de proposito general) de JavaStack en Maven Central:

  • packer:1.1.1 > Libreria de Serializacion de datos (compresion, encriptacion,…). Similar a Kryo.
  • mapexpression:1.0.2 > Evaluador de Expresiones para usar en placeholders como ${name}.
  • stringproperties:1.0.1 > Properties con Features extra (${placeholders}).
  • kvstore:1.0.0 > Un NoSQL / Map Key-Value (disco y memoria).
  • standalone-preferences:1.0.4 > Implementacion del API de Preferences en Filesystem.
  • figaro:1.0.0 > Sistema de mensajes asincronos In-process / EventBus / ActorModel. Similar a Kilim, µJavaActors, Akka.

Todos estos artefactos siguen la misma filosofía: Zen, KiSS

Maven Central: org.javastack

Java: Generating CIDR InetAddress

Una pequeña chuleta para generar una “NetMask” desde un CIDR en Java:

import java.net.InetAddress;

public static InetAddress getAddressByCIDR(final int bits, final boolean ipv6) {
	final int totalBits = (ipv6 ? 128 : 32);
	if (bits < 0 || bits > totalBits)
		throw new IllegalArgumentException("Illegal CIDR prefix");
	final byte[] bytes = new byte[totalBits >> 3];
	for (int offset = 0; offset < bits; offset++) {
		bytes[offset >> 3] |= (1 << (7 - (offset & 7)));
	}
	try {
		return InetAddress.getByAddress(bytes);
	} catch (UnknownHostException e) {
		throw new RuntimeException(e);
	}
}

Referencias:
CIDR

Java: Could not generate DH keypair

Si te aparece este error, sigue leyendo…

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1762)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1723)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1706)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1237)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1214)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)

Leer más de esta entrada

Network: Latency benchmark

Las pruebas han sido muy basicas (pero dan una idea/orden de magnitud), las maquinas dst tienen un Servidor ECHO-TCP y las maquinas src tiene un Cliente ECHO-TCP. El cliente se conecta al servidor, envia un byte, lee el byte de vuelta, asi una y otra vez en un bucle de 10mil iteraciones, calcula la latencia minima, maxima y la media de las 10mil iteraciones.

Los resultados:

+--------+--------+------------+-------------+------------+----------+
| src    | dst    |    min     |     max     |    avg     | medium   |
+--------+--------+------------+-------------+------------+----------+
| linux1 | win7   | 2137.421µs | 24779.393µs | 3471.736µs | plc      |
| linux2 | win7   | 2035.887µs | 36111.414µs | 3040.004µs | plc      |
| linux3 | win7   | 1889.267µs | 10737.868µs | 2689.145µs | plc      |
| linux1 | win7   | 1031.974µs |  6943.338µs | 1371.043µs | wifi-11n |
| linux2 | win7   |  786.553µs |  4445.808µs | 1153.319µs | wifi-11n |
| linux3 | win7   |  621.457µs | 40078.223µs |  964.037µs | wifi-11n |
| linux1 | win7   |  380.495µs | 69546.800µs |  732.009µs | gbe      |
| linux1 | linux3 |  101.130µs | 10486.523µs |  314.863µs | vm       |
| linux2 | linux1 |  159.140µs |  9334.732µs |  308.808µs | vm       |
| linux2 | win7   |  165.534µs | 11921.050µs |  307.096µs | gbe      |
| linux3 | win7   |   79.133µs |  2289.499µs |  150.973µs | gbe      |
| linux2 | linux3 |   54.764µs |  5447.378µs |   86.460µs | vm       |
| linux1 | linux1 |   54.197µs |   299.199µs |   85.713µs | loopback |
| linux2 | linux2 |   41.505µs |   372.127µs |   72.765µs | loopback |
| linux3 | linux3 |   15.805µs |   500.069µs |   48.219µs | loopback |
| win7   | win7   |   17.675µs |    76.399µs |   22.927µs | loopback |
+--------+--------+------------+-------------+------------+----------+

Las maquinas son:

  • linux1: Ubuntu 14.04 32bits (virtual)
  • linux2: Ubuntu 14.04 64bits (virtual)
  • linux3: Ubuntu 12.04 64bits (fisica)
  • win7: Windows 7 Pro 64bits (fisica)

Los medios de transmision son:

  • plc: enlace PLC HomePlug-AV (aunque el PLC se conecta a la red por Ethernet a 100Mb)
  • wifi: enlace wifi 802.11n (aunque el AP-Wifi se conecta a la red por Ethernet a 100Mb)
  • vm: comunicacion entre dos maquinas dentro de un mismo hypervisor/host (linux3)
  • gbe: enlace Ethernet a 1Gb
  • loopback: comunicacion dentro de la misma maquina (127.0.0.1)

Sourcecode on GitHub:
EchoServer.java
EchoClient.java

Java: Agnostic Cache with Dynamic Proxies and Reflection

Hace tiempo usé un modulo de Perl muy interesante, Memoize. La idea era muy sencilla, tienes una funcion X, si para una entrada A, hay una salida B constantes y ese cálculo es lento, puede usar un caché.

La idea es esa, calcular una vez, usar muchas; sin tener que tener una implementación con cache de cada implementación original.

Aquí está la implementación en Java usando Reflexión:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class ReflectMemoizer implements InvocationHandler {
  private final Object object;
  private final HashMap<Method, ConcurrentHashMap<List<Object>, Object>> caches;

  /**
   * Memoize object
   * @param object source
   * @return proxied object
   */
  public static Object memoize(final Object object) 
        throws InstantiationException, IllegalAccessException {
    final Class<?> clazz = object.getClass();
    final ReflectMemoizer memoizer = new ReflectMemoizer(object);
    return Proxy.newProxyInstance(clazz.getClassLoader(), 
        clazz.getInterfaces(), memoizer);
  }

  private ReflectMemoizer(final Object object) {
    this.object = object;
    this.caches = new HashMap<Method, ConcurrentHashMap<List<Object>, Object>>();
  }

  public Object invoke(final Object proxy, final Method method, 
        final Object[] args) throws Throwable {
    if (method.getReturnType().equals(Void.TYPE)) {
      // Don't cache void methods
      return invoke(method, args);
    } else {
      final Map<List<Object>, Object> cache = getCache(method);
      final List<Object> key = Arrays.asList(args);
      Object value = cache.get(key);
      if ((value == null) && !cache.containsKey(key)) {
        value = invoke(method, args);
        cache.put(key, value);
      }
      return value;
    }
  }

  private synchronized Map<List<Object>, Object> getCache(final Method m) {
    ConcurrentHashMap<List<Object>, Object> cache = caches.get(m);
    if (cache == null) {
      cache = new ConcurrentHashMap<List<Object>, Object>();
      caches.put(m, cache);
    }
    return cache;
  }

  private Object invoke(final Method method, final Object[] args) 
        throws Throwable {
    try {
      return method.invoke(object, args);
    } catch (InvocationTargetException e) {
      throw e.getTargetException();
    }
  }
}

Leer más de esta entrada

Java: ServiceLoader decouple API and Implementation

Un sencillo ejemplo del uso de ServiceLoader, muy útil para para crear aplicaciones extensibles a la vez que separamos las interfaces de sus implementaciones en diferentes empaquetados (jar).

La factoría que usa el ServiceLoader y la interface común (ambos ficheros en storage-api.jar):

package com.acme;

import java.util.ServiceLoader;

public class StorageFactory {
  public static Storage getInstance() {
    for (Storage storage : ServiceLoader.load(Storage.class)) {
      return storage;
    }
    throw new UnsupportedOperationException("No implementation found");
  }
}

La interface que deben implementar todos los servicios:

package com.acme;

public interface Storage {
  void put(String key, String value);

  String get(String key);
}

Un ejemplo de implementación en memoria (ambos ficheros en storage-memory.jar):

package com.acme;

import java.util.concurrent.ConcurrentHashMap;

public class MemoryStorage implements Storage {
  private final ConcurrentHashMap<String, String> map;

  public MemoryStorage() {
    map = new ConcurrentHashMap<String, String>();
  }

  @Override
  public void put(final String key, final String value) {
    map.put(key, value);
  }

  @Override
  public String get(final String key) {
    return map.get(key);
  }
}

El fichero META-INF/services/com.acme.Storage

com.acme.MemoryStorage

Otra implementación estilo /dev/null (ambos ficheros en storage-null.jar):

package com.acme;

public class NullStorage implements Storage {
  @Override
  public void put(final String key, final String value) {
  }

  @Override
  public String get(final String key) {
    return null;
  }
}

El fichero META-INF/services/com.acme.Storage

com.acme.NullStorage

Y para acabar, el código de prueba:

package com.acme;

public class TestStorage {
  public static void main(final String[] args) throws Throwable {
    final Storage storage = StorageFactory.getInstance();
    storage.put("data", "hello world");
    System.out.println(storage.get("data"));
  }
}

Referencias:
java.util.ServiceLoader

Java: Get Current Method Name from a Class

Una cosa que suele mejorar mucho las trazas o el profiling es saber “donde estás”, no solo en que clase, si no en que método. Por desgracia actualmente en Java no existe un simple Thread.currentThread().getCurrentMethod() o similar.

La información se puede sacar del StackTrace (también hay un método oscuro sun.reflect.Reflection.getCallerClass(int), pero en Java 8 ha desaparecido y como dicen los de Oracle: sun.* is private api, is not supported).

Lo malo del StackTrace es que es relativamente pesado, tanto si usas Thread.currentThread().getStackTrace() o new Throwable().getStackTrace()

Se puede acelerar la ejecución usando los metodos internos de Throwable mediante reflexión (no suelo ser muy partidario, pero hablamos de 10 veces más rápido). Para asegurar que si los métodos privados cambian el código siga funcionando, aquí un método mixto:
Leer más de esta entrada

A %d blogueros les gusta esto: