Git Product home page Git Product logo

cglib's Introduction

cglib Build Status

IMPORTANT NOTE: cglib is unmaintained and does not work well (or possibly at all?) in newer JDKs, particularly JDK17+. If you need to support newer JDKs, we will accept well-tested well-thought-out patches... but you'll probably have better luck migrating to something like ByteBuddy.

Byte Code Generation Library is high level API to generate and transform JAVA byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access. https://github.com/cglib/cglib/wiki

How To: https://github.com/cglib/cglib/wiki/How-To

Latest Release: https://github.com/cglib/cglib/releases/latest

All Releases: https://github.com/cglib/cglib/releases

cglib-#.#_#.jar binary distribution, CGLIB classes only, it must be used to extend cglib classes dependant on ASM API

cglib-nodep-#.#_#.jar binary distribution, CGLIB and renamed ASM classes, not extendable

cglib's People

Contributors

cushon avatar ebourg avatar elkfrawy-df avatar elrodro83 avatar encounter avatar guw avatar ham1 avatar ijuma avatar izeye avatar jbodkin avatar jhaber avatar lukesandberg avatar mcculls avatar pascalschumacher avatar raphw avatar ronshapiro avatar sameb avatar skuzzle avatar vlsi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cglib's Issues

Reintroduce a mailing list

Hello everybody,

I was wondering if cglib is actively developed again? I tried to get in touch with somebody that is related to cglib about a year ago because I wrote some patches for the library. I am not sure if I still have them floating around because I did not find anybody who could apply them back then. Instead, I found the project dead (mailing list, no commits, etc.). Is there a new attempt to create a new mailing list? The last one was a collection of spam mail and I see it does not exist anymore even though it is still listed.

Is there a mailing list or any place to discuss the development of cglib? Since I found the project dead, I wrote another library which was originally an attempt to refactor cglib in order to support annotations. I learned a lot from
cglib but I believe the rewritten implementation has quite an edge on cglib's current state. However, the library is obviously not API-compatible to cglib.

Maybe we can merge some ideas of my library over to cglib, if you are interested in this? Or collaborate in any other context? I would love to code together with some people instead of merely coding for myself. If there was a mailing list, I would love to discuss these things with you guys.

Caching of FastClass does not work

This issue was found by inspecting a memory leak in Google Guice:
google/guice#1042

These are my findings after digging into the problem:

Proposed fix:

  • Implement hashCode() and equals() for FastClass.Generator

3.2 release request

@sameb Can we get a 3.2 release?

I recently became aware that 3.1, which uses ASM 4x has a problem generating classes via Enhancer when using the -parameters option in JDK 8 built projects. The latest in master, which uses ASM 5x, seems to work fine - we just need a new release!

Regarding impact, right now this effects basically any library using 3.1, including Guice, Spring, ModelMapper (my library), etc.

Proper documentation

Cglib is missing a proper documentation. Are there any attempts to write an extensive documentation that lists all features? I once wrote a blog article about cglib and it gets quite a lot of clicks, so I guess that there is a need for such a documentation.

I am more than happy to help with this, but I am pretty sure that my blog post is not exhaustive. (Again, this would be more suited for a mailing list - see this related issue - if there was any.)

JDK9 Internal API references in cglib

Running on cglib 3.2.4 with Jigsaw b162 with --permit-illegal-access.

I'm seeing the following warning.
WARNING: Illegal access by net.sf.cglib.core.ReflectUtils$1 (file:gradle_cache/caches/modules-2/files-2.1/cglib/cglib-nodep/3.2.4/42c972dee25a436b32c6027e848287ff47ed6750/cglib-nodep-3.2.4.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)

Breaking into this class is no longer allowed in JDK9.

can't deploy release because some maven output is missing

@JBodkin (or anyone else), can you help with some maven issues? I tried deploying a new release this past week, but I can't promote from staging because when I try to close the staging output, it fails verification saying that some files are missing. See https://issues.sonatype.org/browse/OSSRH-18447, or below:

Event: Failed: Javadoc Validation
Friday, October 23, 2015 15:34:26 EDT (GMT-0400)
typeId  javadoc-staging
failureMessage  Missing: no javadoc jar found in folder '/cglib/cglib-nodep/3.2.0'
Event: Failed: Signature Validation
Friday, October 23, 2015 15:34:36 EDT (GMT-0400)
typeId  signature-staging
failureMessage  Invalid Signature: '/cglib/cglib-sample/3.2.0/cglib-sample-3.2.0-site.jar.asc' is not a valid signature for 'cglib-sample-3.2.0-site.jar'.
failureMessage  Missing Signature: '/cglib/cglib-sample/3.2.0/cglib-sample-3.2.0.jar.asc' does not exist for 'cglib-sample-3.2.0.jar'.
failureMessage  Invalid Signature: '/cglib/cglib-sample/3.2.0/cglib-sample-3.2.0-javadoc.jar.asc' is not a valid signature for 'cglib-sample-3.2.0-javadoc.jar'.
failureMessage  Invalid Signature: '/cglib/cglib-sample/3.2.0/cglib-sample-3.2.0-sources.jar.asc' is not a valid signature for 'cglib-sample-3.2.0-sources.jar'.
failureMessage  Invalid Signature: '/cglib/cglib/3.2.0/cglib-3.2.0-javadoc.jar.asc' is not a valid signature for 'cglib-3.2.0-javadoc.jar'.
failureMessage  Missing Signature: '/cglib/cglib/3.2.0/cglib-3.2.0.jar.asc' does not exist for 'cglib-3.2.0.jar'.
failureMessage  Missing Signature: '/cglib/cglib-nodep/3.2.0/cglib-nodep-3.2.0.jar.asc' does not exist for 'cglib-nodep-3.2.0.jar'.
failureMessage  Missing Signature: '/cglib/cglib-integration-test/3.2.0/cglib-integration-test-3.2.0.jar.asc' does not exist for 'cglib-integration-test-3.2.0.jar'.

... I suspect the POM needs updating to produce those files?

Update to ASM 5.x

It would be great if Cglib could update its ASM dependency to 5.x (5.0.3 is the most recent right now).

Poor multithreading performance, even with cache turned off

I have a scenario where a lot of threads are generating classes concurrently. I control my own way of reusing these classes as needed. "useCache" option is set to false. Each thread is using it's own instance of Enhancer. Multithreaded performance is very poor because of the global synchronized (source) block in AbstractClassGenerator.create(key). There is no way to give each instance of Enhancer it's own Source due to the constructor setup. Even when "useCache" is false it still attempts to manipulate the cache structures in the synchronized block.

NPE thrown in Service Bean enhanced by Cglib

I asked the Problem in Stackoverflow with no response, maybe because of my poor english. But the problem lingering over my head these days.
A Service Bean:

 public class ZhilianPartnerOuterServiceProxy{
    private IZhilianPartnerHourRoomStatusService zhilianPartnerHourRoomStatusService;

    ZhilianRoomStatusSyncResult testGetRemoteHourRoomStatus() {
        getLogger().info("??? package " + zhilianPartnerHourRoomStatusService);
        return new ZhilianRoomStatusSyncResult();
    }

    public ZhilianRoomStatusSyncResult testGetRemoteHourRoomStatus1() {
        getLogger().info("??? public " + zhilianPartnerHourRoomStatusService);
        return new ZhilianRoomStatusSyncResult();
    }

    public Logger getLogger(){
        return zhilianPartnerCommonService.getLogger();
    }
 }

Watch that testGetRemoteHourRoomXXX(), testGetRemoteHourRoomStatus1 has public declared. And them are both been called in same method listRoomStatusFromRemote in Another Bean

 public ZhilianRoomStatusSyncResult listRoomStatusFromRemote(){
        zhilianPartnerOuterServiceProxy.testGetRemoteHourRoomStatus1();
        zhilianPartnerOuterServiceProxy.testGetRemoteHourRoomStatus();
        return null;
    }

However, the output is like this:

ZhilianPartnerOuterServiceProxy.java:285) ## ??? public com.meituan.service.mobile.hotel.zhilian.huazhu.service.impl.HuazhuHourRo
omstatusServiceImpl@5400d17c
(ZhilianPartnerOuterServiceProxy.java:280) ## ??? package null

It makes no sense! The only difference between them is public declared. I dumped the byte code enhanced by cglib, testGetRemoteHourRoomStatus method is almost same as testGetRemoteHourRoomStatus1 and both override super class ZhilianPartnerOuterServiceProxy's:

 0 aload_0
 1 getfield #50 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$CONSTRUCTED>
 4 ifne 12 (+8)
 7 aload_0
 8 invokespecial #484 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy.testGetRemoteHourRoomStatus>
11 areturn
12 aload_0
13 getfield #52 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$CALLBACK_0>
16 dup
17 ifnonnull 29 (+12)
20 pop
21 aload_0
22 invokestatic #56 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$BIND_CALLBACKS>
25 aload_0
26 getfield #52 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$CALLBACK_0>
29 dup
30 ifnull 52 (+22)
33 aload_0
34 getstatic #486 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$testGetRemoteHourRoomStatus$35$Method>
37 getstatic #60 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$emptyArgs>
40 getstatic #488 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy$$EnhancerByCGLIB$$3e555043.CGLIB$testGetRemoteHourRoomStatus$35$Proxy>
43 invokeinterface #68 <net/sf/cglib/proxy/MethodInterceptor.intercept> count 5
48 checkcast #135 <com/hotelswlib/results/ZhilianRoomStatusSyncResult>
51 areturn
52 aload_0
53 invokespecial #484 <com/zhilian/service/impl/ZhilianPartnerOuterServiceProxy.testGetRemoteHourRoomStatus>
56 areturn

But the phenomenon is tell me that when testGetRemoteHourRoomStatus() is called, it goes directly into super's testGetRemoteHourRoomStatus() as zhilianPartnerHourRoomStatusService is never initialized so log out null, It seems that callback intercepter is never been executed? why?
However when testGetRemoteHourRoomStatus1 is called, everything is ok. it goes callback intercepter and invoke targetSource and log not null.
More interesting thing is that:
zhilianPartnerHourRoomStatusService() -> getLogger() ->intercept getLogger() , yes, getLogger() is intercepted because it was declared public.
Even interesting thing is that:
it goes fine in my PC but null in testing environment. the only different is jdk version.

BeanCopier.java problem

line 112
PropertyDescriptor[] setters = ReflectUtils.getBeanGetters(target);

whether should be modified to

PropertyDescriptor[] setters = ReflectUtils.getBeanSetters(target);

3.2.1 Release request

Hi,

It would be great to have the release that contains the permgen leak fix, so that spring can repackage it.

Thanks in advance.

ClassNotFoundException

Hello,

i tried to use enhancer.createClass(); und then i become this error:
java.lang.ClassNotFoundException: net.sf.cglib.proxy.Factory

Proxy creation is not thread safe

By default, Enhancer enables method interception during proxy construction (InterceptDuringConstruction flag) and, if incompletely constructed proxy will be called from a different thread, actual callback (interceptor) will be lost (because callbacks are stored inside thread local during proxy creation).

Test case for reproduction: google/guice#1070 (comment)

For sure, this is "never do that" case, but still easy to accidently do. The resulted behavior is confusing: no callbacks registered and no errors thrown.

Will you consider this as a bug or "by design" behavior? Please share your opinion.

java.lang.VerifyError with this set of classes

