New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MyBatis and JDK 9: Illegal reflective access #1156

Closed
EldarAgalarov opened this Issue Dec 13, 2017 · 12 comments

Comments

Projects
None yet
7 participants
@EldarAgalarov
Copy link

EldarAgalarov commented Dec 13, 2017

After updating from JDK 8 to JDK 9, I'm getting following warnings:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/C:/Java%20Libs/MyBatis/mybatis-3.4.5.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.Reflector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

This happens because of new modular arch of JDK 9.

@kazuki43zoo

This comment has been minimized.

Copy link
Member

kazuki43zoo commented Dec 24, 2017

Thanks for your reporting!
We'll plan support JDK 9 officially since next minor version up(3.5).

@kazuki43zoo kazuki43zoo added this to the 3.5.0 milestone Dec 24, 2017

loicmathieu pushed a commit to loicmathieu/mybatis-3 that referenced this issue Jan 30, 2018

loicmathieu pushed a commit to loicmathieu/mybatis-3 that referenced this issue Jan 30, 2018

harawata added a commit that referenced this issue Feb 1, 2018

Skip Object when collecting class methods (#1180)
As a side effect, this might reduce the chance of 'illegal reflective access' warnings on Java 9. #1156

@kazuki43zoo kazuki43zoo modified the milestones: 3.5.0, 3.4.6 Mar 17, 2018

@kazuki43zoo

This comment has been minimized.

Copy link
Member

kazuki43zoo commented Mar 17, 2018

This issue has been fixed via 3.4.6 (#1180).

@jgprospect

This comment has been minimized.

Copy link

jgprospect commented Mar 19, 2018

With 3.4.6 I'm still getting a "reflective" error but just on a different method:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/..../.m2/repository/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar) to method java.lang.String.coder()
WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.Reflector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

@kazuki43zoo kazuki43zoo reopened this Mar 19, 2018

@kazuki43zoo

This comment has been minimized.

Copy link
Member

kazuki43zoo commented Mar 19, 2018

@jgprospect thanks for your reaction! This issue keeps the open status.

@kazuki43zoo kazuki43zoo added this to the 3.5.0 milestone Mar 19, 2018

@cristian-mocanu-mob

This comment has been minimized.

Copy link

cristian-mocanu-mob commented May 28, 2018

I think the fix in #1180 should be rolled-back, since it doesn't address the root cause.
The problem is not accessing private fields/methods in java.lang.Object, but in ANY class.

Check the following stacktraces (obtained by running the JVM with "--illegal-access=debug"):

WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/home/cvmocanu/.m2/repository/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar) to method java.lang.Class.getDeclaredConstructors0(boolean)
	at org.apache.ibatis.reflection.Reflector.addUniqueMethods(Reflector.java:344)
	at org.apache.ibatis.reflection.Reflector.getClassMethods(Reflector.java:317)
	at org.apache.ibatis.reflection.Reflector.addGetMethods(Reflector.java:96)
	at org.apache.ibatis.reflection.Reflector.<init>(Reflector.java:63)
	at org.apache.ibatis.reflection.DefaultReflectorFactory.findForClass(DefaultReflectorFactory.java:44)
	at org.apache.ibatis.reflection.MetaClass.<init>(MetaClass.java:39)
	at org.apache.ibatis.reflection.MetaClass.forClass(MetaClass.java:43)
	at org.apache.ibatis.reflection.wrapper.BeanWrapper.<init>(BeanWrapper.java:40)
	at org.apache.ibatis.reflection.MetaObject.<init>(MetaObject.java:56)
	at org.apache.ibatis.reflection.MetaObject.forObject(MetaObject.java:64)
	at org.apache.ibatis.reflection.SystemMetaObject.<clinit>(SystemMetaObject.java:30)
	at org.apache.ibatis.reflection.wrapper.MapWrapper.hasGetter(MapWrapper.java:123)
	at org.apache.ibatis.reflection.MetaObject.hasGetter(MetaObject.java:109)
	at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping(SqlSourceBuilder.java:75)
	at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken(SqlSourceBuilder.java:67)
	at org.apache.ibatis.parsing.GenericTokenParser.parse(GenericTokenParser.java:78)
	at org.apache.ibatis.builder.SqlSourceBuilder.parse(SqlSourceBuilder.java:45)
	at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:44)
	at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
	at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:40)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46)
	at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:558)
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:58)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
	at com.sun.proxy.$Proxy17.createOrUpdate(Unknown Source)
