Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metaspace out of memory when combining AOP and prototype #29967

Closed
ZhangChee opened this issue Feb 10, 2023 · 11 comments
Closed

Metaspace out of memory when combining AOP and prototype #29967

ZhangChee opened this issue Feb 10, 2023 · 11 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression)

Comments

@ZhangChee
Copy link

ZhangChee commented Feb 10, 2023

Spring Boot version: 2.3.12.RELEASE, 2.7.8

I've tried to apply AOP ( cglib ) on prototype Bean. Since cglib generates new class every time, metaspace hit OOM at the end.

Below is my code for AOP and prototype Bean:

@Aspect("pertarget(this(pack.path.to.Bean))")
public class BeanAspect {

    @Pointcut("execution(public void pack.path.to.BeanImpl.hi(..))")
    public void hi() {}

    @Around("hi()")
    public Object before(ProceedingJoinPoint pjp) throws Throwable {
        try {
            System.out.println("before hi");
            return pjp.proceed();
        } finally {
            System.out.println("after hi");
        }
    }
}


@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopConfiguration {
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public BeanAspect beanAspect() {
        return new BeanAspect();
    }
}

public interface Bean {
    void hi();
}

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class BeanImpl implements Bean {
    @Override
    public void hi() {
        System.out.println("hi~");
    }
}

@Component
public class BeanFactory {
    @Autowired
    private ApplicationContext context;

    public Bean create() {
        return context.getBean(BeanImpl.class);
    }
}

Below is my Runner

@Component
public class Runner {
    @Autowired
    private BeanFactory factory;
    private final ExecutorService executorService = Executors.newFixedThreadPool(1);

    @PostConstruct
    public void init() {
        executorService.execute(() -> {
            while (true) {
                Bean bean = factory.create();
                System.out.println(bean.hashCode() + " " + bean.getClass());
                bean.hi();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

I've referred to this PR, but it seems not work:

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 10, 2023
@bclozel bclozel transferred this issue from spring-projects/spring-boot Feb 14, 2023
@rstoyanchev rstoyanchev added the in: core Issues in core modules (aop, beans, core, context, expression) label Feb 14, 2023
@sbrannen sbrannen changed the title metasapce OOM when combining AOP and prototype Metaspace out of memory when combining AOP and prototype Feb 28, 2023
@vishalsingh2972
Copy link

vishalsingh2972 commented Apr 16, 2023

@ZhangChee @rstoyanchev @sbrannen could you assign this to me if it's still open?

@backslideZhang
Copy link

backslideZhang commented Apr 20, 2023

This case still exists.

I've tried to find out why this happened. Maybe this is the hint.
cglib will create new class instance every time when a prototype bean instance is created.
So as the system running, more prototype bean instance created, and more class instance created without recycling.
Finally metaspace hit OOM.
When it comes to singleton bean, no more bean instance is created, so no more cglib class instance created too. That's why this case hits Metasapce OOM but singleton won't happen.

The solution maybe: Every prototype instance shares the same cglib class instance ( Maybe we need relation cache between cglib class instance and corresponding Bean Class with @component and @scope=SCOPE_PROTOTYPE ? )

I've no authrization to reassign. Let's waiting... T T

@vishalsingh2972
Copy link

vishalsingh2972 commented Apr 20, 2023

This case still exists.

I've tried to find out why this happened. Maybe this is the hint. cglib will create new class instance every time when a prototype bean instance is created. So as the system running, more prototype bean instance created, and more class instance created without recycling. Finally metaspace hit OOM. When it comes to singleton bean, no more bean instance is created, so no more cglib class instance created too. That's why this case hits Metasapce OOM but singleton won't happen.

The solution maybe: Every prototype instance shares the same cglib class instance ( Maybe we need relation cache between cglib class instance and corresponding Bean Class with @component and @scope=SCOPE_PROTOTYPE ? )

I've no authrization to reassign. Let's waiting... T T

@ZhangChee @backslideZhang
I see it is tagged as waiting-for-triage, so maybe no use of us contributing some internal error and maybe core spring team will handle this.

@ArvindAbi
Copy link

I m facing this issue as well, Any workaround for this till it get fixed ?

@vishalsingh2972 , Can you point me to a workaround if you found one?

@ArvindAbi
Copy link

From my observation, the Proxies are not GCed even though the underlying Target Source is GCed, Attaching an example where one of the Proxy Generated is GCed but there are two other proxies still in Heap causing memory leak.

I don't find a way to manually destroy these proxy objects as well. Any help would be helpful.

Screenshot 2023-07-05 at 4 33 42 AM

@ArvindAbi
Copy link

@ZhangChee , have you found any workaround/
fix for it temporarily?

@ZhangChee
Copy link
Author

@ArvindAbi
I give up using aop on prototype bean.
Instead, I inject another service with aop to the prototype bean

@snicoll
Copy link
Member

snicoll commented Dec 1, 2023

Everyone, the creation of a new bean using the prototype scope should not lead to the creation of a new CGLIB class. If that happens, something unexpected happened that we need to debug. In order to do that, please share a small sample that we can run ourselves with instructions to trigger the problem. You can attach a zip to this issue or push the code to a separate GitHub repository. Thank you!

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Dec 1, 2023
@spring-projects-issues
Copy link
Collaborator

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Dec 8, 2023
@spring-projects-issues
Copy link
Collaborator

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

@spring-projects-issues spring-projects-issues closed this as not planned Won't fix, can't repro, duplicate, stale Dec 15, 2023
@spring-projects-issues spring-projects-issues removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on labels Dec 15, 2023
@dcaillia

This comment was marked as duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression)
Projects
None yet
Development

No branches or pull requests

8 participants