Archivos por Etiqueta: reflect

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: 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

Java: El coste de usar Reflexion (Reflect)

Cual es el coste de usar reflexion (reflect) en Java?

En cifras (tiempo de ejecucion en milisegundos, bajo=mejor) sobre 5millones de invocaciones de un metodo sencillo:

Loop iteration counter=5000000
Normal Static time=78ms
Normal Object time=78ms
Reflection Static time=796ms
Reflection Object time=796ms
Static XX=96349939634993
Object XX=96349939634993

Resumen: 796ms por reflexion (lento) vs 78ms de una invocacion normal (rapido).

El codigo fuente de las pruebas…
Leer más de esta entrada

A %d blogueros les gusta esto: