views:

455

answers:

4

I have the understanding that perm size is used to store meta data, that would include byte code, static stuff etc.

My question how does usage of reflection affect the perm size, if it ever does. I mean if Program-A uses normal way of running objects and Program-B uses reflection all over, how will the perm-sizes of the two programs compare?

+3  A: 

I'm not entirely sure I understand the question but Java classes already include everything need to perform reflection on them. A .class file doesn't change based on how it's used.

Edit 1: Providing some more specific examples to better distinguish the type of "reflection" we are talking about.

Example:

class Foo {
    public void bar() {
        System.out.println( "Hello, world." );
    }
}

// Conventional calling
Foo f = new Foo();
foo.bar();

// Reflection based callling
Class fooClass = Class.forName( "Foo" );
Method m = fooClass.getMethod( "bar", null );
Object f = fooClass.newInstance();
m.invoke( m, null );

In the conventional calling case, Foo.class and any of its direct class dependencies will be loaded. bar will be executed. The strings "Foo" and "bar" will already have been interned as part of the calling class because the byte code uses strings to resolve the classes and methods at runtime. (actually "bar" will be the full method signature so actually longer than just "bar")

In the reflection case, exactly the same thing happens. The only additional class loaded is Method.class. That should be the only affect to perm size.

The latter case has performance implications. The method look-up is relatively expensive so it's advisable to cache Method objects when you can. The extra method call to invoke has a slight performance implication as it's an extra method call. Hotspot will have trouble optimizing through this call... at least more than normal. JITing happens exactly the same.

Edit 2: Noting some additional objects that are loaded during reflection...

java.lang.Class will create and cache Method objects (or Field objects, etc.) upon access. These are cached in a SoftReference and so will be reclaimed if memory usage requires it.

However, the initialization of these objects means that there may be additional intern'ed strings loaded by the VM to support creation of these Method objects. My guess is that these strings were likely already part of the reflective class's constant pool but it's possible that they aren't. Either way, it's a single time hit per method per class, per field per class, etc.. Access the methods, you'll get at least all of the names for those methods intern'ed. Access the fields, you'll get the names of those fields intern'ed.

PSpeed
Classes may be generated dynamically by the reflection implementation for fast access.
Tom Hawtin - tackline
Reference please? I use reflection all the time (really... all the time) and have never seen a single class generated as a result. Third party libraries might do some stuff and the dynamic proxy stuff will definitely generate a runtime class. But simply calling methods on a Class/Object shouldn't.
PSpeed
@PSpeed..pls check the following link https://jaxb.dev.java.net/issues/show_bug.cgi?id=581
Suraj Chandran
@Tom...Can u give an example...that's what is I am exactly looking for!
Suraj Chandran
+4  A: 

The perm space will grow when you execute code that will load new classes or internalize strings. The reflection classes have to be loaded that's for sure. I'm not sure if the reflection API does use internalized strings heavily but it should not be to hard to find out.

For example for the method getDeclaredMethod(String name, Class<?>... parameterTypes) the name parameter will be internalized.

This snippet will nicely fills up the perm space:

Random random = new Random();
while(true){
    try {
     X.class.getDeclaredMethod(toBinaryString(random.nextLong()));
    } catch (Exception e) {
    }
}

alt text

In a real world application it will make no difference.

Thomas Jung
What I believe you are seeing there is interning the searched for name so that `==` can be used on the already interned method names. (Not convinced that is a great idea.) In face, reflection can create classes (sometimes).
Tom Hawtin - tackline
(Those interned strings are GCable with a full on garbage collect cycle, assume a good quality of implementation.)
Tom Hawtin - tackline
@Tom, can you provide a single example where a class is created because of reflection? I'm not trying to be a pain, I'd really like to know of these cases as I've never seen one.
PSpeed
@[email protected] am not sure but we were discussing on this point and somebody said that JaxB seems to create new classes each time if u create a new JAXBContext each time. There's a bug raised for it here : https://jaxb.dev.java.net/issues/show_bug.cgi?id=581
Suraj Chandran
@PSpeed..Why do u think the given snippet will fill the perm space. Also is the picture attached the profile for the given snippet!
Suraj Chandran
@PSpeed...What do u mean by internalize string? How can anyone dynamically internalize a string?
Suraj Chandran
"interned string"... Java keeps a cache of string objects. When a class is loaded, the strings that are part of the class definition (references to other class names, string constants used by the class, etc.) are added to the intern cache. String.intern() is how you can access this directly. The javadocs for that method explain further.
PSpeed
The snippet above fills perm space because Class.getDeclaredMethod() will intern() the passed string during the method search. This is fine for normal use and allows them to use == internally... but in degenerate cases like above where one is calling lots and lots of bad method names it fills the intern cache with lots of garbage.
PSpeed
The Jaxb issue seems significant in its own right but is unrelated to reflection. I've never used Jaxb much so I can't comment on why they do this specifically but there are many strategies for caching access like this. The link you reference indicates that the original poster was using Jaxb incorrectly by basically reinitializing the whole environment over and over.
PSpeed
@PSpeed..." Class.getDeclaredMethod() will intern() the passed string during the method search"...Are you sure of this? Can you provide me with a reference, from where to compare!
Suraj Chandran
@PSpeed...Actually inside JAXB uses a lot of reflection, hence my comments!
Suraj Chandran
In Class.java searchMethods(), the second line is String internedName = name.intern();
PSpeed
It's not JAXB's use of reflection that is at issue... it's their cache. For performance reasons, most frameworks that use reflection will do some amount of caching. In the linked case, the poster was reinitializing the JAXB cache over and over. Note: even Class.java does a little caching.
PSpeed
Note: Class.java's caching is softly referenced so eventually gets GC'ed after disuse.
PSpeed
+2  A: 

The first answer is basically right -- whether a class is loaded 'normally' or via reflection makes no difference. Either way it's loaded. I can't think of any difference in interned Strings that I know of.

I suppose there is a more indirect effect: using reflection, you might cause fewer classes to be loaded. Let's say you have some code that loads one of 100 classes based on some parameter. Writing it without reflection, you'd import all 100 classes and instantiate one of them.

With reflection, only 1 class would be loaded. Without, at the time the class with this code loads, all 100 imported classes would load since all are referenced. So, more classes get loaded into the perm space.

But this is a somewhat contrived example. Unless it really described your situation, I imagine you will notice virtually no difference. That is, until you're sure it's not trivial, don't let this influence your design decisions.

Sean Owen
+2  A: 

Reflection can generate classes, depending upon implementation. You may, for instance, need to use a reflection artifact thousands of times before it is compiled to bytecode.

As ever, the advice is: Profile your code in realistic situations.

Tom Hawtin - tackline
Do you mean "native code" above? The classes are already byte code. Hotspot will have trouble optimizing through calls of reflection but the JIT behaves the same.
PSpeed
No, I mean bytecode. Obviously after use HotSpot will compile the bytecode to native. Fields can be read by finding the offset from the start of the object and adding. They can also be read by writing byte code that reads those fields (that ignores access privileges). Something like that goes on (in the Sun JRE), but I forget the details.
Tom Hawtin - tackline