You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Arjan Tijms (Jira)" <ji...@apache.org> on 2021/06/10 14:29:00 UTC

[jira] [Updated] (FELIX-6430) Felix uses sun.misc.Unsafe, crashed on JDK 17

     [ https://issues.apache.org/jira/browse/FELIX-6430?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Arjan Tijms updated FELIX-6430:
-------------------------------
    Description: 
When running on JDK 17, Felix crashes with the following exception:
 
{noformat}
java.lang.NoSuchMethodException: sun.misc.Unsafe.defineAnonymousClass(java.lang.Class,[B,[Ljava.lang.Object;)
 at java.base/java.lang.Class.getMethod(Class.java:2227)
 at org.apache.felix.framework.util.SecureAction.getAccessor(SecureAction.java:1134)
 at org.apache.felix.framework.util.SecureAction.<clinit>(SecureAction.java:86)
 at org.apache.felix.framework.Felix.<clinit>(Felix.java:114)
 at org.apache.felix.framework.FrameworkFactory.newFramework(FrameworkFactory.java:30)
{noformat}

The offending code in question reflectively uses {{sun.misc.Unsafe}}


{code:java}
private static Consumer<AccessibleObject[]> getAccessor(Class clazz) {
    String packageName = clazz.getPackage().getName();
    
    if ("java.net".equals(packageName) || "jdk.internal.loader".equals(packageName)) {
        if (m_accessorCache == null) {
            try {
                // Use reflection on Unsafe to avoid having to compile against it
                Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
                Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
                
                // NOTE: deep reflection is allowed on sun.misc package for java 9.
                theUnsafe.setAccessible(true);
                Object unsafe = theUnsafe.get(null);
                
                // using defineAnonymousClass here because it seems more simple 
                // to get what we need
                Method defineAnonymousClass = 
                    unsafeClass.getMethod("defineAnonymousClass", 
                        Class.class, 
                        byte[].class, 
                        Object[].class);
                
                // The bytes stored in a resource to avoid real loading of it 
                // (see accessible.src for source).
                Class<Consumer<AccessibleObject[]>> result =
                   (Class<Consumer<AccessibleObject[]>>) 
                   defineAnonymousClass.invoke(
                        unsafe, URL.class,
                        accessor, null);
                m_accessorCache = result.getConstructor().newInstance();
            } catch (Throwable t) {
                t.printStackTrace();
                m_accessorCache = 
                    objects -> AccessibleObject.setAccessible(objects, true);
            }
        }
        
        return m_accessorCache;
    }
    
    return objects -> AccessibleObject.setAccessible(objects, true);
}
{code}

For JDK 17+ it may be needed to stop using {{sun.misc.Unsafe}} and use a JDK replacement?



  was:
When running on JDK 17, Felix crashes with the following exception:
 
{noformat}
java.lang.NoSuchMethodException: sun.misc.Unsafe.defineAnonymousClass(java.lang.Class,[B,[Ljava.lang.Object;)
 at java.base/java.lang.Class.getMethod(Class.java:2227)
 at org.apache.felix.framework.util.SecureAction.getAccessor(SecureAction.java:1134)
 at org.apache.felix.framework.util.SecureAction.<clinit>(SecureAction.java:86)
 at org.apache.felix.framework.Felix.<clinit>(Felix.java:114)
at org.apache.felix.framework.FrameworkFactory.newFramework(FrameworkFactory.java:30)
{noformat}

The offending code in question reflectively uses {{sun.misc.Unsafe}}


{code:java}
private static Consumer<AccessibleObject[]> getAccessor(Class clazz) {
    String packageName = clazz.getPackage().getName();
    
    if ("java.net".equals(packageName) || "jdk.internal.loader".equals(packageName)) {
        if (m_accessorCache == null) {
            try {
                // Use reflection on Unsafe to avoid having to compile against it
                Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
                Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
                
                // NOTE: deep reflection is allowed on sun.misc package for java 9.
                theUnsafe.setAccessible(true);
                Object unsafe = theUnsafe.get(null);
                
                // using defineAnonymousClass here because it seems more simple 
                // to get what we need
                Method defineAnonymousClass = 
                    unsafeClass.getMethod("defineAnonymousClass", 
                        Class.class, 
                        byte[].class, 
                        Object[].class);
                
                // The bytes stored in a resource to avoid real loading of it 
                // (see accessible.src for source).
                Class<Consumer<AccessibleObject[]>> result =
                   (Class<Consumer<AccessibleObject[]>>) 
                   defineAnonymousClass.invoke(
                        unsafe, URL.class,
                        accessor, null);
                m_accessorCache = result.getConstructor().newInstance();
            } catch (Throwable t) {
                t.printStackTrace();
                m_accessorCache = 
                    objects -> AccessibleObject.setAccessible(objects, true);
            }
        }
        
        return m_accessorCache;
    }
    
    return objects -> AccessibleObject.setAccessible(objects, true);
}
{code}

For JDK 17+ it may be needed to stop using {{sun.misc.Unsafe}} and use a JDK replacement?




> Felix uses sun.misc.Unsafe, crashed on JDK 17
> ---------------------------------------------
>
>                 Key: FELIX-6430
>                 URL: https://issues.apache.org/jira/browse/FELIX-6430
>             Project: Felix
>          Issue Type: Bug
>    Affects Versions: framework-7.0.0
>            Reporter: Arjan Tijms
>            Priority: Major
>
> When running on JDK 17, Felix crashes with the following exception:
>  
> {noformat}
> java.lang.NoSuchMethodException: sun.misc.Unsafe.defineAnonymousClass(java.lang.Class,[B,[Ljava.lang.Object;)
>  at java.base/java.lang.Class.getMethod(Class.java:2227)
>  at org.apache.felix.framework.util.SecureAction.getAccessor(SecureAction.java:1134)
>  at org.apache.felix.framework.util.SecureAction.<clinit>(SecureAction.java:86)
>  at org.apache.felix.framework.Felix.<clinit>(Felix.java:114)
>  at org.apache.felix.framework.FrameworkFactory.newFramework(FrameworkFactory.java:30)
> {noformat}
> The offending code in question reflectively uses {{sun.misc.Unsafe}}
> {code:java}
> private static Consumer<AccessibleObject[]> getAccessor(Class clazz) {
>     String packageName = clazz.getPackage().getName();
>     
>     if ("java.net".equals(packageName) || "jdk.internal.loader".equals(packageName)) {
>         if (m_accessorCache == null) {
>             try {
>                 // Use reflection on Unsafe to avoid having to compile against it
>                 Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
>                 Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
>                 
>                 // NOTE: deep reflection is allowed on sun.misc package for java 9.
>                 theUnsafe.setAccessible(true);
>                 Object unsafe = theUnsafe.get(null);
>                 
>                 // using defineAnonymousClass here because it seems more simple 
>                 // to get what we need
>                 Method defineAnonymousClass = 
>                     unsafeClass.getMethod("defineAnonymousClass", 
>                         Class.class, 
>                         byte[].class, 
>                         Object[].class);
>                 
>                 // The bytes stored in a resource to avoid real loading of it 
>                 // (see accessible.src for source).
>                 Class<Consumer<AccessibleObject[]>> result =
>                    (Class<Consumer<AccessibleObject[]>>) 
>                    defineAnonymousClass.invoke(
>                         unsafe, URL.class,
>                         accessor, null);
>                 m_accessorCache = result.getConstructor().newInstance();
>             } catch (Throwable t) {
>                 t.printStackTrace();
>                 m_accessorCache = 
>                     objects -> AccessibleObject.setAccessible(objects, true);
>             }
>         }
>         
>         return m_accessorCache;
>     }
>     
>     return objects -> AccessibleObject.setAccessible(objects, true);
> }
> {code}
> For JDK 17+ it may be needed to stop using {{sun.misc.Unsafe}} and use a JDK replacement?



--
This message was sent by Atlassian Jira
(v8.3.4#803005)