I apologize if this is the wrong way or the wrong project to be bothering. Maybe it's ASM, maybe it's easymock, maybe it's me?

Anyway, I've got a little project here https://github.com/mikecurwen/verifyError and the stacktrace I get with it, when I run "maven test" is

java.lang.VerifyError: (class: com/company/app/module/constraint/validator/FooExtendsValidator$$EnhancerByCGLIB$$f33b9a57, method: CGLIB$isValid$0 signature: (Ljava/lang/Object;Ljavax/validation/ConstraintValidatorContext;)Z) Incompatible argument to function
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:340)
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:386)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
    at org.easymock.internal.ClassProxyFactory.createProxy(ClassProxyFactory.java:175)
    at org.easymock.internal.MocksControl.createMock(MocksControl.java:114)
    at org.easymock.internal.MocksControl.createMock(MocksControl.java:88)
    at org.easymock.internal.MockBuilder.createMock(MockBuilder.java:206)
    at org.easymock.internal.MockBuilder.createMock(MockBuilder.java:219)
    at org.easymock.internal.MockBuilder.createMock(MockBuilder.java:188)
    at com.company.app.module.constraint.validator.FooExtendsValidatorTest.createPartialMock(FooExtendsValidatorTest.java:38)
    at com.company.app.module.constraint.validator.FooExtendsValidatorTest.testValid(FooExtendsValidatorTest.java:25)

This is using Java 8.0_20 and for all the other dependencies, see the pom.xml in the linked project. You'll see that when some stuff gets inherited there's an issue. The VerifyError goes away when you copy/paste the two methods from FooNoimplementsConstraintValidator into FooExtendsValidator (and then remove the 'extends ...'). I'm initially reporting this here, because cglib appears to be the last library called before JRE classes.

Memory leak caused by identical classes being generated

We're having an issue where our spring-based JSF webapp throws an OOM after a few days (Spring 4.2.6 with cglib 3.2.2). I've tracked it down to the proxy classes that are generated for the Spring/JSF beans: instead of reusing the already generated cglib class definition, new ones are generated quite frequently. Since the classes themselves won't get garbage collected we run out of memory after a few days.

I've created a small example (mirroring the way spring uses cglib internally) to reproduce the issue:

while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(SampleClass.class);
            enhancer.setCallbackFilter(new CallbackFilter() {
                @Override
                public int accept(Method method) {
                    return 0;
                }
                @Override
                public boolean equals(Object obj) {
                    return true;
                }

                @Override
                public int hashCode() {
                    return 0;
                }
            });
            enhancer.setInterfaces(new Class[]{SampleI.class});
            enhancer.setCallback(new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (method.getDeclaringClass() != Object.class
                            && method.getReturnType() == String.class) {
                        System.out.println("Hello cglib!");
                        return null;
                    } else {
                        throw new RuntimeException("Do not know what to do.");
                    }
                }});
            SampleClass proxy = (SampleClass) enhancer.create();
            proxy.test("2");
            Thread.sleep(30);
        }

SampleClass is just:

public class SampleClass implements SampleI {

    public String test(String s) {
        return s;
    }

}

After every GC run, the cached generated classes are no longer used, instead new ones are generated. See attached shot from memory profiler
2016-06-16 11_51_00-cg - yourkit java profiler 2016 02-b38 - 64-bit

I've tracked this down to the LoadingCache and the use of a CallbackFilter on the Enhancer. The CallbackFilter is kept via WeakReference and used as part of the map key in the cache. If the filter is not referenced from outside it will be GC'd, so the entry in the cache won't be found any more.

Question: what is the static hook used for?

Hi,

I'm running in to an issue where a class generated by cglib (via Mockito) has a CGLIB$STATICHOOK method larger than 64K which causes the JVM to throw an error.

So now I'm curious:

  1. Conceptually, what is the static hook used for? It seems like there is one generated per class. Is this used to intercept static initialization? Something else?
  2. How would I be able to reduce the size of the static hook generated by my class?

Thanks for your time!

VerifyError on attempt to load class generated by cglib

Hi,

I've got a VerifyError: Must call initializers using invokespecial during load of the class generated by cglib. It seems like cglib doesn't handle the case when bridge methods generated by javac contain arbitrary code. In my project I use @NotNull annotation by jetbrains which adds check if the returned value is null and throw an exception in this case. It adds this code both to original method and to bridge method generated by javac. The generated byte code looks like this:

  public java.lang.Object getValue();
    descriptor: ()Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
    Code:
      stack=8, locals=1, args_size=1
         0: aload_0
         1: invokevirtual #43                 // Method getValue:()Ljava/lang/String;
         4: dup
         5: ifnonnull     38
         8: new           #25                 // class java/lang/IllegalStateException
        11: dup
        12: ldc           #27                 // String @NotNull method %s.%s must not return null
        14: ldc           #28                 // int 2
        16: anewarray     #4                  // class java/lang/Object
        19: dup
        20: ldc           #29                 // int 0
        22: ldc           #30                 // String TestImpl
        24: aastore
        25: dup
        26: ldc           #31                 // int 1
        28: ldc           #32                 // String getValue
        30: aastore
        31: invokestatic  #38                 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
        34: invokespecial #40                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
        37: athrow
        38: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      39     0  this   LTestImpl;
      LineNumberTable:
        line 4: 0
      StackMapTable: number_of_entries = 1
        frame_type = 102 /* same_locals_1_stack_item */
          stack = [ class java/lang/String ]
    RuntimeInvisibleAnnotations:
      0: #23()

The BridgeMethodResolver code is triggered by 34: invokespecial #40 as a result in generated code by cglib invokestatic is replaced by invokevirtual which results in VerifyError.

Release CGLIB 3.1.x?

I'm interested in getting a new release of CGLIB up on Maven Central which can be consumed by downstream projects. I need pull request #15 for Mockito but they only consume official releases.

Can I pretty please get a release?

Add more committers

I don't have the time to keep up with all the PRs for this project, so I'd like to add more committers.

Based on recent activity, the following folks may be interested:
@JBodkin
@lukesandberg
@raphw
@guw

If you'd like to be a committer, please respond on this issue. I ask only that you

  1. Ensure tests are added with new code and are meaningful (e.g, fail w/o the fixes, pass w/ them)
  2. Any new APIs are sane. If you're unsure about sanity, just ask.
  3. Keep backwards compatibility as much as possible.

TinyBitSet: is it used/useful

I stumbled across the TinyBitSet and noticed a small improvement; I then added some more tests but wondered why it would be useful (as there isn't any documentation).

Some possible bugs:

  1. set bits 0-31 then bits 32.. are already set
  2. set bit 31 then cardinality() results in an infinite loop

After a bit of searching it doesn't seem that this code is used anywhere (in the open source world) apart from copies of it or its test file.

Can we delete it or document (and test and maybe fix it)?

Update version in pom.xml

3.2.1 is released, yet pom.xml reads 3.2.0.

maven-release-plugin should probably be configured to keep versions consistent.

JFYI: I've went though configuration of maven-release-publish-to-central projects recently, however it requires oss.sonatype grants to test the procedure.

Switch to Opcodes.ASM5

It looks like CGLIB version 3.2 will upgrade ASM dep to 5.0.3, but Opcodes.ASM4 is still being passed everywhere. Are there any plans to change this before 3.2 release? It causes runtime exceptions when trying to proxy classes compiled with the -parameters flag

Help with NPE in Spring-Bundled Version of cglib

Hello!

I have an issue with a large application utilizing IntelliJ's @NotNull annotation weaver (https://github.com/osundblad/intellij-annotations-instrumenter-maven-plugin) and spring core 4.2.6. Spring has a bundled version of cglib, which according to the sources should be cglib 3.1. I have however been unsuccessful when trying to correlate this stack trace with cglib 3.1. I am also unable to reproduce this error in small test cases, so I thought I would ask you for help. Can you make any sense of this stack trace?

Caused by: java.lang.NullPointerException
	at java.lang.String.<init>(String.java:204)
	at org.springframework.asm.Type.getInternalName(Type.java:580)
	at org.springframework.cglib.core.CodeEmitter.emit_type(CodeEmitter.java:552)
	at org.springframework.cglib.core.CodeEmitter.checkcast(CodeEmitter.java:584)
	at org.springframework.cglib.proxy.Enhancer$6.emitInvoke(Enhancer.java:1128)
	at org.springframework.cglib.proxy.MethodInterceptorGenerator.superHelper(MethodInterceptorGenerator.java:143)
	at org.springframework.cglib.proxy.MethodInterceptorGenerator.generate(MethodInterceptorGenerator.java:103)
	at org.springframework.cglib.proxy.Enhancer.emitMethods(Enhancer.java:1158)
	at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:581)
	at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
	at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
	at org.springframework.aop.framework.CglibAopProxy$ClassLoaderAwareUndeclaredThrowableStrategy.generate(CglibAopProxy.java:990)
	at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:312)
	at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:445)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:85)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:83)
	at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
	at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
	at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:105)
	at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:278)
	at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:433)
	at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:338)
	at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:55)
	at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:203)

What I can conclude from this stacktrace is that Type.getInternalName() is called for the type boolean ('Z'), which isn't supported for primitive types according to the method documentation. Type subsequently tries to create a String from a null char buffer. The guard around calling getInternalName() in TypeEmitter.emit_type() only checks for array types, which seems fishy.

While trying to modify the code slightly to see a pattern, I've also ran into issue #48 , so it seems likely that they are related.

By the way, in emitInvoke, the stack contains these seemingly interesting frames (might be related to bridge methods):

method=update(Lcom/redacted/User;)Z
bridgeTarget=<init>(Ljava/lang/String;)V
retType=Z

Thank you for your help.

Support generation of stateless callbacks

cglib_generates_instance_fields

When creating a proxy, cglib always creates CGLIB$CALLBACK field.
It makes sense creating static fields (or avoid creation of the fields) to lower memory consumption and improve the response time.

In the attached screenshot, there are some like 180 (!) fields, that is 180*4 = 720 bytes loss per object.

Make the dominant development state more visible

cglib is still the most-used code generation library in the JVM space. However, its code base is no longer actively maintained and the alternatives show less bugs and better performance. The little ongoing maintenance is also quite a challenge as the code base lacks comments and test coverage. For its age, cglib is however still the most known and many users still start projects using this library.

I want to suggest that we discourage the usage of cglib in new projects and mention this on the landing page here on GitHub. Does this sound reasonable?

Support Java 8

