Skip to content

Commit a563384

Browse files
beikovmbellade
authored andcommitted
HHH-19372 Test and fix IAE for AccessOptimizer bridge superclasses
1 parent bcbd691 commit a563384

File tree

1 file changed

+84
-82
lines changed

1 file changed

+84
-82
lines changed

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

Lines changed: 84 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import java.util.ArrayList;
1616
import java.util.Arrays;
1717
import java.util.Collections;
18-
import java.util.Iterator;
1918
import java.util.List;
2019
import java.util.Map;
2120

@@ -236,9 +235,9 @@ public ReflectionOptimizer getReflectionOptimizer(
236235
return null;
237236
}
238237

239-
Class<?> superClass = determineAccessOptimizerSuperClass( clazz, getters, setters );
240-
241238
final String[] propertyNames = propertyAccessMap.keySet().toArray( new String[0] );
239+
final Class<?> superClass = determineAccessOptimizerSuperClass( clazz, propertyNames, getters, setters );
240+
242241
final Class<?> bulkAccessor = byteBuddyState.load( clazz, byteBuddy -> byteBuddy
243242
.with( new NamingStrategy.SuffixingRandom(
244243
OPTIMIZER_PROXY_NAMING_SUFFIX,
@@ -265,106 +264,94 @@ public ReflectionOptimizer getReflectionOptimizer(
265264
}
266265
}
267266

268-
private static class ForeignPackageClassInfo {
267+
private static class BridgeMembersClassInfo {
269268
final Class<?> clazz;
269+
final List<String> propertyNames = new ArrayList<>();
270270
final List<Member> getters = new ArrayList<>();
271271
final List<Member> setters = new ArrayList<>();
272272

273-
public ForeignPackageClassInfo(Class<?> clazz) {
273+
public BridgeMembersClassInfo(Class<?> clazz) {
274274
this.clazz = clazz;
275275
}
276276
}
277277

278-
private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, Member[] getters, Member[] setters) {
278+
private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, String[] propertyNames, Member[] getters, Member[] setters) {
279279
if ( clazz.isInterface() ) {
280280
return Object.class;
281281
}
282-
// generate access optimizer super classes for foreign package super classes that declare fields
282+
// generate access optimizer super classes for super classes that declare members requiring bridge methods
283283
// each should declare protected static methods get_FIELDNAME(OWNER)/set_FIELDNAME(OWNER, TYPE)
284284
// which should be called then from within GetPropertyValues/SetPropertyValues
285285
// Since these super classes will be in the correct package, the package-private entity field access is fine
286-
final List<ForeignPackageClassInfo> foreignPackageClassInfos = createForeignPackageClassInfos( clazz );
287-
for ( Iterator<ForeignPackageClassInfo> iterator = foreignPackageClassInfos.iterator(); iterator.hasNext(); ) {
288-
final ForeignPackageClassInfo foreignPackageClassInfo = iterator.next();
289-
for ( int i = 0; i < getters.length; i++ ) {
290-
final Member getter = getters[i];
291-
final Member setter = setters[i];
292-
if ( getter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( getter.getModifiers() ) ) {
293-
foreignPackageClassInfo.getters.add( getter );
294-
}
295-
if ( setter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( setter.getModifiers() ) ) {
296-
foreignPackageClassInfo.setters.add( setter );
297-
}
298-
}
299-
if ( foreignPackageClassInfo.getters.isEmpty() && foreignPackageClassInfo.setters.isEmpty() ) {
300-
iterator.remove();
301-
}
302-
}
286+
final List<BridgeMembersClassInfo> bridgeMembersClassInfos = createBridgeMembersClassInfos( clazz, getters, setters, propertyNames );
303287

304288
Class<?> superClass = Object.class;
305-
for ( int i = foreignPackageClassInfos.size() - 1; i >= 0; i-- ) {
306-
final ForeignPackageClassInfo foreignPackageClassInfo = foreignPackageClassInfos.get( i );
289+
for ( int i = bridgeMembersClassInfos.size() - 1; i >= 0; i-- ) {
290+
final BridgeMembersClassInfo bridgeMembersClassInfo = bridgeMembersClassInfos.get( i );
307291
final Class<?> newSuperClass = superClass;
308292

309-
final String suffix = OPTIMIZER_PROXY_BRIDGE_NAMING_SUFFIX + encodeName( foreignPackageClassInfo.propertyNames, foreignPackageClassInfo.getters, foreignPackageClassInfo.setters );
310293
superClass = byteBuddyState.load(
311-
foreignPackageClassInfo.clazz,
294+
bridgeMembersClassInfo.clazz,
312295
byteBuddy -> {
313296
DynamicType.Builder<?> builder = byteBuddy.with(
314297
new NamingStrategy.SuffixingRandom(
315-
suffix,
298+
OPTIMIZER_PROXY_BRIDGE_NAMING_SUFFIX,
316299
new NamingStrategy.SuffixingRandom.BaseNameResolver.ForFixedValue(
317-
foreignPackageClassInfo.clazz.getName() )
300+
bridgeMembersClassInfo.clazz.getName() )
318301
)
319302
).subclass( newSuperClass );
320-
for ( Member getter : foreignPackageClassInfo.getters ) {
321-
final Class<?> getterType;
322-
if ( getter instanceof Field ) {
323-
getterType = ( (Field) getter ).getType();
324-
}
325-
else {
326-
getterType = ( (Method) getter ).getReturnType();
303+
for ( Member getter : bridgeMembersClassInfo.getters ) {
304+
if ( !Modifier.isPublic( getter.getModifiers() ) ) {
305+
final Class<?> getterType;
306+
if ( getter instanceof Field ) {
307+
getterType = ( (Field) getter ).getType();
308+
}
309+
else {
310+
getterType = ( (Method) getter ).getReturnType();
311+
}
312+
313+
builder = builder.defineMethod(
314+
"get_" + getter.getName(),
315+
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(
316+
getterType
317+
),
318+
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
319+
)
320+
.withParameter( bridgeMembersClassInfo.clazz )
321+
.intercept(
322+
new Implementation.Simple(
323+
new GetFieldOnArgument(
324+
getter
325+
)
326+
)
327+
);
327328
}
328-
329-
builder = builder.defineMethod(
330-
"get_" + getter.getName(),
331-
TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(
332-
getterType
333-
),
334-
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
335-
)
336-
.withParameter( foreignPackageClassInfo.clazz )
337-
.intercept(
338-
new Implementation.Simple(
339-
new GetFieldOnArgument(
340-
getter
341-
)
342-
)
343-
);
344329
}
345-
for ( Member setter : foreignPackageClassInfo.setters ) {
346-
final Class<?> setterType;
347-
if ( setter instanceof Field ) {
348-
setterType = ( (Field) setter ).getType();
349-
}
350-
else {
351-
setterType = ( (Method) setter ).getParameterTypes()[0];
330+
for ( Member setter : bridgeMembersClassInfo.setters ) {
331+
if ( !Modifier.isPublic( setter.getModifiers() ) ) {
332+
final Class<?> setterType;
333+
if ( setter instanceof Field ) {
334+
setterType = ( (Field) setter ).getType();
335+
}
336+
else {
337+
setterType = ( (Method) setter ).getParameterTypes()[0];
338+
}
339+
340+
builder = builder.defineMethod(
341+
"set_" + setter.getName(),
342+
TypeDescription.Generic.VOID,
343+
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
344+
)
345+
.withParameter( bridgeMembersClassInfo.clazz )
346+
.withParameter( setterType )
347+
.intercept(
348+
new Implementation.Simple(
349+
new SetFieldOnArgument(
350+
setter
351+
)
352+
)
353+
);
352354
}
353-
354-
builder = builder.defineMethod(
355-
"set_" + setter.getName(),
356-
TypeDescription.Generic.VOID,
357-
Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
358-
)
359-
.withParameter( foreignPackageClassInfo.clazz )
360-
.withParameter( setterType )
361-
.intercept(
362-
new Implementation.Simple(
363-
new SetFieldOnArgument(
364-
setter
365-
)
366-
)
367-
);
368355
}
369356

370357
return builder;
@@ -374,10 +361,10 @@ private Class<?> determineAccessOptimizerSuperClass(Class<?> clazz, Member[] get
374361
for ( int j = 0; j < getters.length; j++ ) {
375362
final Member getter = getters[j];
376363
final Member setter = setters[j];
377-
if ( foreignPackageClassInfo.getters.contains( getter ) ) {
364+
if ( bridgeMembersClassInfo.getters.contains( getter ) && !Modifier.isPublic( getter.getModifiers() ) ) {
378365
getters[j] = new ForeignPackageMember( superClass, getter );
379366
}
380-
if ( foreignPackageClassInfo.setters.contains( setter ) ) {
367+
if ( bridgeMembersClassInfo.setters.contains( setter ) && !Modifier.isPublic( setter.getModifiers() ) ) {
381368
setters[j] = new ForeignPackageMember( superClass, setter );
382369
}
383370
}
@@ -565,16 +552,31 @@ private boolean is64BitType(Class<?> type) {
565552
}
566553
}
567554

568-
private List<ForeignPackageClassInfo> createForeignPackageClassInfos(Class<?> clazz) {
569-
final List<ForeignPackageClassInfo> foreignPackageClassInfos = new ArrayList<>();
555+
private List<BridgeMembersClassInfo> createBridgeMembersClassInfos(
556+
Class<?> clazz,
557+
Member[] getters,
558+
Member[] setters,
559+
String[] propertyNames) {
560+
final List<BridgeMembersClassInfo> bridgeMembersClassInfos = new ArrayList<>();
570561
Class<?> c = clazz.getSuperclass();
571562
while (c != Object.class) {
572-
if ( !c.getPackageName().equals( clazz.getPackageName() ) ) {
573-
foreignPackageClassInfos.add( new ForeignPackageClassInfo( c ) );
563+
final BridgeMembersClassInfo bridgeMemberClassInfo = new BridgeMembersClassInfo( c );
564+
for ( int i = 0; i < getters.length; i++ ) {
565+
final Member getter = getters[i];
566+
final Member setter = setters[i];
567+
if ( getter.getDeclaringClass() == c && !Modifier.isPublic( getter.getModifiers() )
568+
|| setter.getDeclaringClass() == c && !Modifier.isPublic( setter.getModifiers() ) ) {
569+
bridgeMemberClassInfo.getters.add( getter );
570+
bridgeMemberClassInfo.setters.add( setter );
571+
bridgeMemberClassInfo.propertyNames.add( propertyNames[i] );
572+
}
573+
}
574+
if ( !bridgeMemberClassInfo.propertyNames.isEmpty() ) {
575+
bridgeMembersClassInfos.add( bridgeMemberClassInfo );
574576
}
575577
c = c.getSuperclass();
576578
}
577-
return foreignPackageClassInfos;
579+
return bridgeMembersClassInfos;
578580
}
579581

580582
public ByteBuddyProxyHelper getByteBuddyProxyHelper() {

0 commit comments

Comments
 (0)