Skip to content

Commit 79069e5

Browse files
committed
HHH-19372 Test and fix IAE for AccessOptimizer bridge superclasses
1 parent f106717 commit 79069e5

File tree

1 file changed

+40
-42
lines changed

1 file changed

+40
-42
lines changed

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

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.util.ArrayList;
1717
import java.util.Arrays;
1818
import java.util.Collections;
19-
import java.util.Iterator;
2019
import java.util.List;
2120
import java.util.Map;
2221
import java.util.concurrent.Callable;
@@ -282,13 +281,13 @@ public ReflectionOptimizer getReflectionOptimizer(
282281
}
283282
}
284283

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

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

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

333-
final String className = foreignPackageClassInfo.clazz.getName() + "$" + OPTIMIZER_PROXY_BRIDGE_NAMING_SUFFIX + encodeName( foreignPackageClassInfo.propertyNames, foreignPackageClassInfo.getters, foreignPackageClassInfo.setters );
310+
final String className = bridgeMembersClassInfo.clazz.getName() + "$" + OPTIMIZER_PROXY_BRIDGE_NAMING_SUFFIX + encodeName( bridgeMembersClassInfo.propertyNames, bridgeMembersClassInfo.getters, bridgeMembersClassInfo.setters );
334311
superClass = byteBuddyState.load(
335-
foreignPackageClassInfo.clazz,
312+
bridgeMembersClassInfo.clazz,
336313
className,
337314
(byteBuddy, namingStrategy) -> {
338315
DynamicType.Builder<?> builder = byteBuddy.with( namingStrategy ).subclass( newSuperClass );
339-
for ( Member getter : foreignPackageClassInfo.getters ) {
316+
for ( Member getter : bridgeMembersClassInfo.getters ) {
340317
final Class<?> getterType;
341318
if ( getter instanceof Field ) {
342319
getterType = ( (Field) getter ).getType();
@@ -352,7 +329,7 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] pro
352329
),
353330
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
354331
)
355-
.withParameter( foreignPackageClassInfo.clazz )
332+
.withParameter( bridgeMembersClassInfo.clazz )
356333
.intercept(
357334
new Implementation.Simple(
358335
new GetFieldOnArgument(
@@ -361,7 +338,7 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] pro
361338
)
362339
);
363340
}
364-
for ( Member setter : foreignPackageClassInfo.setters ) {
341+
for ( Member setter : bridgeMembersClassInfo.setters ) {
365342
final Class<?> setterType;
366343
if ( setter instanceof Field ) {
367344
setterType = ( (Field) setter ).getType();
@@ -375,7 +352,7 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] pro
375352
TypeDescription.Generic.VOID,
376353
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
377354
)
378-
.withParameter( foreignPackageClassInfo.clazz )
355+
.withParameter( bridgeMembersClassInfo.clazz )
379356
.withParameter( setterType )
380357
.intercept(
381358
new Implementation.Simple(
@@ -393,10 +370,10 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] pro
393370
for ( int j = 0; j < getters.length; j++ ) {
394371
final Member getter = getters[j];
395372
final Member setter = setters[j];
396-
if ( foreignPackageClassInfo.getters.contains( getter ) ) {
373+
if ( bridgeMembersClassInfo.getters.contains( getter ) ) {
397374
getters[j] = new ForeignPackageMember( superClass, getter );
398375
}
399-
if ( foreignPackageClassInfo.setters.contains( setter ) ) {
376+
if ( bridgeMembersClassInfo.setters.contains( setter ) ) {
400377
setters[j] = new ForeignPackageMember( superClass, setter );
401378
}
402379
}
@@ -620,16 +597,37 @@ private boolean is64BitType(Class<?> type) {
620597
}
621598
}
622599

623-
private List<ForeignPackageClassInfo> createForeignPackageClassInfos(Class<?> clazz) {
624-
final List<ForeignPackageClassInfo> foreignPackageClassInfos = new ArrayList<>();
600+
private List<BridgeMembersClassInfo> createBridgeMembersClassInfos(
601+
Class<?> clazz,
602+
Member[] getters,
603+
Member[] setters,
604+
String[] propertyNames) {
605+
final List<BridgeMembersClassInfo> bridgeMembersClassInfos = new ArrayList<>();
625606
Class<?> c = clazz.getSuperclass();
626607
while (c != Object.class) {
627-
if ( !c.getPackageName().equals( clazz.getPackageName() ) ) {
628-
foreignPackageClassInfos.add( new ForeignPackageClassInfo( c ) );
608+
final BridgeMembersClassInfo bridgeMemberClassInfo = new BridgeMembersClassInfo( c );
609+
for ( int i = 0; i < getters.length; i++ ) {
610+
final Member getter = getters[i];
611+
final Member setter = setters[i];
612+
boolean found = false;
613+
if ( getter.getDeclaringClass() == c && !Modifier.isPublic( getter.getModifiers() ) ) {
614+
bridgeMemberClassInfo.getters.add( getter );
615+
found = true;
616+
}
617+
if ( setter.getDeclaringClass() == c && !Modifier.isPublic( setter.getModifiers() ) ) {
618+
bridgeMemberClassInfo.setters.add( setter );
619+
found = true;
620+
}
621+
if ( found ) {
622+
bridgeMemberClassInfo.propertyNames.add( propertyNames[i] );
623+
}
624+
}
625+
if ( !bridgeMemberClassInfo.propertyNames.isEmpty() ) {
626+
bridgeMembersClassInfos.add( bridgeMemberClassInfo );
629627
}
630628
c = c.getSuperclass();
631629
}
632-
return foreignPackageClassInfos;
630+
return bridgeMembersClassInfos;
633631
}
634632

635633
public ByteBuddyProxyHelper getByteBuddyProxyHelper() {

0 commit comments

Comments
 (0)