Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clarify a situation with a cleaning Spring Prototype-beans from memory

I would like to understand whether I should clean prototype-beans from memory manually by myself.

In the Spring documentation you can see: "The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding."

So from this it seems that you should clean prototype-beans by yourself.

However.

I'm using VisualVM memory profiler. I have created a number of prototype-beans. You can see 51 instances of them.

enter image description here

Then you can see the situation when the garbage collector clean the memory - all prototype-beans were cleared.

enter image description here

So can anyone clarify the situation? Are prototype-beans cleared successfully by garbage collector or we should clear them manually (if yes, how)?


Addition. Some guys asked to show the code of creating the prototype-beans. Actually I don't see any sense in this because in the particular example I am creating them only as a test and this don't concern the actual situation with cleaning prototype-beans from memory. Developers can create prototype-beans by different ways but the future behaviour of them doesn't or shouldn't depend on a creation method.

In our real project where we have more than 400 components annotated as Prototype-beans I can see the same behavior. I have made a number of requests to our system, see a number of created prototype beans through VisualVM, then after garbage collector clean the memory all prototype beans become cleared.

I show the testing code just in the hope that those who asked about this will give some senseful information about the real behavior not just empty words about this particular test bean creation.

Test creating of the prototype-beans for the example:

for(int i=0;i<10;i++){
        Prototype1 prototype1=applicationContext.getBean(Prototype1.class);
        Prototype2 prototype2=applicationContext.getBean(Prototype2.class);

        prototype1.test1();
        prototype2.test2();
}

Test example of the prototype-bean:

@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Prototype1 {

    private int number;

    public Prototype1() {
        System.out.println("Prototype1 was created.");
    }

    public void test1(){

    }

}
like image 800
Kirill Ch Avatar asked Jun 14 '17 14:06

Kirill Ch


1 Answers

Once you create a prototype bean; you are responsible for its lifecycle.

Once you have no reference to that bean it is gone. The only real differences between a prototype bean and a scoped bean is how it is managed by the container.

In a unit test you would not rely on the container to give you these beans you would simply new them yourself.

So to really answer your question, if you allow the prototype object to be dereferenced by your application, the jvm's default behavior will eliminate these beans.

 public class Example {

    @Scope("prototype")
    public static class SomePrototypeBean{

    }

    @Singleton
    public static class MySingleton{

        @Bean
        private SomePrototypeBean somePrototypeBean;

    }

    public static void main(String[] args){
       // context creation code goes here

       // singleton is created, a prototype injected
       context.getBean(MySingleton.class);
       // NOTE: the prototype injected will last for as long as MySingleton has reference
       // my singleton will exist for as long as the context has reference

       doStuff(context);
       //prototype bean created in the method above will be GCed
    }

    public static void doStuff(Context context){
        context.getBean(MyPrototypeBean.class);
        //since we literally are doing nothing with this bean, it will be 
        // marked for garbage collection
    }

}  
like image 62
AnthonyJClink Avatar answered Sep 30 '22 07:09

AnthonyJClink