... stacktrace trimmed for privacy reasons

WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/home/cvmocanu/.m2/repository/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar) to field java.lang.String.value
	at org.apache.ibatis.reflection.Reflector.addFields(Reflector.java:259)
	at org.apache.ibatis.reflection.Reflector.<init>(Reflector.java:65)
	at org.apache.ibatis.reflection.DefaultReflectorFactory.findForClass(DefaultReflectorFactory.java:44)
	at org.apache.ibatis.reflection.MetaClass.<init>(MetaClass.java:39)
	at org.apache.ibatis.reflection.MetaClass.forClass(MetaClass.java:43)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:612)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:594)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:396)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:355)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:330)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:303)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:196)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:64)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:326)
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:136)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:83)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
	at com.sun.proxy.$Proxy27.getValue(Unknown Source)
... stacktrace trimmed for privacy reasons

As you can see, the error doesn't have anything to do with java.lang.Object.
It's simply forbidden to access private fields and methods.

I suspect the code looks-up fields and getter/setters for mappings, but maybe it shouldn't look up private fields and getters/setters at all.
It's a bit weird anyway, for MyBatis to be able to set them, but not the code.
I am only using public getters/setters (and non-default constructor mappings for immutability), and I don't map private fields.

If this is not possible to completely remove mapping of non-public fields/methods (for backward compatibility reasons), add a configuration option to turn off such mapping (with the default to allow - to preserve backwards compatibility).
Then start deprecating that option immediately, because soon (not sure how soon) Oracle will release a JVM that turns these warnings into errors (i.e. it will be forbidden to reflectively access private API).

@cristian-mocanu-mob

This comment has been minimized.

Copy link

cristian-mocanu-mob commented May 30, 2018

BTW, I the only places for this problem seem to be in org.apache.ibatis.reflection.Reflector.addUniqueMethods(Reflector.java:344) and org.apache.ibatis.reflection.Reflector.addFields(Reflector.java:259) (see stacktraces above).

At least in my code, I couldn't find any other place.

@harawata

This comment has been minimized.

Copy link
Member

harawata commented May 30, 2018

Hi @cristian-mocanu-mob ,

Please read the comments on #1180 .
The change was applied as a general optimization, not as a fix for the warnings.

@dawwin

This comment has been minimized.

Copy link
Contributor

dawwin commented Aug 1, 2018

I think the additional property suggested by @cristian-mocanu-mob is a good solution. JDK11 will be released soon and it will be LTS so a lot of people will migrate to this version. It would be good to have this option already.

@harawata

This comment has been minimized.

Copy link
Member

harawata commented Aug 1, 2018

I am still doing my research, but simple ON/OFF switch may be insufficient.
Calling setAccessible() is not a problem if the developer opened their module to MyBatis and we should support this scenario.

I think the right fix would be to check if a field/method is accessible only when it's requested by user's code (e.g. the field/property is referenced from a mapper).
Please give us some more time.

@harawata

This comment has been minimized.

Copy link
Member

harawata commented Oct 14, 2018

Hi all,
I have merged #1321 which should resolve the warning.
Please verify the fix with the latest 3.5.0-SNAPSHOT and let us know if there is any problem.
Thank you!

@harawata

This comment has been minimized.

Copy link
Member

harawata commented Jan 7, 2019

I assume all is working well. :)

@petarov

This comment has been minimized.

Copy link

petarov commented Jan 14, 2019

Using OpenJDK 11 with 3.5.0-SNAPSHOT, I can confirm the warnings are gone. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment