Mybatis-3: MyBatis and JDK 9: Illegal reflective access

Created on 14 Dec 2017  Â·  16Comments  Â·  Source: mybatis/mybatis-3

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.

enhancement

Most helpful comment

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

All 16 comments

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

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

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

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

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).

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.

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.

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.

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.

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!

I assume all is working well. :)

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

3.5.1 with JDK11.0.2 ,still has this waining:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.ibatis.reflection.invoker.GetFieldInvoker (file:/C:/Users/liunewshine/.m2/repository/org/mybatis/mybatis/3.5.1/mybatis-3.5.1.jar) to field java.lang.reflect.Proxy.h
WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.invoker.GetFieldInvoker
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

3.5.2 with openjdk version "11.0.4" 2019-07-16
WARNING: Illegal reflective access by org.apache.ibatis.binding.MapperProxy (file:/.../.m2/repository/org/mybatis/mybatis/3.5.2/mybatis-3.5.2.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)

@Verdoso ,
Please try 3.5.3-SNAPSHOT .
The issue was reported and fixed via #1636 .

Yep, confirmed! (that it is fixed)
Thanks @harawata

Was this page helpful?
0 / 5 - 0 ratings