Lazy-initializing a static Method and making accessible not thread-safe

Description

An example is in AttributeConverterDescriptorImpl#toMember.

There are some scenarios that could lead to an exception when executing this line in AttributeConverterDescriptorImpl#toMember when first accessed in a multi-threaded environment:

memberMethod.invoke( xProperty )

One scenario:
1) thread-1 initializes the static field, memberMethod;
2) thread-2 finds that memberMethod != null, and attempts to invoke the method before thread-1 makes the memberMethod accessible via memberMethod.setAccessible( true ), resulting in HibernateException being thrown.

Another scenario:
1) both thread-1 and thread-2 find memberMethod == null and enter block to initialize memberMethod;
2) thread-1 initializes memberMethod and makes it accessible;
3) thread-2 overwrites memberMethod with a different Method, because Class#getDeclaredMethod returns a copy of the requested Method;
4) thread-1, attempts to invoke the method before thread-2 makes the overwritten memberMethod accessible, resulting in HibernateException being thrown.

There are 2 ways to fix this.

1) If lazy initialization is not needed, Initialize the static memberMethod in a static block, as in https://github.com/scottmarlow/hibernate-orm/tree/IllegalAccessException_hack.

2) If lazy initialization is desirable, assign the Method to a temporary variable and make it accessible before assigning to the static memberMethod. For example:

{{
Method tempMemberMethod = javaXMemberClass.getDeclaredMethod( "getMember" ); tempMemberMethod.setAccessible( true );
memberMethod = tempMemberMethod;
}}

Other places that need to be fixed are still to be determined.

Environment

None

Status

Assignee

Gail Badner

Reporter

Gail Badner

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Priority

Blocker