cglib 3.1 doesn't seem to work under Java 8. In the best case, all that's required is to update to ASM 5 (see #7).

net.sf.cglib.asm.ClassReader.<init>(Unknown Source)

hi there, what i do wrong with cglib-nodep 3.1 on jdk8?
Exception in thread "main" java.lang.IllegalArgumentException
at net.sf.cglib.asm.ClassReader.(Unknown Source)
at net.sf.cglib.asm.ClassReader.(Unknown Source)
at net.sf.cglib.asm.ClassReader.(Unknown Source)
at net.sf.cglib.proxy.BridgeMethodResolver.resolveAll(BridgeMethodResolver.java:61)
at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:911)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:498)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at com.wintv.cache.AbstractProxy.getInstance(AbstractProxy.java:49)
at com.wintv.cache.test.ProxyTest.testSimple(ProxyTest.java:31)
at com.wintv.cache.test.ProxyTest.main(ProxyTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

--- source code AbstractProxy --
`package com.wintv.cache;

import com.wintv.common.utils.JsonUtil;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
*

  • Created by huaying on 2016/5/3.
    */
    public abstract class AbstractProxy implements MethodInterceptor {

    public static final String DEFAULT_CACHE="winTv";

    private final Logger logger = LoggerFactory.getLogger(getTargetClass());
    private final String cacheName;
    private Cache cache;

    public AbstractProxy() {
    this(DEFAULT_CACHE);
    }

    public AbstractProxy(String cacheName) {
    this.cacheName = cacheName;
    try {
    cache = CacheManager.getCache(cacheName);
    }catch (Exception e) {
    logger.warn("get cache error", e);
    cache = null;
    }
    }

    /**

    • ๅˆ›ๅปบไปฃ็†ๅฏน่ฑก
      *
    • @return
      */
      public T getInstance() {
      Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(getTargetClass());
      enhancer.setCallback(this);
      return (T)enhancer.create();
      }

    public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {

    if(!needCache(method) || cache == null) {
        return methodProxy.invokeSuper(proxy, params);
    }
    
    System.out.println("before method invoke");
    String cacheKey = getCacheKey(method, params);
    Element element = cache.get(cacheKey);
    if(element != null) {
        logger.info("get from cache with key: {}" ,cacheKey);
        return element.getObjectValue();
    }
    
    logger.info("none cache, get from db with key: {}", cacheKey);
    Object result;
    synchronized (this) {
        result = methodProxy.invokeSuper(proxy, params);
        cache.put(new Element(cacheKey, result, timeToIdleSeconds(), timeToLiveSeconds()));
        System.out.println("after method invoke");
        after(method, params, result);
    }
    return result;
    

    }

    protected abstract boolean needCache(Method method);

    protected abstract Class getTargetClass();

    protected abstract void after(Method method, Object[] params, Object result);

    protected Integer timeToIdleSeconds(){
    return 120;
    };

    protected Integer timeToLiveSeconds() {
    return 120;
    }

    protected String getCacheKey(Method method, Object[] params) {
    return new StringBuffer()
    .append(getTargetClass().getName())
    .append(".")
    .append(method.getName())
    .append(JsonUtil.toJson(params))
    .toString();
    }
    }
    `

--- source code ProxyTest --

`package com.wintv.cache.test;

import com.wintv.cache.AbstractProxy;

import java.lang.reflect.Method;

/**

  • Created by huaying on 2016/5/4.
    */
    public class ProxyTest {

    public static void testSimple() {

    User user = new AbstractProxy<User>() {
        @Override
        protected boolean needCache(Method method) {
            return true;
        }
    
        @Override
        protected Class<User> getTargetClass() {
            return User.class;
        }
    
        @Override
        protected void after(Method method, Object[] params, Object result) {
    
        }
    }.getInstance();
    
    user.test();
    

    }

    public static void main(String[] args) {
    testSimple();
    }

}

package com.wintv.cache.test;

/**

  • Created by huaying on 2016/5/4.
    */
    public class User extends BaseDao<com.wintv.subsystem.business.user.model.User, String> {

    public void test() {
    System.out.println(System.currentTimeMillis());
    }

    @OverRide
    public String getTableName() {
    return "tv_user";
    }

    @OverRide
    public Class getClazz() {
    return User.class;
    }

    @OverRide
    public String getPrimaryKeyFieldName() {
    return "user_id";
    }

    @OverRide
    public String getPrimaryKeyFieldValue(String id) {
    return id;
    }
    }
    package com.wintv.subsystem.common;

import com.squareup.wire.Message;
import com.wintv.common.utils.StringUtil;
import com.wintv.subsystem.db.DBUtils;
import com.wintv.subsystem.db.TransactionManager;
import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.log4j.Logger;
import org.postgresql.util.PGobject;

import java.sql.Array;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**

  • Created by pipi on 16/1/20.

  • T ๆ˜ฏๆจกๅž‹ๅฏน่ฑก

  • K ๆ˜ฏๆ•ฐๆฎๅบ“ไธป้”ฎ็š„ๅฏน่ฑก็ฑปๅž‹

  • ็ปงๆ‰ฟ Apache DBUtils ็š„ BasicRowProcessor
    */
    public abstract class BaseDao<T extends BaseDBObject, K> extends BasicRowProcessor {

    public static final Logger log = Logger.getLogger(BaseDao.class.getName());

    // Apache DBUtils ้ป˜่ฎคไธป้”ฎID่Žทๅ–็š„ Handler (ScalarHandler)
    public final ResultSetHandler DEFAULT_PRIMARY_KEY_HANDLER = new ScalarHandler();

    // Apache DBUtils ้œ€่ฆ็š„ Bean ่ฝฌๆข็ฑป๏ผŒๅ‚่€ƒApache DBUtils่ฏดๆ˜Ž
    private BeanListHandler beanListHandler;

    // Apache DBUtils ๅ•ๅ€ผๆŸฅ่ฏข Handler
    public final ResultSetHandler SINGLE_VALUE_HANDLER = new ScalarHandler<>(1);

    // beanListHandler็š„ๅฏน่ฑก้”๏ผŒ็”จไบŽ้ฆ–ๆฌก็”Ÿๆˆๅฏน่ฑกไฟๆŠค้”
    private Object lock = new Object();

    // ็ปงๆ‰ฟๅ’Œๅฎž็ŽฐBasicRowProcessor็š„็ฑป๏ผŒๅ‚่€ƒApache DBUtils่ฏดๆ˜Ž
    @OverRide
    public TT toBean(ResultSet rs, Class type) throws SQLException {

    T t = null;
    try {
        t = (T) getClazz().newInstance();
    } catch (InstantiationException ex) {
        log.error("<toBean> catch exception=" + ex.toString(), ex);
        throw new RuntimeException(ex);
    } catch (IllegalAccessException ex) {
        log.error("<toBean> catch exception=" + ex.toString(), ex);
        throw new RuntimeException(ex);
    }
    
    // ่ฐƒ็”จๆจกๆฟ็ฑป็š„ toBean ๆ–นๆณ•ๆฅๅฎž็Žฐ JDBC ๆŸฅ่ฏข็ป“ๆžœ้›†ๅˆๅˆฐ ๆ•ฐๆฎๅฏน่ฑก็š„่ฝฌๆข
    t.toBean(rs, t.getData());
    return (TT) t;
    

    }

    // ็ปงๆ‰ฟๅ’Œๅฎž็ŽฐBasicRowProcessor็š„็ฑป๏ผŒๅ‚่€ƒApache DBUtils่ฏดๆ˜Ž
    @OverRide
    public List toBeanList(ResultSet rs, Class type) {
    try {
    List newlist = new LinkedList();
    while (rs.next()) {
    newlist.add(toBean(rs, type));
    }
    return newlist;
    } catch (SQLException ex) {
    log.error(" catch exception=" + ex.toString(), ex);
    throw new RuntimeException(ex);
    }
    }

    // ๆ˜ ๅฐ„็š„ๆ•ฐๆฎๅบ“่กจๅ
    public abstract String getTableName();

    // ๅฏน่ฑก็ฑป
    public abstract Class getClazz();

    // ๆ•ฐๆฎๅญ˜ๅ‚จๅฏน่ฑกไธป้”ฎๅ็งฐ
    abstract public String getPrimaryKeyFieldName();

    // ๆ•ฐๆฎๅบ“ๅญ˜ๅ‚จๅฏน่ฑกไธป้”ฎ๏ผŒไปŽๅญ—็ฌฆไธฒๅ€ผ่ฝฌๆขไธบๅฎž้™…ๅฏน่ฑก๏ผˆๅฆ‚Integer, Long๏ผ‰
    abstract public K getPrimaryKeyFieldValue(String id);

    // ่Žทๅ–BeanListHandler๏ผŒ็”จไบŽDBUtilsๆ–นๆณ•ๆ“ไฝœ๏ผŒๅ‚่€ƒApache DBUtils่ฏดๆ˜Ž
    public BeanListHandler getBeanListHandler() {
    synchronized (lock) {
    if (beanListHandler == null) {
    beanListHandler = new BeanListHandler(getClazz(), this);
    }
    return beanListHandler;
    }
    }

    // ๆ นๆฎ็ป™ๅฎš็ฑปๆž„้€ ๅฏน่ฑก
    protected T newClassInstance(Class clazz) {
    try {
    return clazz.newInstance();
    } catch (InstantiationException e) {
    log.error(" please implement the default constructor for " + clazz.getSimpleName() + "!!! ", e);
    return null;
    } catch (IllegalAccessException e) {
    log.error(" catch exception" + e.toString(), e);
    return null;
    }
    }

    // ๆทปๅŠ ๆ’ๅ…ฅๅญ—ๆฎตๅ’Œๅญ—ๆฎตๅฏนๅบ”็š„ๅฏน่ฑกๅ€ผ๏ผŒๅฏน่ฑกๅ€ผๅฟ…้กปๆ˜ฏ JDBC SQL ๆ”ฏๆŒ็š„ๅฏน่ฑกๅ€ผ
    protected void addInsertField(String fieldType, Object fieldValue, List fieldList, List paramsList) {

    if (fieldValue == null){
        return;
    }
    
    fieldList.add(fieldType);
    paramsList.add(fieldValue);
    

    }

    //
    protected String buildBatchInsertValuesSQL(Object[][] paramsArrays) {
    if (paramsArrays == null || paramsArrays.length == 0 || paramsArrays[0].length == 0) {
    return "";
    }

    //ๆž„้€ ็ฌฌไธ€่กŒ็š„๏ผŸๅทๅ‚ๆ•ฐ
    List<String> fList = new ArrayList<>();
    for (int i = 0; i < paramsArrays[0].length; i++) {
        if (paramsArrays[0][i] instanceof PGobject) {
            fList.add("?::jsonb");
        } else {
            fList.add("?");
        }
    }
    String fiParamsString = "(" + String.join(",", fList) + ")";
    
    //ๆž„้€ ๆ€ปๅ‚ๆ•ฐ
    

    // List allList = new ArrayList<>();
    // for (int i = 0; i < paramsArrays.length; i++) {
    // allList.add(fiParamsString);
    // }
    // String allParamsString = String.join(",", allList);

    return fiParamsString;
    

    }

    public K batchInsert(J[] pbObjects, OldAddFieldsInsertBatchInterface fieldsInterface, AddValuesInsertBatchInterface valuesInterface) throws SQLException {

    if (pbObjects == null || pbObjects.length == 0) {
    
        return null;
    }
    

    // queryRunner.batch
    // Objects
    // queryRunner.insertBatch()
    List fieldsList = new ArrayList<>();

    //่ฐƒ็”จๆ—ถๅบ”่ฏฅๅœจๅฎž็Žฐไธญๅคšๆฌก่ฐƒ็”จaddInsertBatchField(fieldList,่ฆ็ฝฎๅ…ฅfieldList็š„ๅ€ผ)๏ผŒไธŽvaluesInterface.addFValuesๅฏนๅบ”
    fieldsInterface.addFields(fieldsList);
    
    if (fieldsList.size() == 0) {
        return null;
    }
    
    
    //่Žทๅ–ไบŒ็ปดๆ•ฐ็ป„ๅ‚ๆ•ฐ
    Object[][] paramsArrays = new Object[pbObjects.length][];
    for (int i = 0; i < pbObjects.length; i++) {
    
        List<Object> paramsList = new ArrayList<>();
    
        J pbObject = pbObjects[i];
    
        //ๅ†…้ƒจๆŽฅๅฃๅฎž็Žฐๅบ”่ฏฅๅคšๆฌก่ฐƒ็”จparamsList.add(pbObject.XXX),ไธŽfieldsInterface.addFieldsๅฏนๅบ”
        valuesInterface.addFValues(paramsList, pbObject);
    
        if (paramsList.size() == 0) {
            return null;
        }
    
        paramsArrays[i] = paramsList.toArray();
    }
    
    if (paramsArrays == null || paramsArrays.length == 0 || paramsArrays[0].length == 0) {
        return null;
    }
    
    log.info("<batchInsert > ๅ‚ๆ•ฐๆ•ฐ้‡๏ผš" + fieldsList.size());
    log.info("<batchInsert > ๅ€ผ็š„ๆ•ฐ้‡๏ผš" + paramsArrays[0].length);
    if (fieldsList.size() != paramsArrays[0].length) {
        log.error("<batchInsert > ๅ‚ๆ•ฐไธŽๅ‚ๆ•ฐๅ€ผ็š„ๆ•ฐ้‡ไธๅฏนๅบ”,ๆ’ๅ…ฅๅคฑ่ดฅ๏ผ");
        return null;
    }
    
    //ๆž„้€ ไบŒ็ปดๆ•ฐ็ป„ๅ‚ๆ•ฐ็š„๏ผŸๅทๅˆ—่กจ
    String valuesString = buildBatchInsertValuesSQL(paramsArrays);
    
    
    StringBuilder sqlBuilder = new StringBuilder();
    sqlBuilder.append("INSERT INTO " + getTableName());
    sqlBuilder.append(" (");
    sqlBuilder.append(buildInsertFieldsSQL(fieldsList));
    sqlBuilder.append(" )");
    sqlBuilder.append(" VALUES ");
    sqlBuilder.append(valuesString);
    String sql = sqlBuilder.toString();
    
    //่พ“ๅ‡บๆ—ฅๅฟ—
    log.info("<batchInsert > spl=" + sql);
    for (int i = 0; i < paramsArrays.length; i++) {
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < paramsArrays[0].length; j++) {
            sb.append(fieldsList.get(j) + "=" + paramsArrays[i][j] + " ");
        }
        log.info("<batchInsert > ็ฌฌ" + i + "ๆ•ฐๆฎไธบ\t" + sb.toString());
    }
    
    
    //ๅผ€ๅง‹ๅ‡†ๅค‡ๆ’ๅ…ฅๆ•ฐๆฎ
    
    // init query runner
    QueryRunner queryRunner = new QueryRunner();
    
    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    
    K k = queryRunner.insertBatch(connection, sql, DEFAULT_PRIMARY_KEY_HANDLER, paramsArrays);
    
    
    log.info("<batchInsert > ่ตทๅง‹id=" + k);
    log.info("<batchInsert > ๆ’ๅ…ฅๆกๆ•ฐ=" + pbObjects.length);
    
    
    return k;
    

    }

    @FunctionalInterface
    public static interface OldAddFieldsInsertBatchInterface {

    public void addFields(List<String> fieldList) throws SQLException;
    

    }

    @FunctionalInterface
    public static interface AddValuesInsertBatchInterface {

    public void addFValues(List pbObjectList, J pbObject) throws SQLException;
    

    }

    // ๆ’ๅ…ฅไธ€ๆก่ฎฐๅฝ•
    public K insert(InsertSQLInterface insertSQLInterface) throws SQLException {

    // init query runner
    QueryRunner queryRunner = new QueryRunner();
    
    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    List<String> fieldsList = new ArrayList<>();
    List<Object> paramsList = new ArrayList<>();
    
    insertSQLInterface.addInsertFieldValues(connection, fieldsList, paramsList);
    
    if (fieldsList.size() == 0) {
        // nothing to insert
        return null;
    }
    
    StringBuilder sqlBuilder = new StringBuilder();
    
    sqlBuilder.append("INSERT INTO " + getTableName());
    sqlBuilder.append(" (");
    sqlBuilder.append(buildInsertFieldsSQL(fieldsList));
    sqlBuilder.append(" )");
    sqlBuilder.append(" VALUES (");
    sqlBuilder.append(buildInsertValuesSQL(paramsList));
    sqlBuilder.append(" )");
    
    String sql = sqlBuilder.toString();
    log.info("<insert> sql=" + sql + " , params=" + paramsList);
    
    // init date field
    K seqId = queryRunner.insert(connection, sql,
            DEFAULT_PRIMARY_KEY_HANDLER,
            paramsList.toArray());
    
    log.info("<insert> " + getTableName() + ", return id=" + seqId);
    return seqId;
    

    }

    // ๆž„้€ ๆ’ๅ…ฅ็š„ๅญ—ๆฎต็š„ VALUES ็ฉบไฝ ? ๅˆ—่กจ
    private String buildInsertValuesSQL(List paramsList) {
    if (paramsList.size() == 0) {
    return "";
    }

    List<String> list = new ArrayList<>();
    for (int i = 0; i < paramsList.size(); i++) {
        if (paramsList.get(i) instanceof PGobject) {
            list.add("?::jsonb");
        } else {
            list.add("?");
        }
    }
    
    return String.join(", ", list);
    

    }

    // ๆž„้€ ๆ’ๅ…ฅ็š„ๅญ—ๆฎตๅˆ—่กจ
    private String buildInsertFieldsSQL(List fieldsList) {
    if (fieldsList.size() == 0) {
    return "";
    }

    return String.join(", ", fieldsList);
    

    }

    // ๆ นๆฎๆŸฅ่ฏขๆกไปถ่ฟ”ๅ›žๅˆ—่กจ
    public List queryByCondition(String whereString, int offset, int limit, String[] returnFields, Object... params) throws SQLException {

    // init query runner
    QueryRunner queryRunner = new QueryRunner();
    
    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    List<String> whereSQL = new ArrayList<>();
    
    StringBuilder sqlBuilder = new StringBuilder();
    sqlBuilder.append("SELECT ");
    sqlBuilder.append(buildSelectFields(returnFields));
    sqlBuilder.append(" FROM " + getTableName() + " ");
    
    sqlBuilder.append(whereString);
    sqlBuilder.append(buildOffsetLimit(offset, limit));
    
    // execute update
    String sql = sqlBuilder.toString();
    
    // execute query
    log.info("<query> " + getTableName() + " " + sql + " , params=" + params);
    List<T> list = queryRunner.query(connection, sql, getBeanListHandler(), params);
    
    // handler return
    if (list == null || list.size() == 0) {
        log.info("<query> " + getTableName() + " but return no result");
        return Collections.emptyList();
    }
    
    log.info("<query> " + getTableName() + " total " + list.size() + " returns");
    return list;
    

    }

    // ๆž„้€ ่ฟ”ๅ›ž็š„่ฎฐๅฝ•ๆ•ฐ็›ฎๅ’Œๅ็งป
    private String buildOffsetLimit(int offset, int limit) {

    String sql = "";
    if (limit > 0) {
        sql += " LIMIT " + limit;
    }
    
    if (offset > 0) {
        sql += " OFFSET " + offset;
    }
    
    return sql;
    

    }

    // ๆ นๆฎ็ป™ๅฎš SQL ๅ’Œไผ ๅ…ฅๅ‚ๆ•ฐๅ€ผ๏ผŒๆ‰ง่กŒๆŸฅ่ฏข๏ผŒJDBC ๆ ‡ๅ‡†๏ผŒๅŸบไบŽApache DBUtils็š„ QueryRunner ๅฎž็Žฐ
    public List query(String sql, int offset, int limit, Object... params) throws SQLException {

    // init query runner
    QueryRunner queryRunner = new QueryRunner();
    
    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    if (limit > 0) {
        sql += " LIMIT " + limit;
    }
    
    if (offset > 0) {
        sql += " OFFSET " + offset;
    }
    
    log.info("<query> " + getTableName() + " sql=" + sql + " , params=" + params);
    
    // execute query
    List<T> list = queryRunner.query(connection, sql, getBeanListHandler(), params);
    
    // handler return
    if (list == null) {
        log.info("<query> " + getTableName() + " but return list null");
        return Collections.emptyList();
    }
    
    log.info("<query> " + getTableName() + " total " + list.size() + " returns");
    return list;
    

    }

    // ๆ นๆฎ็ป™ๅฎš็š„ๅญ—ๆฎต๏ผŒๆž„้€ ่ฟ”ๅ›ž็š„ SELECT ๅญ—ๆฎต็š„ๅญ—็ฌฆไธฒ
    // ๅฆ‚ๆžœๆœช็ฉบๅˆ™่ฟ”ๅ›ž * ๏ผˆSELECT ๏ผ‰
    // ็คบไพ‹๏ผšๅฆ‚ๆžœๆ˜ฏ ["name", "address"] ๅˆ™่ฟ”ๅ›ž name,address
    public String buildSelectFields(String[] returnFields) {
    if (returnFields == null || returnFields.length == 0) {
    return "
    ";
    } else {
    String fields = String.join(", ", returnFields);
    return fields;
    }
    }

    // ๆ นๆฎๆไพ›็š„ where ๆŸฅ่ฏขๆกไปถๆŸฅ่ฏข๏ผŒๅช่ฟ”ๅ›ž็ฌฌไธ€ๆก่ฎฐๅฝ•
    public T queryByCondition(String whereString, String[] returnFields, Object... params) throws SQLException {
    // init query runner
    QueryRunner queryRunner = new QueryRunner();

    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    List<Object> paramsList = new ArrayList<>();
    
    //ๅขžๅŠ ไธ€ๅค„๏ผŒไน‹ๅ‰paramsๅฏน่ฑกไธบ็ฉบ๏ผŒๆŠฅ้”™
    for (Object oj : params) {
        paramsList.add(oj);
    }
    
    List<String> whereSQL = new ArrayList<>();
    
    StringBuilder sqlBuilder = new StringBuilder();
    sqlBuilder.append("SELECT ");
    sqlBuilder.append(buildSelectFields(returnFields));
    sqlBuilder.append(" FROM " + getTableName() + " ");
    
    sqlBuilder.append(whereString);
    sqlBuilder.append(" LIMIT 1");
    
    // execute update
    String sql = sqlBuilder.toString();
    
    // execute query
    log.info("<query> " + getTableName() + " " + sql + " , params size=" + paramsList.size() + ", params = " + paramsList);
    List<T> list = queryRunner.query(connection, sql, getBeanListHandler(), paramsList.toArray());
    
    // handler return
    if (list == null || list.size() == 0) {
        log.info("<query> " + getTableName() + " but return no result");
        return null;
    }
    
    log.info("<query> " + getTableName() + " result=" + list.get(0));
    return list.get(0);
    

    }

    // ๆ นๆฎๅญ—็ฌฆไธฒ PRIMARY KEY ID ๆŸฅ่ฏข
    public T queryById(String id, String... returnFields) throws SQLException {

    // init query runner
    QueryRunner queryRunner = new QueryRunner();
    
    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    List<Object> paramsList = new ArrayList<>();
    List<String> whereSQL = new ArrayList<>();
    
    StringBuilder sqlBuilder = new StringBuilder();
    sqlBuilder.append("SELECT ");
    sqlBuilder.append(buildSelectFields(returnFields));     // ๆŒ‡ๅฎš่ฟ”ๅ›žๅญ—ๆฎต
    sqlBuilder.append(" FROM " + getTableName());
    
    // add where condition
    addWhereValue(whereSQL, paramsList, getPrimaryKeyFieldName(), getPrimaryKeyFieldValue(id));
    
    // add where string
    if (whereSQL.size() > 0) {
        sqlBuilder.append(" WHERE ");
        sqlBuilder.append(buildWhereAndSQL(whereSQL));
        sqlBuilder.append(" LIMIT 1");
    } else {
        // avoid select ALL records...
        return null;
    }
    
    // execute update
    String sql = sqlBuilder.toString();
    
    // execute query
    log.info("<query> " + getTableName() + " " + sql + " , params=" + paramsList);
    
    List<T> list = queryRunner.query(connection, sql, getBeanListHandler(), paramsList.toArray());
    
    // handler return
    if (list == null || list.size() == 0) {
        log.info("<query> " + getTableName() + " but return no result");
        return null;
    }
    
    log.info("<query> " + getTableName() + " result=" + list.get(0));
    return list.get(0);
    

    }

    // ๆ นๆฎ็ป™ๅฎš PRIMARY KEY ID ๅˆ—่กจๆŸฅ่ฏข๏ผŒ่ฟ”ๅ›ž Map
    public Map<K, T> queryMapByIdList(Collection idList) throws SQLException {

    if (idList == null || idList.size() == 0) {
        log.warn("<queryByIdList> " + getTableName() + " empty id list");
        return Collections.emptyMap();
    }
    
    // init query runner
    QueryRunner queryRunner = new QueryRunner();
    
    // get connection from transaction
    Connection connection = TransactionManager.getConnection();
    
    List<Object> paramsList = new ArrayList<>();
    List<String> whereSQL = new ArrayList<>();
    
    StringBuilder sqlBuilder = new StringBuilder();
    sqlBuilder.append("SELECT ");
    sqlBuilder.append("*");
    sqlBuilder.append(" FROM " + getTableName());
    
    // add where condition
    // add where string
    if (idList.size() > 0) {
        sqlBuilder.append(" WHERE " + getPrimaryKeyFieldName() + " IN (");
    
        List<String> stringValues = new ArrayList<>();
        for (K id : idList) {
            stringValues.add("?");
            paramsList.add(id);
        }
    
        // ็”Ÿๆˆๅ’Œๆ‹ผๆŽฅ ?,?,?, ....
        sqlBuilder.append(String.join(",", stringValues));
        sqlBuilder.append(")");
    } else {
        // avoid select ALL records...
        return Collections.emptyMap();
    }
    
    // execute update
    String sql = sqlBuilder.toString();
    
    // execute query
    log.info("<queryByIdList> " + getTableName() + " " + sql + " , params=" + paramsList);
    List<T> list = queryRunner.query(connection, sql, getBeanListHandler(), paramsList.toArray());
    
    // handler return
    if (list == null || list.size() == 0) {
        log.info("<queryByIdList> " + getTableName() + " but return no result");
        return Collections.emptyMap();
    }
    
    // store result in map
    HashMap<K, T> map = new HashMap();
    for (T t : list) {
        map.put(getPrimaryKeyFieldValue(t.getStringId()), t);
    }
    
    return map;
    

    }

    // ๆ นๆฎ็ป™ๅฎš PRIMARY KEY ID ๅˆ—่กจๆŸฅ่ฏข๏ผŒ่ฟ”ๅ›žๅˆ—่กจ
    public List queryByIdList(List idList) throws SQLException {

    Map<K, T> map = queryMapByIdList(idList);
    if (map == null || map.size() == 0) {
        return Collections.emptyList();
    }
    
    // sort result by original ID list sequence
    ArrayList<T> retList = new ArrayList();
    for (K id : idList) {
        if (map.containsKey(id)) {
            T t = map.get(id);
            retList.add(t);
        }
    }
    
    log.info("<queryByIdList> " + getTableName() + ", total " + retList.size() + " result=" + retList);
    return retList;
    

    }

    // ๆทปๅŠ WHERE ๆŸฅ่ฏขๆกไปถๅ˜้‡
    // ๆฏ”ๅฆ‚่ฆๆทปๅŠ ไธ€ไธช name='Benson' ็š„ๆŸฅ่ฏขๆกไปถ
    protected void addWhereValue(List whereSQL, List paramsList, String fieldName, Object value) {
    whereSQL.add(fieldName + "=?");
    paramsList.add(value);
    }

    public enum WhereType {
    WHERE_EQUAL, // ็›ธ็ญ‰
    WHERE_GREATER_THAN_OR_EQUAL, // ๅคงไบŽ็ญ‰ไบŽ
    WHERE_GREATER_THAN,
    WHERE_LESS_THAN_OR_EQUAL, // ๅฐไบŽ็ญ‰ไบŽ
    WHERE_LESS_THAN, // ๅฐไบŽ
    WHERE_LIKE, // ๅ…ณ้”ฎๅญ—ๅŒ…ๅซ
    WHERE_ARRAY_INTEGER_CONTAINS, // ๆ•ฐ็ป„ๅŒ…ๅซ
    WHERE_NOT_EQUAL, // ไธ็ญ‰ไบŽ
    WHERE_IN_LIST // ๅฑžไบŽไธ€ไธชlistไธญ็š„ๆŸไธช
    }

    // ๆž„้€ whereๅญ—ๆฎตlist ๆž„้€ ๅ‚ๆ•ฐlist,้‡่ฝฝๅŽŸaddWhereValueๆ–นๆณ•
    protected void addWhereValue(List whereSQL, List paramsList, String fieldName, Object value, WhereType type) throws SQLException {

    if (value == null)
        return;
    
    switch (type) {
        case WHERE_EQUAL:
            whereSQL.add(fieldName + "= ?");
            paramsList.add(value);
            break;
        case WHERE_NOT_EQUAL:
            whereSQL.add(fieldName + "!= ?");
            paramsList.add(value);
            break;
        case WHERE_GREATER_THAN_OR_EQUAL:
            whereSQL.add(fieldName + ">= ?");
            paramsList.add(value);
            break;
        case WHERE_GREATER_THAN:
            whereSQL.add(fieldName + "> ?");
            paramsList.add(value);
            break;
        case WHERE_LESS_THAN_OR_EQUAL:
            whereSQL.add(fieldName + "<= ?");
            paramsList.add(value);
            break;
        case WHERE_LESS_THAN:
            whereSQL.add(fieldName + "< ?");
            paramsList.add(value);
            break;
        case WHERE_LIKE:
            whereSQL.add(fieldName + " ILIKE ?");
            paramsList.add("%" + value + "%");
            break;
        case WHERE_ARRAY_INTEGER_CONTAINS:
    
            List<Integer> paramValues = null;
    
            // ๅฐ่ฏ•่ฝฌๆขๆˆIntegerๅž‹็š„list
            try {
                paramValues = (List<Integer>) value;
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
    
            if (paramValues == null || paramValues.size() <= 0)
                return;
    
            whereSQL.add(fieldName + " @> ?");
            Connection connection = TransactionManager.getConnection();
            Array tagArray = DBUtils.toIntArray(connection, paramValues, false);
            paramsList.add(tagArray);
            break;
    
        case WHERE_IN_LIST:
            if (value instanceof List) {
                List inList = (List) value;
                if (inList == null || inList.size() == 0) {
                    return;
                }
    
                // ๆž„้€ ้—ฎๅทๅˆ—่กจ
                List<String> markList = new ArrayList<>();
                for (Object o : inList) {
                    markList.add("?");
                }
                String joinString = String.join(",", markList);
                whereSQL.add(fieldName + " IN (" + joinString + ")");
    
                // ๅฐ†ๅ‚ๆ•ฐๅ…จ้ƒจๅŠ ๅ…ฅ
                paramsList.addAll(inList);
            } else {
                return;
            }
            break;
    
    }
    

    }

    // ๆทปๅŠ  Update ็š„ Set ๆกไปถ
    // ๆฏ”ๅฆ‚่ฆๆทปๅŠ ไธ€ไธช SET mobile='13912345555'
    // forceUpdateNull : ๅฆ‚ๆžœ็ป™ๅฎšๅญ—ๆฎตๅ€ผไธบ็ฉบ๏ผŒๆ˜ฏๅฆไนŸไฟๅญ˜่ฏฅๅ€ผ๏ผŒไธ€่ˆฌ้ป˜่ฎคๅปบ่ฎฎ็”จ false๏ผŒๅณๅชๆœ‰้ž็ฉบๆ‰ๆ›ดๆ–ฐ่ฏฅๅญ—ๆฎต
    protected void addUpdateField(List setFieldList, List paramsList, String fieldName, Object value, boolean forceUpdateNull) {

    if (value == null && !forceUpdateNull) {
        // no need to update
        return;
    }
    
    setFieldList.add(fieldName + "=?");
    paramsList.add(value);
    

    }

    // ่ฟžๆŽฅๅคšไธช set ๅญ—ๆฎต๏ผŒ้€—ๅทๅˆ†้š”
    protected String buildSetSQL(List setFieldList) {
    if (setFieldList.size() == 0) {
    return null;
    }

    return String.join(", ", setFieldList);
    

    }

    // ่ฟžๆŽฅๅคšไธช where ๅญ—ๆฎต๏ผŒๅชๆ”ฏๆŒ AND ่ฟžๆŽฅ
    protected String buildWhereAndSQL(List fieldList) {
    if (fieldList.size() == 0) {
    return null;
    }

    return String.join(" AND ", fieldList);
    

    }

    // lamda ๅ‡ฝๆ•ฐๅผๆŽฅๅฃ๏ผŒ็”จไบŽinsertๆ–นๆณ•
    @FunctionalInterface
    public static interface InsertSQLInterface {
    // ๆทปๅŠ ่ฆๆ’ๅ…ฅ็š„ๅญ—ๆฎตๅ’Œๅ€ผ๏ผŒไฟๅญ˜ๅˆฐ fieldList ๅ’Œ paramsList ไธญ
    public void addInsertFieldValues(Connection connection, List fieldList, List paramsList) throws SQLException;
    }

    // lamda ๅ‡ฝๆ•ฐๅผๆŽฅๅฃ๏ผŒ็”จไบŽupdateๆ–นๆณ•
    @FunctionalInterface
    public static interface UpdateSetInterface {
    // ๆทปๅŠ ่ฆไฟฎๆ”น็š„ๅญ—ๆฎตๅ’Œๅ€ผ๏ผŒไฟๅญ˜ๅˆฐ updateSetSQL ๅ’Œ paramsList ไธญ
    public void addUpdateSetFields(Connection connection, List updateSetSQL, List paramsList) throws SQLException;
    }

    // lamda ๅ‡ฝๆ•ฐๅผๆŽฅๅฃ๏ผŒ็”จไบŽupdateๆ–นๆณ•
    @FunctionalInterface
    public static interface WhereIdInterface {
    // ๆทปๅŠ ่ฆWHERE็š„ๆกไปถ๏ผˆไป…ๆ”ฏๆŒ AND๏ผ‰๏ผŒไฟๅญ˜ๅˆฐ whereSQL ๅ’Œ paramsList ไธญ
    public void addWhereFields(Connection connection, List whereSQL, List paramsList) throws SQLException;
    }

    /**

    • @param updateSetInterface ่ฆไฟฎๆ”น็š„ๅญ—ๆฎตๅ’Œๅญ—ๆฎตๅ€ผ

    • @param whereIdInterface ไฟฎๆ”นๆปก่ถณ็š„ๆŸฅ่ฏขๆกไปถ

    • @return

    • @throws SQLException
      */
      public int update(UpdateSetInterface updateSetInterface, WhereIdInterface whereIdInterface) throws SQLException {

      // init query runner
      QueryRunner queryRunner = new QueryRunner();

      // get connection from transaction
      Connection connection = TransactionManager.getConnection();

      List paramsList = new ArrayList<>();
      List updateSetSQL = new ArrayList();
      List whereSQL = new ArrayList<>();

      StringBuilder sqlBuilder = new StringBuilder();
      sqlBuilder.append("UPDATE " + getTableName() + " SET ");

      updateSetInterface.addUpdateSetFields(connection, updateSetSQL, paramsList);

      String setString = buildSetSQL(updateSetSQL);
      if (setString == null) {
      // nothing to update???
      return 0;
      }

      // add update set string
      sqlBuilder.append(setString);

      // add update condition
      whereIdInterface.addWhereFields(connection, whereSQL, paramsList);

      // add where string
      if (whereSQL.size() > 0) {
      sqlBuilder.append(" WHERE ");
      sqlBuilder.append(buildWhereAndSQL(whereSQL));
      }

      // execute update
      String sql = sqlBuilder.toString();
      log.info(" " + sql + " , params=" + paramsList);
      int updates = queryRunner.update(connection, sql, paramsList.toArray());
      log.info(" " + getTableName() + " total " + updates + " updates");

      return updates;
      }

      // ๆ‰ง่กŒ SQL UPDATE ๆˆ–่€… DELETE ่ฏทๆฑ‚
      protected int executeUpdate(String sql, Object... params) throws SQLException {

      // init query runner
      QueryRunner queryRunner = new QueryRunner();
      
      // get connection from transaction
      Connection connection = TransactionManager.getConnection();
      
      log.info("<executeUpdate> " + sql);
      log.info("<executeUpdate>  params= " + Arrays.asList(params));
      int affected = queryRunner.update(connection, sql, params);
      log.info("<executeUpdate> " + getTableName() + " total " + affected + " affected");
      
      return affected;
      

      }

      // ๆ นๆฎ็ป™ๅฎš ID ๅˆ ้™ค่ฎฐๅฝ•
      protected int deleteById(String id) throws SQLException {

      // init query runner
      QueryRunner queryRunner = new QueryRunner();
      
      // get connection from transaction
      Connection connection = TransactionManager.getConnection();
      
      List<Object> paramsList = new ArrayList<>();
      List<String> whereSQL = new ArrayList<>();
      
      StringBuilder sqlBuilder = new StringBuilder();
      sqlBuilder.append("DELETE FROM " + getTableName());
      
      // add update condition
      addWhereValue(whereSQL, paramsList, getPrimaryKeyFieldName(), getPrimaryKeyFieldValue(id));
      
      // add where string
      if (whereSQL.size() > 0) {
          sqlBuilder.append(" WHERE ");
          sqlBuilder.append(buildWhereAndSQL(whereSQL));
      } else {
          // avoid deleteById ALL records...
          return 0;
      }
      
      // execute update
      String sql = sqlBuilder.toString();
      log.info("<deleteById> " + sql + " , id=" + id);
      int updates = queryRunner.update(connection, sql, paramsList.toArray());
      log.info("<deleteById> " + getTableName() + " total " + updates + " deleted");
      
      return updates;
      

      }

      // ๆŠŠๅญ—ๆฎตๅŠ ไธŠ่กจๅ๏ผŒ็”จไบŽ่”่กจๆŸฅ่ฏข
      public String prefixField(String fieldName) {
      return getTableName() + "." + fieldName;
      }

      // ๅ•ๅ€ผๆŸฅ่ฏข
      protected R queryOfSingleValue(String sql, Class returnTypeClass, Object... params) throws SQLException {

      if (StringUtil.isEmpty(sql)) {
          return null;
      }
      //ๅผ€ๅง‹ๅ‡†ๅค‡ๆ’ๅ…ฅๆ•ฐๆฎ
      
      log.info("<queryOfSingleValue>  sql=" + sql);
      // init query runner
      QueryRunner queryRunner = new QueryRunner();
      
      // get connection from transaction
      Connection connection = TransactionManager.getConnection();
      
      
      R result = queryRunner.query(connection, sql, new ScalarHandler<R>(1), params);
      log.info("<queryOfSingleValue>  " + getTableName() + " total " + result + " results");
      return result;
      

      }

      /**

      • ็”จไบŽๆž„้€ WHEREๅญๅฅ๏ผŒๅชๆ”ฏๆŒAND่ฟžๆŽฅ
      • ็”จๆณ•็คบไพ‹๏ผš
        *
      • WhereClauseBuilder where = new WhereClauseBuilder()
      •       .and(UserIncomeAudit.FIELD_STATUS, status)
        
      •       .and(UserIncomeAudit.FIELD_USER_NAME, username, WhereType.WHERE_LIKE);
        
      • return queryByCondition(where.getSql(), offset, limit, null, where.getParams());
      • Created by Vincent
        */
        protected class WhereClauseBuilder {
        private List fields = new ArrayList<>();
        private List params = new ArrayList<>();

        public WhereClauseBuilder() {}

        public WhereClauseBuilder and(String field, Object value) {
        addWhereValue(fields, params, field, value);
        return this;
        }

        public WhereClauseBuilder and(String field, Object value, WhereType whereType) {
        try {
        addWhereValue(fields, params, field, value, whereType);
        return this;
        } catch (SQLException e) {
        throw new RuntimeException(e);
        }
        }

        public String getSql() {
        if(fields == null || fields.isEmpty()) {
        return null;
        }
        return " WHERE " + buildWhereAndSQL(fields);
        }

        public Object[] getParams() {
        return params.toArray();
        }
        }
        }
        //
        // Source code recreated from a .class file by IntelliJ IDEA
        // (powered by Fernflower decompiler)
        //

        package org.apache.commons.dbutils;

        import java.sql.ResultSet;
        import java.sql.ResultSetMetaData;
        import java.sql.SQLException;
        import java.util.HashMap;
        import java.util.Iterator;
        import java.util.LinkedHashMap;
        import java.util.List;
        import java.util.Locale;
        import java.util.Map;
        import java.util.Map.Entry;
        import org.apache.commons.dbutils.BeanProcessor;
        import org.apache.commons.dbutils.RowProcessor;

        public class BasicRowProcessor implements RowProcessor {
        private static final BeanProcessor defaultConvert = new BeanProcessor();
        private static final BasicRowProcessor instance = new BasicRowProcessor();
        private final BeanProcessor convert;

        /** @deprecated */
        @Deprecated
        public static BasicRowProcessor instance() {
            return instance;
        }
        
        public BasicRowProcessor() {
            this(defaultConvert);
        }
        
        public BasicRowProcessor(BeanProcessor convert) {
            this.convert = convert;
        }
        
        public Object[] toArray(ResultSet rs) throws SQLException {
            ResultSetMetaData meta = rs.getMetaData();
            int cols = meta.getColumnCount();
            Object[] result = new Object[cols];
        
            for(int i = 0; i < cols; ++i) {
                result[i] = rs.getObject(i + 1);
            }
        
            return result;
        }
        
        public <T> T toBean(ResultSet rs, Class<T> type) throws SQLException {
            return this.convert.toBean(rs, type);
        }
        
        public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException {
            return this.convert.toBeanList(rs, type);
        }
        
        public Map<String, Object> toMap(ResultSet rs) throws SQLException {
            BasicRowProcessor.CaseInsensitiveHashMap result = new BasicRowProcessor.CaseInsensitiveHashMap();
            ResultSetMetaData rsmd = rs.getMetaData();
            int cols = rsmd.getColumnCount();
        
            for(int i = 1; i <= cols; ++i) {
                String columnName = rsmd.getColumnLabel(i);
                if(null == columnName || 0 == columnName.length()) {
                    columnName = rsmd.getColumnName(i);
                }
        
                result.put(columnName, rs.getObject(i));
            }
        
            return result;
        }
        
        private static class CaseInsensitiveHashMap extends LinkedHashMap<String, Object> {
            private final Map<String, String> lowerCaseMap;
            private static final long serialVersionUID = -2848100435296897392L;
        
            private CaseInsensitiveHashMap() {
                this.lowerCaseMap = new HashMap();
            }
        
            public boolean containsKey(Object key) {
                Object realKey = this.lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
                return super.containsKey(realKey);
            }
        
            public Object get(Object key) {
                Object realKey = this.lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
                return super.get(realKey);
            }
        
            public Object put(String key, Object value) {
                Object oldKey = this.lowerCaseMap.put(key.toLowerCase(Locale.ENGLISH), key);
                Object oldValue = super.remove(oldKey);
                super.put(key, value);
                return oldValue;
            }
        
            public void putAll(Map<? extends String, ?> m) {
                Iterator i$ = m.entrySet().iterator();
        
                while(i$.hasNext()) {
                    Entry entry = (Entry)i$.next();
                    String key = (String)entry.getKey();
                    Object value = entry.getValue();
                    this.put(key, value);
                }
        
            }
        
            public Object remove(Object key) {
                Object realKey = this.lowerCaseMap.remove(key.toString().toLowerCase(Locale.ENGLISH));
                return super.remove(realKey);
            }
        }
        

        }
        `

3.2.2 Release request

I have run the spring build with the cglib master including the fixes #65 and #66 and it finished correctly, so it would be good to have a cglib version out that is fully compatible with 3.2.0 and can be used in spring 4.2.x.

Thanks!

Change of code history

Hi,

I committed my last updates with a fresh work machine and my git config was not properly set up. I would ask you to please remove this data from the commit history as it contains some (now changed) workgroup codes from my work place which I would prefer to not have online. Really no idea how they ended up there, I might have copy-pasted something without noticing at some point.

You can do the changes as follows from the current state:

git rebase -i -p HEAD~2
(press insert in VIM, change puth lines to begin with 'e', escape, type ':wq' to save and close)
git commit --amend --author "Rafael Winterhalter <[email protected]>" 
(in VIM, press esape, type ':wq')
git rebase --continue
git commit --amend --author "Rafael Winterhalter <[email protected]>" 
(in VIM, press esape, type ':wq')
git rebase --continue
git push --force

Thank you and sorry for the extra work, I should know git better than that.

Source build issue

Hello,

I have been trying to build cglib but unit tests are failing. I checked the latest and tags/RELEASE_3_1 9b504bd

Is there any information on supported platforms?

Thanks!

test:
     [java] -- listing properties --
     [java] java.runtime.name=Java(TM) SE Runtime Environment
     [java] sun.boot.library.path=c:\tools\java\jdk1.7.0_55\jre\bin
     [java] java.vm.version=24.55-b03
     [java] cglib.debugLocation=C:\Users\bvarnai\cglib-debug
     [java] java.vm.vendor=Oracle Corporation
     [java] java.vendor.url=http://java.oracle.com/
     [java] path.separator=;
     [java] java.vm.name=Java HotSpot(TM) 64-Bit Server VM
     [java] file.encoding.pkg=sun.io
     [java] user.script=
     [java] user.country=US
     [java] sun.java.launcher=SUN_STANDARD
     [java] sun.os.patch.level=Service Pack 1
     [java] java.vm.specification.name=Java Virtual Machine Specification
     [java] user.dir=f:\ext\cglib
     [java] java.runtime.version=1.7.0_55-b13
     [java] java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
     [java] java.endorsed.dirs=c:\tools\java\jdk1.7.0_55\jre\lib\end...
     [java] os.arch=amd64
     [java] java.io.tmpdir=C:\Users\bvarnai\AppData\Local\Temp\
     [java] line.separator=
     [java]
     [java] java.vm.specification.vendor=Oracle Corporation
     [java] user.variant=
     [java] os.name=Windows 7
     [java] sun.jnu.encoding=Cp1252
     [java] java.library.path=c:\tools\java\jdk1.7.0_55\jre\bin;C:\...
     [java] java.specification.name=Java Platform API Specification
     [java] java.class.version=51.0
     [java] sun.management.compiler=HotSpot 64-Bit Tiered Compilers
     [java] os.version=6.1
     [java] user.home=C:\Users\bvarnai
     [java] user.timezone=
     [java] java.awt.printerjob=sun.awt.windows.WPrinterJob
     [java] file.encoding=Cp1252
     [java] java.specification.version=1.7
     [java] user.name=bvarnai
     [java] java.class.path=f:\ext\cglib\build\proxy\classes;f:\e...
     [java] java.vm.specification.version=1.7
     [java] sun.arch.data.model=64
     [java] java.home=c:\tools\java\jdk1.7.0_55\jre
     [java] sun.java.command=net.sf.cglib.TestAll net.sf.cglib.Tes...
     [java] java.specification.vendor=Oracle Corporation
     [java] user.language=en
     [java] awt.toolkit=sun.awt.windows.WToolkit
     [java] java.vm.info=mixed mode
     [java] java.version=1.7.0_55
     [java] java.ext.dirs=c:\tools\java\jdk1.7.0_55\jre\lib\ext...
     [java] sun.boot.class.path=c:\tools\java\jdk1.7.0_55\jre\lib\res...
     [java] java.vendor=Oracle Corporation
     [java] file.separator=\
     [java] java.vendor.url.bug=http://bugreport.sun.com/bugreport/
     [java] sun.cpu.endian=little
     [java] sun.io.unicode.encoding=UnicodeLittle
     [java] sun.desktop=windows
     [java] sun.cpu.isalist=amd64
     [java] CGLIB debugging enabled, writing to 'C:\Users\bvarnai\cglib-debug'
     [java] Failed to invoke suite():java.lang.VerifyError: Expecting a stackmap frame at branch target 36
     [java] Exception Details:
     [java]   Location:
     [java]     net/sf/cglib/transform/impl/TestProvideFields.getField(Ljava/lang/String;)Ljava/lang/Object; @6: tableswitch
     [java]   Reason:
     [java]     Expected stackmap frame at this location.
     [java]   Bytecode:
     [java]     0000000: 2a2b 59b6 0066 aa00 0000 001e 05ce a0fa
     [java]     0000010: 05ce a0fa 0000 0012 121a b600 6a99 0008
     [java]     0000020: b400 13b0 57bb 006c 5912 6eb7 006f bf
     [java]

Cache related issue with class definitions

Hi,

Since CGLIB 3.2.1+ (including 3.2.3) I experience the following error:

net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:332)
    at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:445)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:85)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:83)
    at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
    at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:108)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:282)
    at net.sf.cglib.proxy.Enhancer.nextInstance(Enhancer.java:643)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:286)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:433)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:304)
    at org.apache.wicket.jmx.Initializer.createProxy(Initializer.java:295)
    at org.apache.wicket.jmx.Initializer.register(Initializer.java:249)
    at org.apache.wicket.jmx.Initializer.init(Initializer.java:192)
    at org.apache.wicket.Application.initInitializers(Application.java:568)
    at org.apache.wicket.Application.initApplication(Application.java:776)
    at org.apache.wicket.protocol.http.WicketFilter.init(WicketFilter.java:431)
    at org.apache.wicket.protocol.http.WicketFilter.init(WicketFilter.java:355)
    at org.eclipse.jetty.servlet.FilterHolder.initialize(FilterHolder.java:137)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:856)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:346)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1380)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1342)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:772)
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:259)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:518)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:405)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:106)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:372)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.apache.wicket.examples.StartExamples.main(StartExamples.java:110)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:409)
    at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:323)
    ... 36 more
