[ 
https://issues.apache.org/jira/browse/LANG-1685?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17515869#comment-17515869
 ] 

David Connard commented on LANG-1685:
-------------------------------------

I completely agree!  I don't think this is the right way to go either ... the 
toString() produced by this is off, and not really what you want.

This is simply the easiest option I could come up with to stop the library 
exploding.  I created that JDKSafeReflectiveToStringBuilder, overriding that 
one method with the above code, to stop it failing.  I'm not suggesting that 
this code should be merged, or that this is the right approach ... and that's 
why I didn't create a PR.

I think the solution will be to rely on Object::toString for these classes (as 
there's not much else you can do), but that solution most liekly lies 
elsewhere, and will need a more complex set of changes in the parent classes.

> [JDK17] ToStringBuilder.reflectionToString fails with 
> InaccessibleObjectException on java.lang classes
> ------------------------------------------------------------------------------------------------------
>
>                 Key: LANG-1685
>                 URL: https://issues.apache.org/jira/browse/LANG-1685
>             Project: Commons Lang
>          Issue Type: Bug
>          Components: lang.builder.*
>    Affects Versions: 3.12.0
>            Reporter: David Connard
>            Priority: Major
>
> JDK17 prevents reflective access to java.lang classes by default.
> The following code fails on JDK17+
> {code:java}
> System.out.println("boom = " + 
> ToStringBuilder.reflectionToString(Set.of(123))); {code}
> I understand that we can "--add-opens" (eg. as you've done for hbase builds 
> in 
> [https://github.com/jojochuang/hbase/commit/b909db7ca7c221308ad5aba1ea58317c77358b94)]
>  ... but, ideally, that should not be a standard requirement to run an 
> application that uses {{ToStringBuilder.reflectionToString()}} on JDK17+
> The following sample code appears to work for our use-case, albeit with some 
> additional spurious output on the object.  It catches the exception and just 
> dumps a raw object toString() instead.  You probably want to improve on this.
> {code:java}
> ReflectionToStringBuilder jdk17SafeToStringBuilder = new 
> ReflectionToStringBuilder(obj) {
>     protected void appendFieldsIn(final Class<?> clazz) {
>         if (clazz.isArray()) {
>             this.reflectionAppendArray(this.getObject());
>             return;
>         }
>         // The elements in the returned array are not sorted and are not in 
> any particular order.
>         final Field[] fields = clazz.getDeclaredFields();
>         Arrays.sort(fields, Comparator.comparing(Field::getName));
>         try {
>             // first, check that we can delve into the fields.  With JDK17+, 
> we cannot do this by default on
>             // various JDK classes
>             AccessibleObject.setAccessible(fields, true);
>         } catch (InaccessibleObjectException ioEx) {
>             // JDK 17 - prevents access to fields.  We'll ignore this, and 
> assume these have a decent toString() and not reflect into them
>             this.appendToString(Objects.toString(obj));
>             return;
>         }
>         for (final Field field : fields) {
>             final String fieldName = field.getName();
>             if (this.accept(field)) {
>                 try {
>                     // Warning: Field.get(Object) creates wrappers objects
>                     // for primitive types.
>                     final Object fieldValue = this.getValue(field);
>                     if (!isExcludeNullValues() || fieldValue != null) {
>                         this.append(fieldName, fieldValue, 
> !field.isAnnotationPresent(ToStringSummary.class));
>                     }
>                 } catch (final IllegalAccessException ex) {
>                     //this can't happen. Would get a Security exception
>                     // instead
>                     //throw a runtime exception in case the impossible
>                     // happens.
>                     throw new InternalError("Unexpected 
> IllegalAccessException: " + ex.getMessage());
>                 }
>             }
>         }
>     }
> };
>  {code}



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to