Can Not Instantiate Proxy Of Class

When you see an error message like can not instantiate proxy of class or cannot instantiate proxy for class, it can be confusing and disruptive, especially when you are trying to run a Spring, Hibernate, or other proxy-based framework. This problem commonly appears when the framework attempts to create a dynamic proxy for a class and fails because of restrictions on the target type or missing requirements such as a no-argument constructor. Understanding why proxies are created, how different proxy mechanisms work, and what typical pitfalls cause instantiation failures will help you diagnose and fix the issue quickly.

What a proxy is and why frameworks use them

A proxy is a runtime-generated object that stands in for another object and can intercept method calls to add behavior such as transaction management, lazy loading, security checks, or remote procedure calls. Frameworks like Spring, Hibernate, and various RPC libraries use proxies extensively so they can inject cross-cutting concerns without changing your business classes.

There are two main proxying approaches you will encounter

  • JDK dynamic proxies create proxy instances that implement one or more interfaces. They require an interface and can only proxy interface methods.
  • CGLIB (or other bytecode generation libraries) create subclass-based proxies by generating a subclass of the target class at runtime. These can proxy concrete classes but have more restrictions.

Common causes of cannot instantiate proxy of class

Multiple root causes can trigger this message. Most fall into one of several categories class design, constructor issues, language-level restrictions, or framework configuration.

Final classes and final methods

CGLIB works by creating a subclass at runtime. If a class is declared final, it cannot be subclassed, so CGLIB cannot build a proxy. Similarly, final methods cannot be overridden and thus cannot be intercepted by subclassing proxies. If your target class is final or contains final methods that you expect to be intercepted, switch to interface-based proxies or remove the final modifier.

No default (no-argument) constructor

Subclass-based proxying often requires calling a constructor on the proxy class. If the target class lacks a no-argument constructor and all constructors require parameters, proxy creation can fail. Providing a public or protected no-arg constructor or configuring the framework to use interface proxies usually resolves this issue.

Non-static inner classes

Inner classes that are not static implicitly hold a reference to the outer instance and require a synthetic constructor parameter. This makes them harder (or impossible) for proxy libraries to instantiate without knowledge of the outer instance. Declaring inner classes as static or moving the class to a top-level class solves the problem.

Private or package-private classes

Proxy libraries need to generate a subclass or access methods from a different package. If the class or its methods are private or package-private and generated proxies live in a different package, access is restricted. Make the class and intercepted methods public, or use interface-based proxies that do not require subclassing.

Classloader and module system restrictions

In complex applications, especially with custom classloaders or Java module system constraints (JPMS), runtime generation of proxy classes can fail because the proxy generator cannot define new classes in the required package or cannot access the target class. Verify classloader visibility and module exports or open packages as needed.

Using the wrong proxy type

If the framework defaults to CGLIB but your bean is defined by interface, or vice versa, you can run into problems. For example, if a class has no interfaces and your configuration forces JDK dynamic proxies, instantiation will fail. Make sure your configuration aligns with your class design enable CGLIB for concrete classes or design interfaces for JDK proxying.

How to troubleshoot the error step by step

Debugging proxy instantiation problems is easier when you follow a systematic approach.

1. Read the full stack trace

The stack trace often points to the exact cause (for example, java.lang.IllegalArgumentException Cannot subclass final class). Look for nested exceptions and messages from CGLIB, Spring, or your ORM-these give context.

2. Identify the target class

Find which class the framework tried to proxy. Inspect its modifiers (final, public), constructors, and whether it is a non-static inner class.

3. Check proxy mode and configuration

If using Spring, check whether proxy-target-class is set (which forces CGLIB) or whether it is using interface-based proxies. Confirm any customizations in your framework that change proxying behavior.

4. Try a simple change

Make the class public, add a no-arg constructor, or make the inner class static and rerun. If the change fixes the issue, you’ve found the cause. Remember to choose a long-term design solution, not just a quick patch.

5. Consider using interfaces

Refactoring to program to an interface often resolves many proxy problems because JDK dynamic proxies are simpler and less restrictive. If that’s not possible, configure or accept CGLIB and ensure your classes are proxyable.

Practical fixes and patterns

Here are practical solutions mapped to common causes

  • Final class or methodRemove final or expose an interface. Use JDK proxy if an interface is available.
  • No no-arg constructorAdd a protected or public no-arg constructor or configure the framework to use constructor injection patterns it supports.
  • Non-static inner classMake it static or move it to a top-level class.
  • Access restrictionsMake class and methods public, or adjust module descriptors to open packages.
  • Classloader issuesEnsure proxy generator and target class share the same classloader or allow the code generation classloader to define classes in the right package.

Example Spring and CGLIB vs JDK proxies

In Spring, AOP proxies are created automatically based on your configuration and the type of bean. By default, if a bean implements at least one interface, Spring uses JDK dynamic proxies. If not, it uses CGLIB (if available). You can force CGLIB by setting proxy-target-class to true, but that requires the class to be non-final and proxyable.

If you get a proxy instantiation error in Spring, confirm whether your bean implements an interface, whether proxy-target-class is true, and whether the class is final or non-static. Changing design to an interface or altering proxy settings typically resolves the issue.

When to seek alternative approaches

Sometimes changing the class design is impractical. In such cases, alternatives include

  • Using composition instead of proxy-based interception-wrap the class in another class that you control.
  • Applying AOP at the interface or service layer rather than on concrete classes deep in the stack.
  • Configuring explicit factory beans or manual injection where dynamic proxies aren’t needed.

Can not instantiate proxy of class is a symptom rather than a single problem. It shows that the runtime cannot generate a suitable proxy for the target class. The most common causes are final classes, missing no-argument constructors, non-static inner classes, visibility restrictions, and misaligned proxy configurations. By understanding how JDK and CGLIB proxies work, carefully reading stack traces, and applying targeted fixes-such as making classes proxyable, switching to interfaces, or adjusting framework settings-you can resolve the issue and keep your application’s runtime enhancement features working reliably.