Caused by: java.lang.LinkageError: loader (instance of  org/eclipse/jetty/webapp/WebAppClassLoader): attempted  duplicate class definition for name: "org/apache/wicket/jmx/Application"
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    ... 42 more

There is no such error with 3.2.0.
The CGLIB related code that is involved is https://github.com/apache/wicket/blob/7973959f169a1c44c1de18a6acde21c8b926d64c/wicket-jmx/src/main/java/org/apache/wicket/jmx/Initializer.java#L256-L294

Any idea what could be the reason ?

ReflectUtils breaks with Java 9 build 148+

Since Java 9 build 148, it is no longer possible to do setAccessible on any public Java runtime API class (except sun.misc.Unsafe as special case). This affects ClassLoader#defineClass (protected method).

Because of this any mocking library (Mockito, EasyMock,...) that uses CGLIB breaks with ExceptionOnInitializer.

Example in Apache Solr (Mockito/Easymock):

   [junit4] ERROR   0.38s J2 | TestManagedSchemaThreadSafety.testThreadSafety <<<
   [junit4]    > Throwable #1: java.lang.ExceptionInInitializerError
   [junit4]    >        at __randomizedtesting.SeedInfo.seed([8E654E5E1F32A757:142F5A06CCAD15A1]:0)
   [junit4]    >        at org.mockito.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:167)
   [junit4]    >        at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
   [junit4]    >        at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
   [junit4]    >        at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
   [junit4]    >        at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117)
   [junit4]    >        at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109)
   [junit4]    >        at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105)
   [junit4]    >        at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70)
   [junit4]    >        at org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass(ClassImposterizer.java:85)
   [junit4]    >        at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
   [junit4]    >        at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
   [junit4]    >        at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
   [junit4]    >        at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
   [junit4]    >        at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
   [junit4]    >        at org.mockito.Mockito.mock(Mockito.java:1243)
   [junit4]    >        at org.apache.solr.schema.TestManagedSchemaThreadSafety.createZkController(TestManagedSchemaThreadSafety.java:135)
   [junit4]    >        at org.apache.solr.schema.TestManagedSchemaThreadSafety.testThreadSafety(TestManagedSchemaThreadSafety.java:118)
   [junit4]    >        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   [junit4]    >        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
   [junit4]    >        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   [junit4]    >        at java.base/java.lang.reflect.Method.invoke(Method.java:538)
   [junit4]    >        at java.base/java.lang.Thread.run(Thread.java:844)
   [junit4]    > Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @4cbd6df7
   [junit4]    >        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:207)
   [junit4]    >        at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:192)
   [junit4]    >        at java.base/java.lang.reflect.Method.setAccessible(Method.java:186)
   [junit4]    >        at org.mockito.cglib.core.ReflectUtils$2.run(ReflectUtils.java:57)
   [junit4]    >        at java.base/java.security.AccessController.doPrivileged(Native Method)
   [junit4]    >        at org.mockito.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:47)
   [junit4]    >        ... 55 more
   [junit4]   2> 64469 INFO  (SUITE-TestManagedSchemaThreadSafety-seed#[8E654E5E1F32A757]-worker) [    ] o.a.s.c.ZkTestServer connecting to 127.0.0.1:51648 51648
   [junit4]   2> 64474 INFO  (Thread-158) [    ] o.a.s.c.ZkTestServer connecting to 127.0.0.1:51648 51648
   [junit4]   2> 64478 INFO  (SUITE-TestManagedSchemaThreadSafety-seed#[8E654E5E1F32A757]-worker) [    ] o.a.s.SolrTestCaseJ4 ###deleteCore
   [junit4]   2> NOTE: leaving temporary files on disk at: C:\Users\Uwe Schindler\Projects\lucene\trunk-lusolr1\solr\build\solr-core\test\J2\temp\solr.schema.TestManagedSchemaThreadSafety_8E654E5E1F32A757-001
   [junit4]   2> Dez. 26, 2016 8:47:14 NACHM. com.carrotsearch.randomizedtesting.ThreadLeakControl checkThreadLeaks
   [junit4]   2> WARNUNG: Will linger awaiting termination of 2 leaked thread(s).
   [junit4]   2> NOTE: test params are: codec=Lucene70, sim=RandomSimilarity(queryNorm=false): {}, locale=so-KE, timezone=Etc/GMT+4
   [junit4]   2> NOTE: Windows 10 10.0 amd64/Oracle Corporation 9-ea (64-bit)/cpus=4,threads=1,free=188820656,total=266338304
   [junit4]   2> NOTE: All tests run in this JVM: [TestRandomFaceting, TestCharFilters, BlockJoinFacetSimpleTest, SolrCmdDistributorTest, TestTolerantUpdateProcessorRandomCloud, TestManagedSchemaThreadSafety]
   [junit4] Completed [31/670 (1!)] on J2 in 0.83s, 1 test, 1 error <<< FAILURES!

I have no idea why CGLib needs to do this (instead of just subclassing ClassLoader). I have the feeling that mocking libs need to "inject" classes into existing classloaders, so the workaround is needed.

A trick to solve this might be using MethodHandles instead of Reflection using a "temporary" child class of ClassLoader (just to get a MethodHandle to the defineClass method). But this would require minimum Java 7. I may provide a PR to do this.

More example for proxy support for constructor class with Enhancer ?

Hi, cglib team. I encountered some problem when make proxy support towards the bean with constructor params. e.g when I want to some proxy usecases towards jedis (framework integration with redis server). here comes my code like this with enhancer:

public T getInstance(T target, Class[] args, Object[] argsValue) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return (T) enhancer.create(args, argsValue);
}

the target is jedis like this:
public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommands, AdvancedJedisCommands, ScriptingCommands {
public Jedis(final String host) {
super(host);
}

public Jedis(final String host, final int port) {
super(host, port);
}

public Jedis(final String host, final int port, final int timeout) {
super(host, port, timeout);
}

public Jedis(JedisShardInfo shardInfo) {
super(shardInfo);
}

public Jedis(URI uri) {
super(uri);
}
//omitted

}

when I want to proxy jedis, the constructor for such is for such
public Jedis(final String host, final int port, final int timeout) {
super(host, port, timeout);
}

so here comes the class info and arguments comes like this
Class[] args = new Class[] {String.class, Integer.class, Integer.class};

Object[] arguments = new Object[] {jedis.getClient().getHost(), jedis.getClient().getPort(),
jedis.getClient().getTimeout()};

if such above is not wrong, the cglib will help to create the proxy class with enhancer. but here comes my exception stracktrace:
Caused by: java.lang.NoSuchMethodException: redis.clients.jedis.Jedis$$EnhancerByCGLIB$$e2ffdb0f.(java.lang.String, java.lang.Integer, java.lang.Integer)
at java.lang.Class.getConstructor0(Class.java:2902)
at java.lang.Class.getDeclaredConstructor(Class.java:2066)
at net.sf.cglib.core.ReflectUtils.getConstructor(ReflectUtils.java:244)
... 14 more

I don't know the reason and whether I was wrong. hope someone could point out my mistake with cglib.

Can not add value to the dynamic class with the mixed attribute name

I use Cglib to get the dynamic class and assigent values to all attribute of class.But I find that the mixed attribution name , ex 'N5AME','D4AY' , this attribute names have a number # in the second position of string , a bad result will be got.
# net.sf.cglib.beans.beanMap
# public Object put(Object key, Object value) {
return put(bean, key, value);
}

