Skip to content

HHH-20256 Make ByteBuddy bytecode generation reproducible#11982

Open
gsmet wants to merge 1 commit intohibernate:mainfrom
gsmet:fix-reproducibility
Open

HHH-20256 Make ByteBuddy bytecode generation reproducible#11982
gsmet wants to merge 1 commit intohibernate:mainfrom
gsmet:fix-reproducibility

Conversation

@gsmet
Copy link
Member

@gsmet gsmet commented Mar 16, 2026

By using a fixed suffix for everything generated by Hibernate ORM. This will allow for reproducible builds.

Note that the resulting name still has an additional suffix which is related to the current element. Usually, it's a hashCode representing the element, hashCode that is stable from builds to builds.

@beikov @mbellade @yrodiere if we decide to go with this one, I would very much appreciate if we could backport it to the version that will land in upcoming Quarkus. If it is deemed safe enough, of course.

https://hibernate.atlassian.net/browse/HHH-20256


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.



Please make sure that the following tasks are completed:
Tasks specific to HHH-20256 (Improvement):

  • Add tests for feature/improvement
  • Update documentation as relevant: javadoc for changed API, documentation/src/main/asciidoc/userguide for all features, documentation/src/main/asciidoc/introduction for main features, links from existing documentation
  • Add entries as relevant to migration-guide.adoc (breaking changes) and whats-new.adoc (new features/improvements)

@gsmet gsmet marked this pull request as draft March 16, 2026 13:10
@gsmet
Copy link
Member Author

gsmet commented Mar 16, 2026

Actually, I found another issue regarding the order in which the methods are implemented, I need to see how we can fix that.

@gsmet
Copy link
Member Author

gsmet commented Mar 16, 2026

I created an issue in ByteBuddy for the additional issues I spotted as I think the fixes should live there: raphw/byte-buddy#1890 .

@gsmet gsmet force-pushed the fix-reproducibility branch from 90305d0 to e69ef5c Compare March 16, 2026 16:56
Comment on lines +78 to +84
byteBuddy = new ByteBuddy( classFileVersion )
.with( TypeValidation.DISABLED )
// we use a fixed suffix to make sure our builds are reproducible
// ByteBuddy uses a random suffix by default to be extremely safe
// in case the class is instrumented multiple times
// but in our case, we can use a common suffix affected to Hibernate ORM
.with( new Implementation.Context.Default.Factory.WithFixedSuffix( "hibernate" ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely remember @beikov or @dreab8 adding deterministic suffixes in some area related to bytebuddy at some point, though I'm not sure this is related to what you're doing. I'd rather they have a look before we merge this, because I think this caused some trouble...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and the fix #10192

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah so from what I have seen the original PR was: https://github.com/hibernate/hibernate-orm/pull/9848/changes .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICS, we apply a fixed name in every non-deprecated code path. I see that org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper#buildUnloadedProxy(net.bytebuddy.pool.TypePool, net.bytebuddy.description.type.TypeDefinition, java.util.Collection<? extends net.bytebuddy.description.type.TypeDefinition>) has a comment, that it is used by Quarkus, but even that uses a fixed name.

Can you share the code paths that produce random names so I can better understand what is going on? Chances are that Quarkus is just using deprecated methods and should switch to the newer methods now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the pull request, it looks like the change they did was a lot more involved that what I'm trying to achieve here.

If I'm not mistaken tests were added after the report and all tests are green with this PR.

Copy link
Member

@yrodiere yrodiere Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share the code paths that produce random names so I can better understand what is going on? Chances are that Quarkus is just using deprecated methods and should switch to the newer methods now.

Not sure about the code paths, but the issue description shows the symptoms:

https://media-cdn.atlassian.com/file/f42440ea-b72e-455b-9f5e-49f7fe105cd0/image/cdn?allowAnimated=true&client=bc4cc5d9-ef6e-4ffe-8632-435f44e01e9e&collection=&height=125&max-age=2592000&mode=full-fit&source=mediaCard&token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJiYzRjYzVkOS1lZjZlLTRmZmUtODYzMi00MzVmNDRlMDFlOWUiLCJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpmaWxlOmY0MjQ0MGVhLWI3MmUtNDU1Yi05ZjVlLTQ5ZjdmZTEwNWNkMCI6WyJyZWFkIl19LCJleHAiOjE3NzM4MjY3NDcsIm5iZiI6MTc3MzgyNTg0NywiYWFJZCI6IjU1NzA1ODo1OGZhMWNlZC0xNzFhLTRjMDAtOTdlOC01ZDcwZDQ0MmNjNGIiLCJodHRwczovL2lkLmF0bGFzc2lhbi5jb20vYXBwQWNjcmVkaXRlZCI6ZmFsc2V9.rU1O79YjlHOQyaWiRoF0Y0UHPr-BO7vcAaWHM8wQaQI&width=686

I think this is a different problem then: @beikov made sure the name of proxy classes is stable, while @gsmet is making sure the name of fields within proxy classes is stable.

If I'm not mistaken tests were added after the report and all tests are green with this PR.

Good. Then if you're certain this "fixed suffix" thing will only affect proxy internals, and we won't end up with unwanted suffixes in e.g. bytecode-enhanced accessors (the generated $$_hibernate_read_myProperty() methods)... I suppose it's safe?

It would feel slightly safer to just add this .with( new Implementation.Context.Default.Factory.WithFixedSuffix( "hibernate" ) ) inside org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper#proxyBuilder, but maybe I'm worrying too much.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, after looking into the ByteBuddy code, it seems that this name only affects cached accessors and field values, which was not clear to me when looking at this. Might be worth spelling this out in the comment. Can you please make that clarification @gsmet?

By using a fixed suffix for everything generated by Hibernate ORM.
This will allow for reproducible builds.

Note that the resulting name still has an additional suffix which is
related to the current element. Usually, it's a hashCode representing
the element, hashCode that is stable from builds to builds.
@gsmet gsmet force-pushed the fix-reproducibility branch from e69ef5c to 82f1000 Compare March 17, 2026 18:03
@gsmet gsmet marked this pull request as ready for review March 18, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants