[jboss-jira] [JBoss JIRA] (JASSIST-233) Hibernate entity getId method not proxied - different behavior in Win and Linux

Rafał Figas (JIRA) issues at jboss.org
Fri Sep 19 09:18:03 EDT 2014


     [ https://issues.jboss.org/browse/JASSIST-233?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Rafał Figas updated JASSIST-233:
--------------------------------
    Description: 
First of all I am sorry for the quality of this entry - there will be no test case as the problem is a little bit odd and I am unable to produce a test case. However there is some issue so I am attaching everything I got, maybe someone with more experience in bytecode manipulation will find actual problem. OK, lets get to the point.

Problem seems to be close to this one:
https://issues.jboss.org/browse/JASSIST-187
I have downloaded the test case from that entry, made a test and it works just fine.

The problem
There are:
* class pl.frati.moray.dm.impl.recruitmentpoint.RecruitmentPointImpl (lets call it B for short)
* class pl.frati.moray.dm.impl.helper.EntityWithId<Integer> (lets call it A for short)
* class pl.frati.moray.dm.impl.recruitmentpoint.RecruitingSchoolImpl (lets call it C for short)
* class pl.frati.moray.dm.impl.recruitmentpoint.OfferedGroupImpl (lets call it D for short)

Classes B and C both extend A. Class A provides getId() method which is inherited by B and C.

Classes B, C and D are mapped with Hibernate. D has many-to-one with C and C has many-to-one with B. Configuration of those relations are default what means that classes are proxied.

Calling D.getC().getId() works well - proper ID value is returned.
Calling D.getC().getB().getId() does not work - ID value is null.
Calling D.getC().getB().getName() works fine - value is returned.
Calling:
Session.get('B', bId);
D.getC().getB().getId() - works fine, probably because it was loaded from session cache and was not proxied.

It happens ONLY with jar is compiled with linux Java compiler. When compiled with Windows compiler everything works fine. It does not matter which linux compiler - I've tried couple Java 6 compilers and Java 7 compilers (Oracle or OpenJDK).

What I was able to research:
# Problem appears only with Javassist higher then 3.15.0. With Javassist 3.15.0 it works fine. Hibernate version seems to have no matter, as I have tried:
* Hibernate 4.2.7 with Javassist 3.15.0 - it works fine
* Hibernate 4.2.7 with Javassist 3.18.2 - not working
* Hibernate higher than 4.2.7 including 4.2.15 and 4.3.6 with Javassist 3.18.2 (this Hibernate does not work with 3.15.0) - not working
# I have run the debugger in all cases. 
* Hibernate 4.2.7 with Javassist 3.15.0 - method getId() for class B is proxied - method find2Methods (AFAIR) is called and properly delegated
* Hibernate 4.2.7 with Javassist 3.18.2 - method getId() for class B is NOT proxied - it is called directly on B instance which has all properties set to null, but the name suggests it has been proxied (javassist addition in name). And what is strange, because those classes has exactly the same inheritance and very similar construction - method getId() for C object IS proxied and proper value is returned. Also nothe that method getName() on class B is also properly proxied.

So, summarizing it seems that there is some difference between compilation result between windows and linux. I attach both resulting JARs to this entry. As you can see .class file sizes differ as well for problematic B class. It seems that this difference causes that B class is not correctly proxied - it is somewhat proxied, because getName() method works fine and the name in the debugger is modified by Javassist, but getId() method does not work properly. Unfortunately it is not easy to repeat the problem - I could not find that difference between B and C and when I tried I could not repeat this problem on side, that is why I attach a JAR form actual project. I hope you will be able to analyze bytecode differencies and fix this problem.

For those who have bad luck to run on this problem there are at least two workarounds I've found:
# change your mapping turning off proxying in many-to-one for problematic class. Be careful with this - memory usage will probably increase and speed will drop down.
# add getId() method to problematic class simply calling: return super.getId() - this fixes Javassist instrumentation.


  was:
First of all I am sorry for the quality of this entry - there will be no test case as the problem is a little bit odd and I am unable to produce a test case. However there is some issue so I am attaching everything I got, maybe someone with more experience in bytecode manipulation will find actual problem. OK, lets get to the point.

Problem seems to be close to this one:
https://issues.jboss.org/browse/JASSIST-187
I have downloaded the test case from that entry, made a test and it works just fine.

The problem
There are:
* class pl.frati.moray.dm.impl.recruitmentpoint.RecruitmentPointImpl (lets call it B for short)
* class pl.frati.moray.dm.impl.helper.EntityWithId<Integer> (lets call it A for short)
* class pl.frati.moray.dm.impl.recruitmentpoint.RecruitingSchoolImpl (lets call it C for short)
* class pl.frati.moray.dm.impl.recruitmentpoint.OfferedGroupImpl (lets call it D for short)

Classes B and C both extend A. Class A provides getId() method which is inherited by B and C.

Classes B, C and D are mapped with Hibernate. D has many-to-one with C and C has many-to-one with B. Configuration of those relations are default what means that classes are proxied.

Calling D.getC().getId() works well - proper ID value is returned.
Calling D.getC().getB().getId() does not work - ID value is null.
Calling D.getC().getB().getName() works fine - value is returned.
Calling:
Session.get('B', bId);
D.getC().getB().getId() - works fine, probably because it was loaded from session cache and was not proxied.

It happens ONLY with jar is compiled with linux Java compiler. When compiled with Windows compiler everything works fine. It does not matter which linux compiler - I've tried couple Java 6 compilers and Java 7 compilers (Oracle or OpenJDK).

What I was able to research:
# Problem appears only with Javassist higher then 3.15.0. With Javassist 3.15.0 it works fine. Hibernate version seems to have no matter, as I have tried:
* Hibernate 4.2.7 with Javassist 3.15.0 - it works fine
* Hibernate 4.2.7 with Javassist 3.18.2 - not working
* Hibernate higher than 4.2.7 including 4.2.15 and 4.3.6 with Javassist 3.18.2 (this Hibernate does not work with 3.15.0) - not working

# I have run the debugger in all cases. 
* Hibernate 4.2.7 with Javassist 3.15.0 - method getId() for class B is proxied - method find2Methods (AFAIR) is called and properly delegated
* Hibernate 4.2.7 with Javassist 3.18.2 - method getId() for class B is NOT proxied - it is called directly on B instance which has all properties set to null, but the name suggests it has been proxied (javassist addition in name). And what is strange, because those classes has exactly the same inheritance and very similar construction - method getId() for C object IS proxied and proper value is returned. Also nothe that method getName() on class B is also properly proxied.

So, summarizing it seems that there is some difference between compilation result between windows and linux. I attach both resulting JARs to this entry. As you can see .class file sizes differ as well for problematic B class. It seems that this difference causes that B class is not correctly proxied - it is somewhat proxied, because getName() method works fine and the name in the debugger is modified by Javassist, but getId() method does not work properly. Unfortunately it is not easy to repeat the problem - I could not find that difference between B and C and when I tried I could not repeat this problem on side, that is why I attach a JAR form actual project. I hope you will be able to analyze bytecode differencies and fix this problem.

For those who have bad luck to run on this problem there are at least two workarounds I've found:
# change your mapping turning off proxying in many-to-one for problematic class. Be careful with this - memory usage will probably increase and speed will drop down.
# add getId() method to problematic class simply calling: return super.getId() - this fixes Javassist instrumentation.




> Hibernate entity getId method not proxied - different behavior in Win and Linux
> -------------------------------------------------------------------------------
>
>                 Key: JASSIST-233
>                 URL: https://issues.jboss.org/browse/JASSIST-233
>             Project: Javassist
>          Issue Type: Bug
>    Affects Versions: 3.16.0-GA, 3.16.1-GA, 3.17.0-GA, 3.17.1-GA, 3.18.0-GA, 3.18.1-GA, 3.18.2-GA
>            Reporter: Rafał Figas
>            Assignee: Shigeru Chiba
>
> First of all I am sorry for the quality of this entry - there will be no test case as the problem is a little bit odd and I am unable to produce a test case. However there is some issue so I am attaching everything I got, maybe someone with more experience in bytecode manipulation will find actual problem. OK, lets get to the point.
> Problem seems to be close to this one:
> https://issues.jboss.org/browse/JASSIST-187
> I have downloaded the test case from that entry, made a test and it works just fine.
> The problem
> There are:
> * class pl.frati.moray.dm.impl.recruitmentpoint.RecruitmentPointImpl (lets call it B for short)
> * class pl.frati.moray.dm.impl.helper.EntityWithId<Integer> (lets call it A for short)
> * class pl.frati.moray.dm.impl.recruitmentpoint.RecruitingSchoolImpl (lets call it C for short)
> * class pl.frati.moray.dm.impl.recruitmentpoint.OfferedGroupImpl (lets call it D for short)
> Classes B and C both extend A. Class A provides getId() method which is inherited by B and C.
> Classes B, C and D are mapped with Hibernate. D has many-to-one with C and C has many-to-one with B. Configuration of those relations are default what means that classes are proxied.
> Calling D.getC().getId() works well - proper ID value is returned.
> Calling D.getC().getB().getId() does not work - ID value is null.
> Calling D.getC().getB().getName() works fine - value is returned.
> Calling:
> Session.get('B', bId);
> D.getC().getB().getId() - works fine, probably because it was loaded from session cache and was not proxied.
> It happens ONLY with jar is compiled with linux Java compiler. When compiled with Windows compiler everything works fine. It does not matter which linux compiler - I've tried couple Java 6 compilers and Java 7 compilers (Oracle or OpenJDK).
> What I was able to research:
> # Problem appears only with Javassist higher then 3.15.0. With Javassist 3.15.0 it works fine. Hibernate version seems to have no matter, as I have tried:
> * Hibernate 4.2.7 with Javassist 3.15.0 - it works fine
> * Hibernate 4.2.7 with Javassist 3.18.2 - not working
> * Hibernate higher than 4.2.7 including 4.2.15 and 4.3.6 with Javassist 3.18.2 (this Hibernate does not work with 3.15.0) - not working
> # I have run the debugger in all cases. 
> * Hibernate 4.2.7 with Javassist 3.15.0 - method getId() for class B is proxied - method find2Methods (AFAIR) is called and properly delegated
> * Hibernate 4.2.7 with Javassist 3.18.2 - method getId() for class B is NOT proxied - it is called directly on B instance which has all properties set to null, but the name suggests it has been proxied (javassist addition in name). And what is strange, because those classes has exactly the same inheritance and very similar construction - method getId() for C object IS proxied and proper value is returned. Also nothe that method getName() on class B is also properly proxied.
> So, summarizing it seems that there is some difference between compilation result between windows and linux. I attach both resulting JARs to this entry. As you can see .class file sizes differ as well for problematic B class. It seems that this difference causes that B class is not correctly proxied - it is somewhat proxied, because getName() method works fine and the name in the debugger is modified by Javassist, but getId() method does not work properly. Unfortunately it is not easy to repeat the problem - I could not find that difference between B and C and when I tried I could not repeat this problem on side, that is why I attach a JAR form actual project. I hope you will be able to analyze bytecode differencies and fix this problem.
> For those who have bad luck to run on this problem there are at least two workarounds I've found:
> # change your mapping turning off proxying in many-to-one for problematic class. Be careful with this - memory usage will probably increase and speed will drop down.
> # add getId() method to problematic class simply calling: return super.getId() - this fixes Javassist instrumentation.



--
This message was sent by Atlassian JIRA
(v6.3.1#6329)



More information about the jboss-jira mailing list