this method will return null ,so I can't add value to the dynamic class
this is custom CglibBean to create dynamic class and get/set atrribute value:
CglibBean.txt
this is junit test:
junit.txt
the result:
junit

Finally, I find that when attribute name like '5NAME','NA5ME','NAM5E','NAME5', the junit test will get the value and I can conclude the result that I have successfully valution to the dynamic class.
ex:
junit2
I wander what's happen in the Cglib. Can you give me answer pls.

Avoid reflection in setCallbacksHelper

Under concurrent load lots of threads end up with the following stacktrace.

It looks like using a simple interface for CGLIB$SET_THREAD_CALLBACKS / CGLIB$SET_STATIC_CALLBACKS, etc, etc would improve performance/scalability.

"cglib.BeansBenchmark.newInstance-jmh-worker-1" #11 daemon prio=5 os_prio=31 tid=0x00007fd814112000 nid=0x5a03 runnable [0x00007000017de000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.String.intern(Native Method)
    at java.lang.Class.searchMethods(Class.java:3003)
    at java.lang.Class.getDeclaredMethod(Class.java:2128)
    at net.sf.cglib.proxy.Enhancer.getCallbacksSetter(Enhancer.java:639)
    at net.sf.cglib.proxy.Enhancer.setCallbacksHelper(Enhancer.java:627)
    at net.sf.cglib.proxy.Enhancer.setThreadCallbacks(Enhancer.java:621)
    at net.sf.cglib.proxy.Enhancer.createUsingReflection(Enhancer.java:643)
    at net.sf.cglib.proxy.Enhancer.firstInstance(Enhancer.java:547)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:254)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:376)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:284)
    at net.sf.cglib.samples.Beans.newInstance(Beans.java:33)
    at cglib.BeansBenchmark.newInstance(BeansBenchmark.java:23)
    at cglib.generated.BeansBenchmark_newInstance_jmhTest.newInstance_avgt_jmhStub(BeansBenchmark_newInstance_jmhTest.java:163)
    at cglib.generated.BeansBenchmark_newInstance_jmhTest.newInstance_AverageTime(BeansBenchmark_newInstance_jmhTest.java:128)
    at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:430)
    at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:412)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

About the Cglib dynamic proxy generate subclass

Hello,

I tried to use setting DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, and got the .class files that Cglib generated. I used decomplier to see the classfile, but I can not get all of the generated source code. Would you please send me a demo about the generated code or something else .

Thank you!

Switch to maven build system

Please state your opinion on maven as build/dependency system.

Maven might simplify IDE setup and build process.

JavaFX properties enhancing

Hi!

I'm trying to enhance a SimpleStringProperty (javafx properties has been included to java 8) using the master branch (java 8 support) but I got this error :

Caused by: java.lang.ClassNotFoundException: net.sf.cglib.proxy.Factory

Just doing this:

SimpleStringProperty prop = (SimpleStringProperty) Enhancer.create(SimpleStringProperty.class,new Beans()); // Where Beans is the cglib sample one

Any idea?

Thank you in advance for your help!

EDIT: I tried using a custom class which extend the SimpleStringProperty and it works in this case. :/

class MyStringProperty extends SimpleStringProperty{
}
MyStringProperty prop = (MyStringProperty) Enhancer.create(MyStringProperty.class,new Beans());

Why the second case works?

Thank you

question

how i can find another proxymethod inside the invoker?

i m calling getA but
i might call setA in the super class

jdk 7+ Enhancer.getMethods (guice)

