AvailableSettings.BYTECODE_PROVIDER and compile-time bytecode instrumentation

Hi,

I am using hibernate-enhance-maven-plugin with the following options:

          <enableLazyInitialization>true</enableLazyInitialization>
          <enableDirtyTracking>true</enableDirtyTracking>
          <enableAssociationManagement>false</enableAssociationManagement>
          <enableExtendedEnhancement>false</enableExtendedEnhancement>

And I noticed that when I create the SessionFactory, a lot of time is spent doing some runtime bytecode instrumentation of my entity classes. I discovered AvailableSettings.BYTECODE_PROVIDER and the fact that it could be set to Environment.BYTECODE_PROVIDER_NAME_NONE to disable this runtime bytecode instrumentation.

I would like to know what is the link between those two functionalities, if the runtime instrumentation was redundant and if not, what was the impact of disabling this runtime bytecode instrumentation?

Thank you very much!

If you do enhancement at build time, then the runtime enhancement is redundant. Can you share an example project that reproduces this issue?

Can you share an example project that reproduces this issue?

Do you mean that I shouldn’t have to do anything manually and it’s not normal that I experienced both compile and runtime bytecode enhancement?

If yes, then I will try to reproduce it. The project I am working on is very complex as you may suspect, and also for now is running on Hibernate 5, I’m in the progress of migrating to v6, so once it can at least run, I will try to see if 1) the situation appears and 2) how to reproduce it.

The enhancer should detect very quickly that a class is already enhanced and hence skip further operations, so if you’re seeing a lot of activity at runtime due to enhancement, then that might indicate a problem.

1 Like

Hey @beikov, I did a bit more investigation (still on Hibernate 5) and I would like to understand better about the concepts of Proxy Factory versus Bytecode Enhancer to be sure I’m not confused.

I kind of intuit that Bytecode Enhancer should not be called during initialization if enhancement already happened at build time, but is the Proxy Factory meant to be generated at runtime in this case? I can see a lot of runtime spent in ByteBuddyProxyFactory#postInstantiate (called by PojoEntityTuplizer#buildProxyFactory) but maybe it’s normal actually?

It will be called, but will quite immediately if the class is already enhanced.

Since you’re on ORM 5, you probably didn’t enable the hibernate.enhancer.enableLazyInitialization setting, so yes, in that case, building the proxy factory and runtime proxies is expected. With ORM 6, the enhancer enables this setting by default, but not in ORM 5.

Since you’re on ORM 5, you probably didn’t enable the hibernate.enhancer.enableLazyInitialization setting, so yes, in that case, building the proxy factory and runtime proxies is expected.

Actually as mentioned at the top of this thread, this option is enabled. So it is not normal that the proxy factory and runtime proxies are built?

They should be already existing from the compile-time bytecode enhancement, right?

If I disable the bytecode provide (set it to none), how can I easily validate (ideally with a test, or at worst using debug) that things are working as expected? I’m imagining maybe fetching an entity with lazy fields and then testing the type of the field?

I guess the explanation can be found here: hibernate-orm/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java at 5.6.15 · hibernate/hibernate-orm · GitHub

Is there any good reason that this was commented out? What happens if I use the bytecode provider “none”? Are things going to break?

It’s hard to say, ORM 5.6 is very old by now and only receives limited support. I don’t think that using the bytecode provider “none” is a problem.

Ok, thank you for your insights. The few testing I did seems to show that it’s indeed not a problem.

Can you just tell me if I understand correctly what are those proxies about:

  • when using compile time bytecode enhancement, no proxies are meant to be used at runtime because it’s the enhanced methods for each field (the one with $$ in their name) that take care of doing the lazy loading of the field
  • when not using compile time bytecode enhancement, proxies are used to replace whole entities so that they can do lazy loading of their fields

I will come back once I migrated to Hibernate 6 to see if there is anything that can be improved on that matter (or to confirm it works as expected already :slight_smile:)