-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HHH-18011 Extract DefaultEnhancerClassFileLocator and allow using a d…
…ifferent implementation
- Loading branch information
Showing
7 changed files
with
337 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
...te-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/CoreTypePool.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Hibernate, Relational Persistence for Idiomatic Java | ||
* | ||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. | ||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. | ||
*/ | ||
package org.hibernate.bytecode.enhance.internal.bytebuddy; | ||
|
||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.pool.TypePool; | ||
|
||
/** | ||
* A TypePool which only loads, and caches, types whose package | ||
* name starts with certain chosen prefixes. | ||
* The default is to only load classes whose package names start with | ||
* either "jakarta." or "java.". | ||
* This allows to reuse these caches independently from application | ||
* code and classloader changes, as during enhancement we frequently | ||
* encounter such symbols as well, for example triggered by JPA annotations | ||
* or properties mapped via standard java types and collections. | ||
* Symbols resolved by this pool are backed by loaded classes from | ||
* ORM's classloader. | ||
*/ | ||
public class CoreTypePool extends TypePool.AbstractBase implements TypePool { | ||
|
||
private final ClassLoader hibernateClassLoader = CoreTypePool.class.getClassLoader(); | ||
private final ConcurrentHashMap<String, Resolution> resolutions = new ConcurrentHashMap<>(); | ||
private final String[] acceptedPrefixes; | ||
|
||
/** | ||
* Construct a new {@link CoreTypePool} with its default configuration: | ||
* to only load classes whose package names start with either "jakarta." | ||
* or "java." | ||
*/ | ||
public CoreTypePool() { | ||
//By default optimise for jakarta annotations, and java util collections | ||
this("jakarta.", "java."); | ||
} | ||
|
||
/** | ||
* Construct a new {@link CoreTypePool} with a choice of which prefixes | ||
* for fully qualified classnames will be loaded by this {@link TypePool}. | ||
*/ | ||
public CoreTypePool(final String... acceptedPrefixes) { | ||
//While we implement a cache in this class we also want to enable | ||
//ByteBuddy's default caching mechanism as it will cache the more | ||
//useful output of the parsing and introspection of such types. | ||
super( new TypePool.CacheProvider.Simple() ); | ||
this.acceptedPrefixes = acceptedPrefixes; | ||
} | ||
|
||
private boolean isCoreClassName(final String name) { | ||
for ( String acceptedPrefix : this.acceptedPrefixes ) { | ||
if ( name.startsWith( acceptedPrefix ) ) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
protected Resolution doDescribe(final String name) { | ||
if ( isCoreClassName( name ) ) { | ||
final Resolution resolution = resolutions.get( name ); | ||
if ( resolution != null ) { | ||
return resolution; | ||
} | ||
else { | ||
//We implement this additional layer of caching, which is on top of | ||
//ByteBuddy's default caching, so as to prevent resolving the same | ||
//types concurrently from the classloader. | ||
//This is merely an efficiency improvement and will NOT provide a | ||
//strict guarantee of symbols being resolved exactly once as there | ||
//is no SPI within ByteBuddy which would allow this: the point is to | ||
//make it exceptionally infrequent, which greatly helps with | ||
//processing of large models. | ||
return resolutions.computeIfAbsent( name, this::actualResolve ); | ||
} | ||
} | ||
else { | ||
//These are not cached to not leak references to application code names | ||
return new Resolution.Illegal( name ); | ||
} | ||
} | ||
|
||
private Resolution actualResolve(final String name) { | ||
try { | ||
final Class<?> aClass = Class.forName( name, false, hibernateClassLoader ); | ||
return new TypePool.Resolution.Simple( TypeDescription.ForLoadedType.of( aClass ) ); | ||
} | ||
catch ( ClassNotFoundException e ) { | ||
return new Resolution.Illegal( name ); | ||
} | ||
} | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
...src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerClassLocator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Hibernate, Relational Persistence for Idiomatic Java | ||
* | ||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. | ||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. | ||
*/ | ||
package org.hibernate.bytecode.enhance.internal.bytebuddy; | ||
|
||
import net.bytebuddy.dynamic.ClassFileLocator; | ||
import net.bytebuddy.pool.TypePool; | ||
|
||
/** | ||
* Extends the TypePool contract of ByteBuddy with our additional needs. | ||
*/ | ||
public interface EnhancerClassLocator extends TypePool { | ||
|
||
/** | ||
* Register a new class to the locator explicitly. | ||
* @param className | ||
* @param originalBytes | ||
*/ | ||
void registerClassNameAndBytes(String className, byte[] originalBytes); | ||
|
||
/** | ||
* This can optionally be used to remove an explicit mapping when it's no longer | ||
* essential to retain it. | ||
* The underlying implementation might ignore the operation. | ||
* @param className | ||
*/ | ||
void deregisterClassNameAndBytes(String className); | ||
|
||
/** | ||
* @return the underlying {@link ClassFileLocator} | ||
*/ | ||
ClassFileLocator asClassFileLocator(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.