I use JDK 6 with Guice 2 (cglib also naturally) in my project.
When I want to migrate to jdk 8 and Guice 4, I have a strange problem, hmhm I suspect higher jdk and cglib 3.2.0 (asm 5.x)

I prepared simple application for this case. cglib-test

The problem is Enhancer.getMethods(....)

For JDK 6 Enhancer returns one methods with my annotations (AnnotationFirst,AnnotationSecond)

public cglib.domain.SomeResponse cglib.SimpleHandler.handle(cglib.domain.SomeRequest) [@cglib.inter.anon.AnnotationFirst(), @cglib.inter.anon.AnnotationSecond()]
public cglib.domain.ResponseAbstract cglib.SimpleHandler.handle(cglib.domain.GenericRequest) []
.......
.......

For higher JDK (7+) Enhancer returns magic two methods :/

public cglib.domain.SomeResponse cglib.SimpleHandler.handle(cglib.domain.SomeRequest) [@cglib.inter.anon.AnnotationFirst(), @cglib.inter.anon.AnnotationSecond()]
public cglib.domain.ResponseAbstract cglib.SimpleHandler.handle(cglib.domain.GenericRequest) [@cglib.inter.anon.AnnotationFirst(), @cglib.inter.anon.AnnotationSecond()]
.......
.......

