2013-12-02 3 views
0

В настоящее время я работаю над проектом Java, в котором я пытаюсь изучить все входы и выходы. В предыдущих проектах я использовал отражение Java, чтобы создать toString(), вызывая каждый геттер в объекте и анализируя его для отображения значения. Этот метод был полезным, чистым и динамичным способом отображения данных.Отражение гораздо медленнее, чем обычно

Ниже сильно упрощенная версия моего кода:

private static String objectToString(Object o) { 
    LOGGER.debug("entering ObjectStringUtils::objectToString()"); 


    .... 

    Class<?> oClass = o.getClass(); 
    String className = oClass.getName(); 
    Method[] methods = oClass.getMethods(); 

    for (Method m : methods) { 
     if ([method is a getter]) { 
       String methodName; 
       Object value; 
       try { 
        methodName= m.getName(); 
        LOGGER.debug("Invoking " + className + "::" + methodName); 
        Object value = m.invoke(o); 
        LOGGER.debug("Invoked " + className + "::" + methodName); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        value = null; 
       } 

       LOGGER.debug(methodName+ " -> " + value); 
     } 
    } 
} 

Это производит выход регистратора, который выглядит следующим образом:

14:47:49,478 [] DEBUG ObjectStringUtils:? - Invoking org.hibernate.impl.SessionImpl::isOpen 
14:47:49,613 [] DEBUG ObjectStringUtils:? - Invoked org.hibernate.impl.SessionImpl::isOpen 
14:47:49,613 [] DEBUG ObjectStringUtils:? - isOpen -> true 

Обратите внимание, что он принял Java 139 миллисекунд для вызова функции , Это займет много времени, чтобы выполнить отражение в любом методе в любом классе, даже если метод является только стандартным getter, который не выполняет никакой логики, кроме как вернуть значение. Это означает, что для выполнения операции требуется слишком много времени, если имеется несколько вложенных значений. Когда я использовал отражение ранее в WebSphere 7, для выполнения этой операции потребовалась небольшая часть этого времени.

Итак, мой вопрос: Почему он так долго обрабатывается? Я понимаю, что отражение происходит медленнее, но не должно быть величины 140 миллисекунд, чтобы вызвать геттер. Является ли это артефактом того, как WebLogic требует долгое время для вызова функции или того факта, что номера строк, как представляется, удалены из файлов .class? До сих пор я понятия не имею.

+0

Чтобы получить ясность, переименуйте 'variableName' в' methodName'. –

+0

Вы пробовали профилировать его? – chrylis

+0

@JoshM: сделано, спасибо. – patstuart

ответ

1

Когда вы проверяете фрагмент кода, вы должны выполнить ту же операцию несколько раз, в противном случае тест бессмыслен - это могло быть вызвано сбором мусора или другим процессом, запущенным на том же компьютере.

+0

Я запустил кусок кода несколько раз подряд, и это занимает несколько минут. Это привело к тому, что код не был недоступен при повторении нескольких сотен классов. – patstuart

0

Когда кешируются Method с. используемый в фреймворке, и oClass.getMethods() вызывается только один раз, рефлексивный вызов метода только ~ 2-3 медленнее, чем прямой вызов метода. Я думаю, что oClass.getMethods() должно быть самой медленной частью вашего отражения, а не вызовом метода.

Может быть, это SessionImpl::isOpen, который является медленным сам по себе? То есть он проверяет, все ли он подключен или какое-либо медленное взаимодействие с базой данных? 139 мс очень медленный даже для транзакции БД, так что это также может произойти из-за некоторых ошибок, возникающих во время этого вызова.

Смежные вопросы