Skip to content

Commit e7bcbb4

Browse files
committed
HHH-19372 Test and fix IAE for AccessOptimizer bridge superclasses
1 parent 2852852 commit e7bcbb4

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
@@ -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,93 +296,75 @@ 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 ) {
340-
final Class<?> getterType;
341-
if ( getter instanceof Field ) {
342-
getterType = ( (Field) getter ).getType();
343-
}
344-
else {
345-
getterType = ( (Method) getter ).getReturnType();
316+
for ( Member getter : bridgeMembersClassInfo.getters ) {
317+
if ( !Modifier.isPublic( getter.getModifiers() ) ) {
318+
final Class<?> getterType;
319+
if ( getter instanceof Field ) {
320+
getterType = ( (Field) getter ).getType();
321+
}
322+
else {
323+
getterType = ( (Method) getter ).getReturnType();
324+
}
325+
326+
builder = builder.defineMethod(
327+
"get_" + getter.getName(),
328+
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(
329+
getterType
330+
),
331+
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
332+
)
333+
.withParameter( bridgeMembersClassInfo.clazz )
334+
.intercept(
335+
new Implementation.Simple(
336+
new GetFieldOnArgument(
337+
getter
338+
)
339+
)
340+
);
346341
}
347-
348-
builder = builder.defineMethod(
349-
"get_" + getter.getName(),
350-
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(
351-
getterType
352-
),
353-
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
354-
)
355-
.withParameter( foreignPackageClassInfo.clazz )
356-
.intercept(
357-
new Implementation.Simple(
358-
new GetFieldOnArgument(
359-
getter
360-
)
361-
)
362-
);
363342
}
364-
for ( Member setter : foreignPackageClassInfo.setters ) {
365-
final Class<?> setterType;
366-
if ( setter instanceof Field ) {
367-
setterType = ( (Field) setter ).getType();
368-
}
369-
else {
370-
setterType = ( (Method) setter ).getParameterTypes()[0];
343+
for ( Member setter : bridgeMembersClassInfo.setters ) {
344+
if ( !Modifier.isPublic( setter.getModifiers() ) ) {
345+
final Class<?> setterType;
346+
if ( setter instanceof Field ) {
347+
setterType = ( (Field) setter ).getType();
348+
}
349+
else {
350+
setterType = ( (Method) setter ).getParameterTypes()[0];
351+
}
352+
353+
builder = builder.defineMethod(
354+
"set_" + setter.getName(),
355+
TypeDescription.Generic.VOID,
356+
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
357+
)
358+
.withParameter( bridgeMembersClassInfo.clazz )
359+
.withParameter( setterType )
360+
.intercept(
361+
new Implementation.Simple(
362+
new SetFieldOnArgument(
363+
setter
364+
)
365+
)
366+
);
371367
}
372-
373-
builder = builder.defineMethod(
374-
"set_" + setter.getName(),
375-
TypeDescription.Generic.VOID,
376-
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
377-
)
378-
.withParameter( foreignPackageClassInfo.clazz )
379-
.withParameter( setterType )
380-
.intercept(
381-
new Implementation.Simple(
382-
new SetFieldOnArgument(
383-
setter
384-
)
385-
)
386-
);
387368
}
388369

389370
return builder;
@@ -393,10 +374,10 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] pro
393374
for ( int j = 0; j < getters.length; j++ ) {
394375
final Member getter = getters[j];
395376
final Member setter = setters[j];
396-
if ( foreignPackageClassInfo.getters.contains( getter ) ) {
377+
if ( bridgeMembersClassInfo.getters.contains( getter ) && !Modifier.isPublic( getter.getModifiers() ) ) {
397378
getters[j] = new ForeignPackageMember( superClass, getter );
398379
}
399-
if ( foreignPackageClassInfo.setters.contains( setter ) ) {
380+
if ( bridgeMembersClassInfo.setters.contains( setter ) && !Modifier.isPublic( setter.getModifiers() ) ) {
400381
setters[j] = new ForeignPackageMember( superClass, setter );
401382
}
402383
}
@@ -620,16 +601,31 @@ private boolean is64BitType(Class<?> type) {
620601
}
621602
}
622603

623-
private List<ForeignPackageClassInfo> createForeignPackageClassInfos(Class<?> clazz) {
624-
final List<ForeignPackageClassInfo> foreignPackageClassInfos = new ArrayList<>();
604+
private List<BridgeMembersClassInfo> createBridgeMembersClassInfos(
605+
Class<?> clazz,
606+
Member[] getters,
607+
Member[] setters,
608+
String[] propertyNames) {
609+
final List<BridgeMembersClassInfo> bridgeMembersClassInfos = new ArrayList<>();
625610
Class<?> c = clazz.getSuperclass();
626611
while (c != Object.class) {
627-
if ( !c.getPackageName().equals( clazz.getPackageName() ) ) {
628-
foreignPackageClassInfos.add( new ForeignPackageClassInfo( c ) );
612+
final BridgeMembersClassInfo bridgeMemberClassInfo = new BridgeMembersClassInfo( c );
613+
for ( int i = 0; i < getters.length; i++ ) {
614+
final Member getter = getters[i];
615+
final Member setter = setters[i];
616+
if ( getter.getDeclaringClass() == c && !Modifier.isPublic( getter.getModifiers() )
617+
|| setter.getDeclaringClass() == c && !Modifier.isPublic( setter.getModifiers() ) ) {
618+
bridgeMemberClassInfo.getters.add( getter );
619+
bridgeMemberClassInfo.setters.add( setter );
620+
bridgeMemberClassInfo.propertyNames.add( propertyNames[i] );
621+
}
622+
}
623+
if ( !bridgeMemberClassInfo.propertyNames.isEmpty() ) {
624+
bridgeMembersClassInfos.add( bridgeMemberClassInfo );
629625
}
630626
c = c.getSuperclass();
631627
}
632-
return foreignPackageClassInfos;
628+
return bridgeMembersClassInfos;
633629
}
634630

635631
public ByteBuddyProxyHelper getByteBuddyProxyHelper() {

0 commit comments

Comments
 (0)