Is this normal behavior cglib?

As a consequence, Guice creates two net.sf.cglib.proxy.Callback and double call each intereceptor.

Regression when using javax.tools.JavaCompiler

In CGLib 3.2.0 I was able to generate a subclass from a class that was compiled using javax.tools.JavaCompiler, but in 3.2.1 it's no longer possible. I've put a small project up on GitHub to reproduce it: https://github.com/jqno/cglib-javax-compiler-issue

The pom now points to CGLib 3.2.1 and the test fails, but if you change it to 3.2.0, the test passes.

Come to think of it, this issue is pretty ridiculous: combining 2 different ways of generating code... But it comes from a real project :). This issue is not high priority for me, though. I'll stick with 3.2.0 for now.

Cglib 3.1 naming policy does not allow to override with custom class name.

My code looks something like below ,API allow to override the class name , this code was working fine in older version of CGLIB2.1 .

I used to pass classname with appended "_" .
"className+ Constants.HIBERNATE_PERSISTENT_CLASS_SUFFIX); "

     // tell the enhancer to use the provided class name
    enhancer.setNamingPolicy(new InterceptorNamingPolicy(subclassName));

it works fine in cglib 2.1 , but after upgrading to cglib 3.1 i get the below exception .

it works fine it i do with defaultnamingpolicy and comment out the above line .
/// enhancer.setNamingPolicy(new InterceptorNamingPolicy(subclassName));

Error Stack ๐Ÿ‘

net.sf.cglib.core.CodeGenerationException: java.lang.NoSuchMethodException-->com.splwg.base.domain.common.message.ServerMessageFactory_Impl__.(java.lang.Class)
at net.sf.cglib.core.ReflectUtils.getConstructor(ReflectUtils.java:248)
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:220)
at net.sf.cglib.reflect.FastClass$Generator.firstInstance(FastClass.java:76)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:225)
at net.sf.cglib.reflect.FastClass$Generator.create(FastClass.java:64)
at net.sf.cglib.proxy.MethodProxy.helper(MethodProxy.java:121)
at net.sf.cglib.proxy.MethodProxy.init(MethodProxy.java:74)
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:226)
at com.splwg.base.support.interception.BusinessMethodInterceptor.intercept(BusinessMethodInterceptor.java:84)
at com.splwg.base.domain.common.message.ServerMessageFactory_Impl__.createMessage()
at com.splwg.base.api.changehandling.ServerMessageTemplate.createServerMessage(ServerMessageTemplate.java:99)
at com.splwg.base.api.changehandling.ServerMessageTemplate.createServerMessage(ServerMessageTemplate.java:117)
at com.splwg.base.api.changehandling.RestrictRule.privateThrowError(RestrictRule.java:418)
at com.splwg.base.api.changehandling.RestrictRule.handleWhenConditionalsAreTrue(RestrictRule.java:400)
at com.splwg.base.support.changehandlers.AbstractValidationRule.applyRule(AbstractValidationRule.java:88)
at com.splwg.base.support.changehandlers.ChangeEventHandler.applyRule(ChangeEventHandler.java:321)
at com.splwg.base.support.changehandlers.ChangeEventHandler.access$2(ChangeEventHandler.java:318)
at com.splwg.base.support.changehandlers.ChangeEventHandler$2.run(ChangeEventHandler.java:242)
at com.splwg.base.support.changehandlers.ChangeEventHandler$JumpToChangeHandlerRunner.run(ChangeEventHandler.java:370)
at com.splwg.base.support.interception.SessionInterceptionManager.notifyGenericCallStackJump(SessionInterceptionManager.java:296)
at com.splwg.base.support.context.FrameworkSession.notifyGenericCallStackJump(FrameworkSession.java:2182)
at com.splwg.base.support.changehandlers.ChangeEventHandler.executeValidation(ChangeEventHandler.java:247)
at com.splwg.base.support.changehandlers.SessionChangeManager.fireEagerValidations(SessionChangeManager.java:164)
at com.splwg.base.support.changehandlers.SessionChangeManager.fireEvents(SessionChangeManager.java:113)
at com.splwg.base.support.changehandlers.SessionChangeManager.setDTOCalled(SessionChangeManager.java:67)
at com.splwg.base.support.context.FrameworkSession.setDTOCalled(FrameworkSession.java:1238)
at com.splwg.base.support.api.AbstractBusinessEntity.completeSetAbstractDTO(AbstractBusinessEntity.java:167)
at com.splwg.base.domain.common.script.Script_Per.completeSetAbstractDTO(Script_Per.java:418)
at com.splwg.base.support.context.FrameworkSession.createBusinessEntity(FrameworkSession.java:1541)
at com.splwg.base.support.impl.AbstractDataTransferObject$1.run(AbstractDataTransferObject.java:78)
at com.splwg.base.support.impl.AbstractDataTransferObject$JumpFromDTORunner.run(AbstractDataTransferObject.java:172)
at com.splwg.base.support.interception.SessionInterceptionManager.notifyGenericCallStackJump(SessionInterceptionManager.java:296)
at com.splwg.base.support.context.FrameworkSession.notifyGenericCallStackJump(FrameworkSession.java:2182)
at com.splwg.base.support.impl.AbstractDataTransferObject.abstractNewEntity(AbstractDataTransferObject.java:84)
at com.splwg.base.domain.common.script.Script_DTO.newEntity(Script_DTO.java:268)
at com.splwg.base.domain.common.script.Script_Test.testEligibilityOptionForBPAScript(Script_Test.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at junit.framework.TestCase.runTest(TestCase.java:164)
at com.splwg.base.api.testers.TestCase.runTest(TestCase.java:39)
at com.splwg.base.api.testers.ApplicationComponentTestCase.runTest(ApplicationComponentTestCase.java:181)
at com.splwg.base.api.testers.AbstractEntityTestCase.runTest(AbstractEntityTestCase.java:64)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at com.splwg.base.api.testers.TestCase.run(TestCase.java:26)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:131)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NoSuchMethodException: com.splwg.base.domain.common.message.ServerMessageFactory_Impl__.(java.lang.Class)
at java.lang.Class.getConstructor0(Class.java:2849)
at java.lang.Class.getDeclaredConstructor(Class.java:2053)
at net.sf.cglib.core.ReflectUtils.getConstructor(ReflectUtils.java:244)
... 55 more

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.