kostaskougios / cloning

deep clone java objects
Other
591 stars 112 forks source link

About instantiation. #110

Open LitnhJacuzzi opened 3 years ago

LitnhJacuzzi commented 3 years ago

I recommend you to use sun.misc.Unsafe.allocateInstance(), the Objenesis will be not available when the class is dynamically generated(It causes NoClassDefFoundError like #100 and problems in #45).

kostaskougios commented 3 years ago

@Littlenotch-Jacuzzi , I am getting


java.lang.SecurityException: Unsafe

    at jdk.unsupported/sun.misc.Unsafe.getUnsafe(Unsafe.java:99)
    at com.rits.cloning.Cloner.newInstance(Cloner.java:311)
    at com.rits.cloning.Cloner$CloneObjectCloner.deepClone(Cloner.java:618)
    at com.rits.cloning.Cloner.cloneInternal(Cloner.java:447)
    at com.rits.cloning.Cloner.deepClone(Cloner.java:338)
    at com.rits.tests.cloning.TestCloner.testNullInsteadOfCloneAnnotatedFields(TestCloner.java:555)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at junit.framework.TestCase.runTest(TestCase.java:177)
    at junit.framework.TestCase.runBare(TestCase.java:142)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:130)
    at junit.framework.TestSuite.runTest(TestSuite.java:241)
    at junit.framework.TestSuite.run(TestSuite.java:236)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

if I replace objenesis with Unsafe

LitnhJacuzzi commented 3 years ago

@kostaskougios Yes, you can't directly call that method in Unsafe. I wrote a method to solve it:

private static Unsafe hackUnsafe() {
    try {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        return (Unsafe) field.get(null);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

Use this method to replace the Unsafe.getUnsafe() method.

LitnhJacuzzi commented 3 years ago

Note that the efficiency of the Unsafe.allocateInstance() method is about 2000 times that of Objenesis. But the instantiated objects has not gone any initialization, and the fields in these objects are all null(reference type) or default values(basic type).