Skip to content

Commit 09b6bf8

Browse files
committed
HHH-19372 Test and fix IAE for AccessOptimizer bridge superclasses
1 parent 4d75316 commit 09b6bf8

File tree

1 file changed

+79
-83
lines changed

1 file changed

+79
-83
lines changed

hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java

Lines changed: 79 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.util.ArrayList;
1515
import java.util.Arrays;
1616
import java.util.Collections;
17-
import java.util.Iterator;
1817
import java.util.List;
1918
import java.util.Map;
2019
import java.util.concurrent.Callable;
@@ -281,13 +280,13 @@ public ReflectionOptimizer getReflectionOptimizer(
281280
}
282281
}
283282

284-
private static class ForeignPackageClassInfo {
283+
private static class BridgeMembersClassInfo {
285284
final Class<?> clazz;
286285
final List<String> propertyNames = new ArrayList<>();
287286
final List<Member> getters = new ArrayList<>();
288287
final List<Member> setters = new ArrayList<>();
289288

290-
public ForeignPackageClassInfo(Class<?> clazz) {
289+
public BridgeMembersClassInfo(Class<?> clazz) {
291290
this.clazz = clazz;
292291
}
293292
}
@@ -296,99 +295,81 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] pro
296295
if ( clazz.isInterface() ) {
297296
return Object.class;
298297
}
299-
// generate access optimizer super classes for foreign package super classes that declare fields
298+
// generate access optimizer super classes for super classes that declare members requiring bridge methods
300299
// each should declare protected static methods get_FIELDNAME(OWNER)/set_FIELDNAME(OWNER, TYPE)
301300
// which should be called then from within GetPropertyValues/SetPropertyValues
302301
// Since these super classes will be in the correct package, the package-private entity field access is fine
303-
final List<ForeignPackageClassInfo> foreignPackageClassInfos = createForeignPackageClassInfos( clazz );
304-
for ( Iterator<ForeignPackageClassInfo> iterator = foreignPackageClassInfos.iterator(); iterator.hasNext(); ) {
305-
final ForeignPackageClassInfo foreignPackageClassInfo = iterator.next();
306-
for ( int i = 0; i < getters.length; i++ ) {
307-
final Member getter = getters[i];
308-
final Member setter = setters[i];
309-
boolean found = false;
310-
if ( getter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( getter.getModifiers() ) ) {
311-
foreignPackageClassInfo.getters.add( getter );
312-
found = true;
313-
}
314-
if ( setter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( setter.getModifiers() ) ) {
315-
foreignPackageClassInfo.setters.add( setter );
316-
found = true;
317-
}
318-
if ( found ) {
319-
foreignPackageClassInfo.propertyNames.add( propertyNames[i] );
320-
}
321-
}
322-
if ( foreignPackageClassInfo.getters.isEmpty() && foreignPackageClassInfo.setters.isEmpty() ) {
323-
iterator.remove();
324-
}
325-
}
302+
final List<BridgeMembersClassInfo> bridgeMembersClassInfos = createBridgeMembersClassInfos( clazz, getters, setters, propertyNames );
326303

327304
Class<?> superClass = Object.class;
328-
for ( int i = foreignPackageClassInfos.size() - 1; i >= 0; i-- ) {
329-
final ForeignPackageClassInfo foreignPackageClassInfo = foreignPackageClassInfos.get( i );
305+
for ( int i = bridgeMembersClassInfos.size() - 1; i >= 0; i-- ) {
306+
final BridgeMembersClassInfo bridgeMembersClassInfo = bridgeMembersClassInfos.get( i );
330307
final Class<?> newSuperClass = superClass;
331308

332-
final String className = foreignPackageClassInfo.clazz.getName() + "$" + OPTIMIZER_PROXY_BRIDGE_NAMING_SUFFIX + encodeName( foreignPackageClassInfo.propertyNames, foreignPackageClassInfo.getters, foreignPackageClassInfo.setters );
309+
final String className = bridgeMembersClassInfo.clazz.getName() + "$" + OPTIMIZER_PROXY_BRIDGE_NAMING_SUFFIX + encodeName( bridgeMembersClassInfo.propertyNames, bridgeMembersClassInfo.getters, bridgeMembersClassInfo.setters );
333310
superClass = byteBuddyState.load(
334-
foreignPackageClassInfo.clazz,
311+
bridgeMembersClassInfo.clazz,
335312
className,
336313
(byteBuddy, namingStrategy) -> {
337314
DynamicType.Builder<?> builder = byteBuddy.with( namingStrategy ).subclass( newSuperClass );
338-
for ( Member getter : foreignPackageClassInfo.getters ) {
339-
final Class<?> getterType;
340-
if ( getter instanceof Field field ) {
341-
getterType = field.getType();
342-
}
343-
else if ( getter instanceof Method method ) {
344-
getterType = method.getReturnType();
345-
}
315+
for ( Member getter : bridgeMembersClassInfo.getters ) {
316+
if ( !Modifier.isPublic( getter.getModifiers() ) ) {
317+
final Class<?> getterType;
318+
if ( getter instanceof Field field ) {
319+
getterType = field.getType();
320+
}
321+
else if ( getter instanceof Method method ) {
322+
getterType = method.getReturnType();
323+
}
346324
else {
347325
throw new AssertionFailure( "Unexpected member" + getter );
348326
}
349327

350-
builder = builder.defineMethod(
351-
"get_" + getter.getName(),
352-
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(
353-
getterType
354-
),
355-
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
356-
)
357-
.withParameter( foreignPackageClassInfo.clazz )
358-
.intercept(
359-
new Implementation.Simple(
360-
new GetFieldOnArgument(
361-
getter
362-
)
363-
)
364-
);
365-
}
366-
for ( Member setter : foreignPackageClassInfo.setters ) {
367-
final Class<?> setterType;
368-
if ( setter instanceof Field field ) {
369-
setterType = field.getType();
370-
}
371-
else if ( setter instanceof Method method ) {
372-
setterType = method.getParameterTypes()[0];
328+
builder = builder.defineMethod(
329+
"get_" + getter.getName(),
330+
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(
331+
getterType
332+
),
333+
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
334+
)
335+
.withParameter( bridgeMembersClassInfo.clazz )
336+
.intercept(
337+
new Implementation.Simple(
338+
new GetFieldOnArgument(
339+
getter
340+
)
341+
)
342+
);
373343
}
344+
}
345+
for ( Member setter : bridgeMembersClassInfo.setters ) {
346+
if ( !Modifier.isPublic( setter.getModifiers() ) ) {
347+
final Class<?> setterType;
348+
if ( setter instanceof Field field ) {
349+
setterType = field.getType();
350+
}
351+
else if ( setter instanceof Method method ) {
352+
setterType = method.getParameterTypes()[0];
353+
}
374354
else {
375355
throw new AssertionFailure( "Unexpected member" + setter );
376356
}
377357

378-
builder = builder.defineMethod(
379-
"set_" + setter.getName(),
380-
TypeDescription.Generic.VOID,
381-
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
382-
)
383-
.withParameter( foreignPackageClassInfo.clazz )
384-
.withParameter( setterType )
385-
.intercept(
386-
new Implementation.Simple(
387-
new SetFieldOnArgument(
388-
setter
389-
)
390-
)
391-
);
358+
builder = builder.defineMethod(
359+
"set_" + setter.getName(),
360+
TypeDescription.Generic.VOID,
361+
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
362+
)
363+
.withParameter( bridgeMembersClassInfo.clazz )
364+
.withParameter( setterType )
365+
.intercept(
366+
new Implementation.Simple(
367+
new SetFieldOnArgument(
368+
setter
369+
)
370+
)
371+
);
372+
}
392373
}
393374

394375
return builder;
@@ -398,10 +379,10 @@ else if ( setter instanceof Method method ) {
398379
for ( int j = 0; j < getters.length; j++ ) {
399380
final Member getter = getters[j];
400381
final Member setter = setters[j];
401-
if ( foreignPackageClassInfo.getters.contains( getter ) ) {
382+
if ( bridgeMembersClassInfo.getters.contains( getter ) && !Modifier.isPublic( getter.getModifiers() ) ) {
402383
getters[j] = new ForeignPackageMember( superClass, getter );
403384
}
404-
if ( foreignPackageClassInfo.setters.contains( setter ) ) {
385+
if ( bridgeMembersClassInfo.setters.contains( setter ) && !Modifier.isPublic( setter.getModifiers() ) ) {
405386
setters[j] = new ForeignPackageMember( superClass, setter );
406387
}
407388
}
@@ -623,16 +604,31 @@ private boolean is64BitType(Class<?> type) {
623604
}
624605
}
625606

626-
private List<ForeignPackageClassInfo> createForeignPackageClassInfos(Class<?> clazz) {
627-
final List<ForeignPackageClassInfo> foreignPackageClassInfos = new ArrayList<>();
607+
private List<BridgeMembersClassInfo> createBridgeMembersClassInfos(
608+
Class<?> clazz,
609+
Member[] getters,
610+
Member[] setters,
611+
String[] propertyNames) {
612+
final List<BridgeMembersClassInfo> bridgeMembersClassInfos = new ArrayList<>();
628613
Class<?> c = clazz.getSuperclass();
629614
while (c != Object.class) {
630-
if ( !c.getPackageName().equals( clazz.getPackageName() ) ) {
631-
foreignPackageClassInfos.add( new ForeignPackageClassInfo( c ) );
615+
final BridgeMembersClassInfo bridgeMemberClassInfo = new BridgeMembersClassInfo( c );
616+
for ( int i = 0; i < getters.length; i++ ) {
617+
final Member getter = getters[i];
618+
final Member setter = setters[i];
619+
if ( getter.getDeclaringClass() == c && !Modifier.isPublic( getter.getModifiers() )
620+
|| setter.getDeclaringClass() == c && !Modifier.isPublic( setter.getModifiers() ) ) {
621+
bridgeMemberClassInfo.getters.add( getter );
622+
bridgeMemberClassInfo.setters.add( setter );
623+
bridgeMemberClassInfo.propertyNames.add( propertyNames[i] );
624+
}
625+
}
626+
if ( !bridgeMemberClassInfo.propertyNames.isEmpty() ) {
627+
bridgeMembersClassInfos.add( bridgeMemberClassInfo );
632628
}
633629
c = c.getSuperclass();
634630
}
635-
return foreignPackageClassInfos;
631+
return bridgeMembersClassInfos;
636632
}
637633

638634
public ByteBuddyProxyHelper getByteBuddyProxyHelper() {

0 commit comments

Comments
 (0)