mercredi 23 novembre 2016

Finding and removing memory leak issue (Java Reflection)


I'm working on a maintenance project and a issue is raised for memory leak.

Basically the code is to load the values of data in application context from database. If the values in DB is changed then this functionality is used to update the value in application context also without restarting the server.

The variables annotated with @Value annotation are updated every where in the project, eg:

@Value("${cost}")
private String cost;

The method where memory leak is reported by production is updateObjects():

public class DbPropertySourcesPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

   private CustomBeanPostProcessor customBeanPostProcessor;
   private static Properties dbProps = new Properties();

 private void updateObjects() {
  for (String key : customBeanPostProcessor.getObjectMap().keySet()) {
     if (null != dbProps.get(key)) {
        List<Object> objectList = customBeanPostProcessor.getObjectMap().get(key);
        if (objectList != null && objectList.size() > 0) {
           for (Object object : objectList) {
              if (null != object) {
                 for (Field field : object.getClass().getDeclaredFields()) {
                    Value value = field.getAnnotation(Value.class);
                    if (null != value && null != value.value()
                          && value.value().replace("${", "").replace("}", "").length() > 0
                          && value.value().replace("${", "").replace("}", "").equalsIgnoreCase(key)
                          && field.getType() == String.class) {
                       field.setAccessible(true);
                       try {
                          field.set(object, dbProps.get(key));
                       }
                       catch (IllegalAccessException ee) {
                          logger.error("Unable to update Object",ee);
                       }
                    }
                 }
              }
           }
        }
     }
  }
 }

Is it because of reflection used & can reflectionUtils of spring solve the problem?

CustomBeanPostProcessor.java

public class CustomBeanPostProcessor implements BeanPostProcessor {

public static Map<String, ArrayList<Object>> objectMap;

public Object postProcessBeforeInitialization(Object o, String string) throws BeansException {
    return(o);
}
  public Object postProcessAfterInitialization(Object o, String string) throws BeansException {
    if(objectMap == null) {
           objectMap = new HashMap<String, ArrayList<Object>>();
    }
     if(null == o) {
         return(o);
     }
     if(AopUtils.isAopProxy(o) && o instanceof Advised) {
                  Class targetClass = ((Advised)o).getTargetClass();
                    Object object =  null;
                  try {
                        Object target = ((Advised)o).getTargetSource().getTarget();
                        object = targetClass.cast(target);
                for(Field field:object.getClass().getDeclaredFields()) {
                    Value value = field.getAnnotation(Value.class);
                    if(null != value && null != value.value() && value.value().replace("${", "").replace("}", "").length() > 0) {
                        updateObjectMap(value.value().replace("${", "").replace("}", ""), object);
                    }
                }
                  }
                  catch(Exception ex) {
                        ex.printStackTrace();
                  }
     }
     else {
         for(Field field:o.getClass().getDeclaredFields()) {
             Value value = field.getAnnotation(Value.class);
             if(null != value && null != value.value() && value.value().replace("${", "").replace("}", "").length() > 0) {
                 updateObjectMap(value.value().replace("${", "").replace("}", ""), o);
             }
         }
     }
     return(o);
 }




public static void updateObjectMap(String key, Object object) {
    ArrayList<Object> objectList = objectMap.get(key);
    if(null == objectList) {
        objectList = new ArrayList<Object>();
        objectList.add(object);
        objectMap.put(key, objectList);
    }
    else {
        objectList.add(object);
    }
}

public Map<String, ArrayList<Object>> getObjectMap() {
    return objectMap;
}

public void setObjectMap(Map<String, ArrayList<Object>> objectMap) {
    this.objectMap = objectMap;
}
}

Please let me know if more information is required.
Thank You.





Aucun commentaire:

Enregistrer un commentaire