Skip to content
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

Illegal access reflection #1091

Closed
aelgn opened this issue May 14, 2021 · 14 comments
Closed

Illegal access reflection #1091

aelgn opened this issue May 14, 2021 · 14 comments

Comments

@aelgn
Copy link

aelgn commented May 14, 2021

Javers uses reflection setAccessible on types, see JaversMember:95. If you want to diff a class with non-public fields of a java.lang type (like String, Locale etc...) setAccessible is considered an illegal access operation.
This has just resulted in runtime warnings but with java 16 out the default is to deny these operations. It is still possible to override this behavior with the vm arg --illegal-access=warn, but this will be removed in a future JVM release.

A more granular way is to add the module import with vm args for each sub module in java.base --add-open.
But this will require all downstream projects to change their runtime config, which is much more cumbersome than to declare the modules in a module-info.java file in javers.

#911

Steps To Reproduce

  • create diffable dto class with a private final Locale member
  • launch with java 16
  • diff it
    -> exception: java.lang.reflect.InaccessibleObjectException: Unable to make field private static final java.util.Map java.util.Locale.CONSTANT_LOCALES accessible: module java.base does not "opens java.util" to unnamed module @1c53fd30
static class Qwop {
    private final Locale l;
    Qwop(final Locale l) {
        this.l = l;
    }
}
...
final Javers javers = JaversBuilder.javers().build();
javers.compare(new Qwop(Locale.US), new Qwop(Locale.CHINA));

Javers' Version
5.14.0 & 6.1.0

@bartoszwalacik
Copy link
Member

already fixed in Javers 6.0, see #911

@bartoszwalacik
Copy link
Member

ok, I see that you have referenced #911 in your report, so why this issue?

@aelgn
Copy link
Author

aelgn commented May 14, 2021

@bartoszwalacik hi, ah yes. I tested it with 6.1.0 too but still reproduced - will update the issue to reflect this

@dmitry-weirdo
Copy link

dmitry-weirdo commented May 25, 2021

Most probably is an issue with Java 16, I have exactly the same bug, also on 6.1.0. The same code is working under Java 15.

See https://openjdk.java.net/jeps/396 for more details on the change in the JDK.

@bartoszwalacik
Copy link
Member

Could be, it would be nice if you guys come up with a PR to fix this issue with Java 16.

@bartoszwalacik
Copy link
Member

@dmitry-weirdo how to reproduce this issue with Java 16?

@aelgn
Copy link
Author

aelgn commented Jun 7, 2021

@bartoszwalacik see reproducible steps in the issue above. It is using Locale as an example, but any Type from the java std lib will have the same issue if it contains private members, since javers tries to .setAccessible on them and java16 prevents that as a default. Maybe leverage the jackson serialization lib? I guess they solved it by creating custom serializers for alot of the data types in java std lib, and they also have extnesion modules for eg. Guava types.

@bartoszwalacik
Copy link
Member

confirmed, javers doesn't work on java 16

java.lang.reflect.InaccessibleObjectException: Unable to make field private static final long java.time.LocalDate.serialVersionUID accessible: module java.base does not "opens java.time" to unnamed module @59dfd65b

@bartoszwalacik
Copy link
Member

bartoszwalacik commented Jun 13, 2021

fixed in 6.2.1

lucas-prestes pushed a commit to lucas-prestes/javers that referenced this issue Jun 17, 2021
…commitPropertyIn with singleton list

javers#1091

javers#1091

System.out.printf removed

travis.com test

travis.com test

javers#1105

fix in javadoc
lucas-prestes pushed a commit to lucas-prestes/javers that referenced this issue Jun 17, 2021
javers#1091

System.out.printf removed

travis.com test

travis.com test

javers#1105
lucas-prestes pushed a commit to lucas-prestes/javers that referenced this issue Jun 19, 2021
lucas-prestes pushed a commit to lucas-prestes/javers that referenced this issue Jun 19, 2021
@dmitry-weirdo
Copy link

dmitry-weirdo commented Jul 2, 2021

