2011-08-19 11 views
11

Este es un ejercicio académico (exención de responsabilidad).Rendimiento en tiempo de ejecución de reflexión de Java

Estoy construyendo una aplicación que se beneficiará de ser lo más rápido posible ya que competirá con otros.

Sé que declarar una clase utilizando la reflexión (ejemplo a continuación) sufrirá una gran penalización en comparación con una declaración estándar.

Class mDefinition = Class.forName("MySpecialClassString"); 
Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class}); 
myClass = (MySpecialClass) mConstructor.newInstance(this); 

Sin embargo, después de declarar myClass si lo uso en una forma estándar myClass.myMethod()yo también sufrir de cerdos rendimiento o será el mismo que si hubiera declarado la clase de una manera estándar?

Respuesta

14

Habrá una penalización de rendimiento al crear una instancia por primera vez del objeto. Una vez que se carga la clase, es lo mismo que si se hubiera instanciado normalmente, y no habrá más penalización de rendimiento.

Yendo más lejos, si llama métodos utilizando reflexión, habrá una penalización de rendimiento de unas quince veces (por defecto en Java), después de lo cual la JVM reescribirá la llamada reflejada para que sea exactamente la misma que una compilación estática llamada. Por lo tanto, incluso las llamadas a métodos reflejados repetidamente no causarán una disminución en el rendimiento, una vez que el código de bytes haya sido recompilado por la JVM.

ver a estos dos enlace para obtener más información sobre lo siguiente:

+0

gracias por la bonita descripción detallada y la documentación adicional. Realmente demostrado ser útil en estos últimos días. – Frankie

7

Una vez que la clase se haya cargado, debería estar bien. La sobrecarga está asociada con la inspección de las estructuras de tiempo de ejecución que representan la clase, etc. Los métodos de llamada en una forma estándar deberían estar bien, sin embargo, si comienza a buscar métodos por nombre o firma, incurrirá en gastos adicionales.

+1

+1 estuvieron de acuerdo - no debería haber ningún gran gasto para una búsqueda dinámica de un solo disparo. –

+0

@Chris He estado haciendo algunas pruebas y estás en lo cierto con tus suposiciones. Gracias por pre-aclarar esto. – Frankie

2

La respuesta de Chris Thompson es acertada. Sin embargo, estoy confundido por su ejemplo de código.

Esto cargará dinámicamente la clase:

Class mDefinition = Class.forName("MySpecialClassString"); 

esta forma se consigue un Contructor para su clase, lo que lleva a una instancia de esa misma clase como un argumento. También tenga en cuenta que está accediendo a la clase en tiempo de compilación con MySpecialClass.class:

Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class}); 

Esto se instancias de un MySpecialClass pasando this al constructor:

myClass = (MySpecialClass) mConstructor.newInstance(this); 

Con base en el argumento del constructor, ¿significa estamos en un método de instancia de MySpecialClass? Muy confundido.

EDIT: Esto está más cerca de lo que yo hubiera esperado ver:

Class<?> mDefinition = Class.forName("MySpecialClassString"); 

//constructor apparently takes this as argument 
Class<?> constructorArgType = this.getClass(); //could be ThisClassName.class 

Constructor<?> mConstructor = mDefinition.getConstructor(constructorArgType); 

MySpecialInterface mySpecialInstance = (MySpecialInterface)mConstructor.newInstance(this); 

donde MySpecialInterface es una interfaz que se utiliza para interactuar con sus clases de carga dinámica:

interface MySpecialInterface { 
    //methods used to interface with dynamically loaded classes 
} 

De todos modos por favor avísame si estoy mal entendido o fuera de base aquí.

+0

probablemente tenga razón ya que estoy empezando a usar la reflexión ahora. Permítame informarle muy rápido sobre cómo funciona el sistema. Tenemos tres clases ClassA_interaction, ClassB_object y ClassC_logic ... ClassA_interaction lanza varios objetos ClassB_ y los alimenta con posiciones. Cada objeto ClassB lanza un ClassC_logic usando reflexión. ClassC_logic se alimenta con 'this' (ClassB_object) ya que tienen que llamar funciones que existen en ClassB_object. Puede ser complicado pero funciona. ¿Sugerirías que tome otro enfoque? Gracias por tomarte el tiempo de mirar mi código. – Frankie

+0

Debo decir que no he trabajado personalmente con la carga de clases dinámica, por lo que quería la confirmación de alguien. Pero, entiendo que si hace referencia directamente a una clase en su código o incluso tiene acceso a ella en tiempo de compilación, no tiene sentido cargarla dinámicamente. Sin embargo, tendría sentido si tienes un 'Foo' cargado estáticamente que es una clase o interfaz abstracta, y tus clases cargadas dinámicamente extienden/implementan' Foo'. De esta forma, después de cargar dinámicamente una clase y crear una instancia de la misma, puede convertirla en 'Foo' e interactuar con ella sin más reflexión. –

+0

Por supuesto, 'Foo' necesita saber todo lo que va a querer hacer con estas clases cargadas dinámicamente, en forma de declaraciones de método abstracto/interfaz. –

Cuestiones relacionadas