Unfortunately, still not fixed in 6.2.2, looks like it fails on comparing java.util.Locale fields :(

java.lang.reflect.InaccessibleObjectException: Unable to make field private transient sun.util.locale.BaseLocale java.util.Locale.baseLocale accessible: module java.base does not "opens java.util" to unnamed module @1e6d1014

	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
	at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:177)
	at java.base/java.lang.reflect.Field.setAccessible(Field.java:171)
	at org.javers.common.reflection.JaversMember.setAccessibleIfNecessary(JaversMember.java:95)
	at org.javers.common.reflection.JaversMember.<init>(JaversMember.java:47)
	at org.javers.common.reflection.JaversMember.<init>(JaversMember.java:39)
	at org.javers.common.reflection.JaversField.<init>(JaversField.java:17)
	at org.javers.common.reflection.JaversFieldFactory.createJField(JaversFieldFactory.java:43)
	at org.javers.common.reflection.JaversFieldFactory.getAllFields(JaversFieldFactory.java:31)
	at org.javers.common.reflection.ReflectionUtil.getAllFields(ReflectionUtil.java:125)
	at org.javers.common.reflection.ReflectionUtil.getAllPersistentFields(ReflectionUtil.java:110)
	at org.javers.core.metamodel.scanner.FieldBasedPropertyScanner.getMembers(FieldBasedPropertyScanner.java:19)
	at org.javers.core.metamodel.scanner.PropertyScanner.scan(PropertyScanner.java:25)
	at org.javers.core.metamodel.scanner.ClassScanner.scan(ClassScanner.java:19)
	at org.javers.core.metamodel.type.TypeFactory$JavaRichType.lambda$new$0(TypeFactory.java:195)
	at org.javers.core.metamodel.type.TypeFactory$JavaRichType.getScan(TypeFactory.java:208)
	at org.javers.core.metamodel.type.TypeFactory.inferFromAnnotations(TypeFactory.java:163)
	at org.javers.core.metamodel.type.TypeFactory.lambda$infer$4(TypeFactory.java:108)
	at java.base/java.util.Optional.orElseGet(Optional.java:364)
	at org.javers.core.metamodel.type.TypeFactory.infer(TypeFactory.java:108)
	at org.javers.core.metamodel.type.TypeMapper.lambda$getJaversType$0(TypeMapper.java:121)
	at org.javers.core.metamodel.type.TypeMapperEngine.computeIfAbsent(TypeMapperEngine.java:103)
	at org.javers.core.metamodel.type.TypeMapper.getJaversType(TypeMapper.java:121)
	at org.javers.core.metamodel.type.ManagedClassFactory.lambda$convert$2(ManagedClassFactory.java:54)
	at org.javers.core.metamodel.type.JaversProperty.getType(JaversProperty.java:27)
	at org.javers.core.metamodel.type.JaversProperty.isEntityType(JaversProperty.java:31)
	at org.javers.core.metamodel.type.InstanceIdFactory.dehydratedLocalId(InstanceIdFactory.java:61)
	at org.javers.core.metamodel.type.InstanceIdFactory.dehydratedLocalId(InstanceIdFactory.java:92)
	at org.javers.core.metamodel.type.InstanceIdFactory.create(InstanceIdFactory.java:23)
	at org.javers.core.metamodel.type.EntityType.createIdFromInstance(EntityType.java:123)
	at org.javers.core.metamodel.object.GlobalIdFactory.createId(GlobalIdFactory.java:52)
	at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:38)
	at org.javers.core.graph.EdgeBuilder.lambda$createMultiEdge$0(EdgeBuilder.java:53)
	at org.javers.core.metamodel.type.CollectionType.mapToSet(CollectionType.java:64)
	at org.javers.core.metamodel.type.SetType.map(SetType.java:28)
	at org.javers.core.graph.EdgeBuilder.createMultiEdge(EdgeBuilder.java:62)
	at org.javers.core.graph.ObjectGraphBuilder.buildMultiEdges(ObjectGraphBuilder.java:112)
	at org.javers.core.graph.ObjectGraphBuilder.buildEdges(ObjectGraphBuilder.java:92)
	at org.javers.core.graph.ObjectGraphBuilder.buildGraphFromCdo(ObjectGraphBuilder.java:62)
	at org.javers.core.graph.ObjectGraphBuilder.buildGraph(ObjectGraphBuilder.java:51)
	at org.javers.core.graph.LiveGraphFactory.createLiveGraph(LiveGraphFactory.java:38)
	at org.javers.core.diff.DiffFactory.buildGraph(DiffFactory.java:102)
	at org.javers.core.diff.DiffFactory.compare(DiffFactory.java:55)
	at org.javers.core.JaversCore.compare(JaversCore.java:176)

My Java version:

>java -version
java version "16.0.1" 2021-04-20
Java(TM) SE Runtime Environment (build 16.0.1+9-24)
Java HotSpot(TM) 64-Bit Server VM (build 16.0.1+9-24, mixed mode, sharing)

The trivial test-case

package javers.test

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.javers.core.Javers;
import org.javers.core.JaversBuilder;
import org.javers.core.diff.Diff;
import org.junit.jupiter.api.Test;

import java.util.Locale;

import static org.assertj.core.api.Assertions.assertThat;

@Log4j2
public class JaVersLocaleTest {

    @Data
    @AllArgsConstructor
    static class ObjectWithLocale {
        Locale locale;
    }

    @Test
    void testCompareObjectsWithLocales() {
        final Javers javers = JaversBuilder
            .javers()
            .build();

        ObjectWithLocale primary = new ObjectWithLocale(Locale.ENGLISH);
        ObjectWithLocale secondary = new ObjectWithLocale(Locale.CANADA);

        Diff diff = javers.compare(primary, secondary);

        assertThat(diff).isNotNull();
    }
}

@bartoszwalacik should I reopen this or create a new bug?

@bartoszwalacik
Copy link
Member

Locale should be added to WellKnownValueTypes, please contribute a PR

@bartoszwalacik
Copy link
Member

The problem with java.util.Locale is fixed in 6.2.3

@adrianboimvaser
Copy link

adrianboimvaser commented Mar 1, 2022

Hi, I'm having the same problem with java.time.MonthDay:

Unable to make field private final int java.time.MonthDay.month accessible: module java.base does not "opens java.time" to unnamed module @610f7aa

@bartoszwalacik
Copy link
Member

@adrianboimvaser please open a new issue for that. Please push a failing test case

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

No branches or pull requests

4 participants