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

caijialiang updated RANGER-4201:
--------------------------------
    Attachment: hbase-hbase-master.log

> Hbase master can't start due to  ranger-hbase-plugin jersey jar class loading 
> order
> -----------------------------------------------------------------------------------
>
>                 Key: RANGER-4201
>                 URL: https://issues.apache.org/jira/browse/RANGER-4201
>             Project: Ranger
>          Issue Type: Bug
>          Components: Ranger
>    Affects Versions: 2.3.0, 2.4.0
>            Reporter: caijialiang
>            Assignee: caijialiang
>            Priority: Major
>         Attachments: hbase-hbase-master.err.log, hbase-hbase-master.log, 
> image-2023-04-27-16-11-05-561.png, image-2023-04-27-16-13-44-504.png, 
> image-2023-04-27-16-14-10-803.png, image-2023-04-27-16-14-37-202.png, 
> image-2023-04-27-16-15-44-539.png
>
>
>  
> Issue description: HBase fails to start after enabling Ranger 2.4 plugin. 
> Problem analysis is required.
> environment:
> linux centos7.4
> hbase 2.4.13
> ranger 2.4
> jdk1.8
> hadoop 3.3.4
> zookeeper 3.5.9
> Symptom: After integrating Ranger with HBase, HBase Master cannot start, and 
> Region Server also crashes after running for a period of time. The same error 
> message occurs during both processes.
>  
> {code:java}
>  [master/gs-server-13481:16000:becomeActiveMaster] 
> coprocessor.CoprocessorHost: The coprocessor 
> org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor threw 
> java.lang.ExceptionInInitializerError
> java.lang.ExceptionInInitializerError
>         at 
> com.sun.jersey.core.spi.factory.MessageBodyFactory.initReaders(MessageBodyFactory.java:182)
>         at 
> com.sun.jersey.core.spi.factory.MessageBodyFactory.initReaders(MessageBodyFactory.java:175)
>         at 
> com.sun.jersey.core.spi.factory.MessageBodyFactory.init(MessageBodyFactory.java:162)
>         at com.sun.jersey.api.client.Client.init(Client.java:343)
>         at com.sun.jersey.api.client.Client.access$000(Client.java:119)
>         at com.sun.jersey.api.client.Client$1.f(Client.java:192)
>         at com.sun.jersey.api.client.Client$1.f(Client.java:188)
>         at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193)
>         at com.sun.jersey.api.client.Client.<init>(Client.java:188)
>         at com.sun.jersey.api.client.Client.<init>(Client.java:171)
>         at com.sun.jersey.api.client.Client.create(Client.java:683)
>         at 
> org.apache.ranger.plugin.util.RangerRESTClient.buildClient(RangerRESTClient.java:228)
>         at 
> org.apache.ranger.plugin.util.RangerRESTClient.getClient(RangerRESTClient.java:193)
>         at 
> org.apache.ranger.plugin.util.RangerRESTClient.get(RangerRESTClient.java:473)
>         at 
> org.apache.ranger.admin.client.RangerAdminRESTClient.getRangerRolesDownloadResponse(RangerAdminRESTClient.java:1340)
>         at 
> org.apache.ranger.admin.client.RangerAdminRESTClient.getRolesIfUpdatedWithCred(RangerAdminRESTClient.java:1202)
>         at 
> org.apache.ranger.admin.client.RangerAdminRESTClient.getRolesIfUpdated(RangerAdminRESTClient.java:167)
>         at 
> org.apache.ranger.plugin.util.RangerRolesProvider.loadUserGroupRolesFromAdmin(RangerRolesProvider.java:183)
>         at 
> org.apache.ranger.plugin.util.RangerRolesProvider.loadUserGroupRoles(RangerRolesProvider.java:123)
>         at 
> org.apache.ranger.plugin.util.PolicyRefresher.loadRoles(PolicyRefresher.java:495)
>         at 
> org.apache.ranger.plugin.util.PolicyRefresher.startRefresher(PolicyRefresher.java:144)
>         at 
> org.apache.ranger.plugin.service.RangerBasePlugin.init(RangerBasePlugin.java:245)
>         at 
> org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.start(RangerAuthorizationCoprocessor.java:1120)
>         at 
> org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.start(RangerAuthorizationCoprocessor.java:160)
>         at 
> org.apache.hadoop.hbase.coprocessor.BaseEnvironment.startup(BaseEnvironment.java:69)
>         at 
> org.apache.hadoop.hbase.coprocessor.CoprocessorHost.checkAndLoadInstance(CoprocessorHost.java:285)
>         at 
> org.apache.hadoop.hbase.coprocessor.CoprocessorHost.loadSystemCoprocessors(CoprocessorHost.java:171)
>         at 
> org.apache.hadoop.hbase.master.MasterCoprocessorHost.<init>(MasterCoprocessorHost.java:155)
>         at 
> org.apache.hadoop.hbase.master.HMaster.initializeCoprocessorHost(HMaster.java:3870)
>         at 
> org.apache.hadoop.hbase.master.HMaster.finishActiveMasterInitialization(HMaster.java:902)
>         at 
> org.apache.hadoop.hbase.master.HMaster.startActiveMasterManager(HMaster.java:2175)
>         at 
> org.apache.hadoop.hbase.master.HMaster.lambda$run$0(HMaster.java:520)
>         at java.lang.Thread.run(Thread.java:748)
> Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: 
> org.glassfish.jersey.internal.RuntimeDelegateImpl
>         at 
> javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:130)
>         at 
> javax.ws.rs.ext.RuntimeDelegate.getInstance(RuntimeDelegate.java:97)
>         at javax.ws.rs.core.MediaType.valueOf(MediaType.java:172)
>         at com.sun.jersey.core.header.MediaTypes.<clinit>(MediaTypes.java:65)
>         ... 33 more
> Caused by: java.lang.ClassNotFoundException: 
> org.glassfish.jersey.internal.RuntimeDelegateImpl
>         at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
>         at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
>         at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
>         at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
>         at java.lang.Class.forName0(Native Method)
>         at java.lang.Class.forName(Class.java:264)
>         at javax.ws.rs.ext.FactoryFinder.newInstance(FactoryFinder.java:87)
>         at javax.ws.rs.ext.FactoryFinder.find(FactoryFinder.java:185)
>         at 
> javax.ws.rs.ext.RuntimeDelegate.findDelegate(RuntimeDelegate.java:112)
>         ... 36 more {code}
> Steps to reproduce:
>  
>  * 1.After installing HBase 2.x and Ranger 2.4, configure HBase by modifying 
> the hbase-site.xml file:
>  * Set hbase.coprocessor.master.classes to 
> org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor
>  * Set hbase.coprocessor.region.classes to 
> org.apache.hadoop.hbase.security.access.SecureBulkLoadEndpoint,org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor
>  * Set hbase.coprocessor.regionserver.classes to 
> org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor
>  * Restart HBase and check the HBase Master logs to observe the exception and 
> see the Master crash soon after
> solution:delete 
> /usr/bigtop/3.2.0/usr/lib/hbase/lib/ranger-hbase-plugin-impl/jersey-core-1.19.3.jar
>  
>  
> related issues
> https://issues.apache.org/jira/browse/HBASE-22029
> https://issues.apache.org/jira/browse/HBASE-22052
> !image-2023-04-27-16-11-05-561.png!
> Problem Analysis:
> Conclusion: Exception caused by class loading order
>  
> Analysis process: The call chain is roughly as follows: master start {-}> 
> org.apache.ranger.authorization.hbase.RangerAuthorizationCoprocessor.start 
> ... ->com.sun.jersey.api.client.Client.create 
> ...{-}>com.sun.jersey.core.spi.factory.MessageBodyFactory.init 
> ->com.sun.jersey.core.header.MediaTypes ->javax.ws.rs.core.MediaType.valueOf 
> -> javax.ws.rs.ext.RuntimeDelegate.getInstance -> 
> javax.ws.rs.ext.RuntimeDelegate.findDelegate
> I have fully investigated this call chain and found that the root cause of 
> the problem is that javax.ws.rs.ext.RuntimeDelegate in the 
> javax.ws.rs-api-2.1.1.jar package in HBase did not find 
> org.glassfish.jersey.internal.RuntimeDelegateImpl when calling findDelegate, 
> which caused the error. Specifically, javax.ws.rs.ext.RuntimeDelegate first 
> looks for the default JAXRS_RUNTIME_DELEGATE, which is 
> "javax.ws.rs.ext.RuntimeDelegate". If it cannot be found, it will fallback 
> and load JAXRS_DEFAULT_RUNTIME_DELEGATE, which is 
> org.glassfish.jersey.internal.RuntimeDelegateImpl.
> The method "findDelegate" in "javax.ws.rs.ext.RuntimeDelegate" is as follows:
> {code:java}
> public abstract class RuntimeDelegate {
>     public static final String JAXRS_RUNTIME_DELEGATE_PROPERTY = 
> "javax.ws.rs.ext.RuntimeDelegate";
>     private static final String JAXRS_DEFAULT_RUNTIME_DELEGATE = 
> "org.glassfish.jersey.internal.RuntimeDelegateImpl";
>     private static final Object RD_LOCK = new Object();
>     private static ReflectPermission suppressAccessChecksPermission = new 
> ReflectPermission("suppressAccessChecks");
>     private static volatile RuntimeDelegate cachedDelegate;    protected 
> RuntimeDelegate() {
>     }
>     public static RuntimeDelegate getInstance() {
>         // Double-check idiom for lazy initialization of fields.
>         // Local variable is used to limit the number of more expensive 
> accesses to a volatile field.
>         RuntimeDelegate result = cachedDelegate;
>         if (result == null) { // First check (no locking)
>             synchronized (RD_LOCK) {
>                 result = cachedDelegate;
>                 if (result == null) { // Second check (with locking)
>                     cachedDelegate = result = findDelegate();
>                 }
>             }
>         }
>         return result;
>     }    private static RuntimeDelegate findDelegate() {
>         try {
>             Object delegate = FactoryFinder.find(
>                     JAXRS_RUNTIME_DELEGATE_PROPERTY,
>                     JAXRS_DEFAULT_RUNTIME_DELEGATE,
>                     RuntimeDelegate.class);
>             if (!(delegate instanceof RuntimeDelegate)) {
>                 Class pClass = RuntimeDelegate.class;
>                 String classnameAsResource = pClass.getName().replace('.', 
> '/') + ".class";
>                 ClassLoader loader = pClass.getClassLoader();
>                 if (loader == null) {
>                     loader = ClassLoader.getSystemClassLoader();
>                 }
>                 URL targetTypeURL = loader.getResource(classnameAsResource);
>                 throw new LinkageError("ClassCastException: attempting to 
> cast"
>                         + 
> delegate.getClass().getClassLoader().getResource(classnameAsResource)
>                         + " to " + targetTypeURL);
>             }
>             return (RuntimeDelegate) delegate;
>         } catch (Exception ex) {
>             throw new RuntimeException(ex);
>         }
>     }
>  {code}
> When the "jersey-core-1.19.3.jar" file is removed from 
> "/usr/bigtop/3.2.0/usr/lib/hbase/lib/ranger-hbase-plugin-impl/", HBase can 
> start normally.
>  
> It is not clear which class, either "javax.ws.rs.ext.RuntimeDelegate" or 
> "org.glassfish.jersey.internal.RuntimeDelegateImpl", is loaded by HBase at 
> this point.
>  
> To determine which class is loaded and from which JAR file it is loaded, we 
> can first remove "/usr/lib/hbase/lib/javax.ws.rs-api-2.1.1.jar" and start 
> HBase normally. Then, we can use the Arthas tool 
> ([https://github.com/alibaba/arthas]) to sniff and determine which class is 
> loaded and from which JAR file it is loaded by the HBase JVM.
> After starting HBase normally, run the Arthas startup script "sudo -u hbase 
> -EH ./as.sh " attach to the HBase process. Then, execute "sc -d 
> javax.ws.rs.ext.RuntimeDelegat" to check whether 
> "javax.ws.rs.ext.RuntimeDelegate" is loaded.
>  
> result:
> {code:java}
> [arthas@1719]$ sc -d javax.ws.rs.ext.RuntimeDelegate
>  class-info        com.sun.jersey.core.spi.factory.AbstractRuntimeDelegate
>  code-source       
> /usr/bigtop/3.2.0/usr/lib/hadoop-hdfs/lib/jersey-core-1.19.jar
>  name              com.sun.jersey.core.spi.factory.AbstractRuntimeDelegate
>  isInterface       false
>  isAnnotation      false
>  isEnum            false
>  isAnonymousClass  false
>  isArray           false
>  isLocalClass      false
>  isMemberClass     false
>  isPrimitive       false
>  isSynthetic       false
>  simple-name       AbstractRuntimeDelegate
>  modifier          abstract,public
>  annotation
>  interfaces
>  super-class       +-javax.ws.rs.ext.RuntimeDelegate
>                      +-java.lang.Object
>  class-loader      +-sun.misc.Launcher$AppClassLoader@4fca772d
>                      +-sun.misc.Launcher$ExtClassLoader@436a4e4b
>  classLoaderHash   4fca772d class-info        
> com.sun.jersey.server.impl.provider.RuntimeDelegateImpl
>  code-source       /usr/bigtop/3.2.0/usr/lib/hadoop/lib/jersey-server-1.19.jar
>  name              com.sun.jersey.server.impl.provider.RuntimeDelegateImpl
>  isInterface       false
>  isAnnotation      false
>  isEnum            false
>  isAnonymousClass  false
>  isArray           false
>  isLocalClass      false
>  isMemberClass     false
>  isPrimitive       false
>  isSynthetic       false
>  simple-name       RuntimeDelegateImpl
>  modifier          public
>  annotation
>  interfaces
>  super-class       +-com.sun.jersey.core.spi.factory.AbstractRuntimeDelegate
>                      +-javax.ws.rs.ext.RuntimeDelegate
>                        +-java.lang.Object
>  class-loader      +-sun.misc.Launcher$AppClassLoader@4fca772d
>                      +-sun.misc.Launcher$ExtClassLoader@436a4e4b
>  classLoaderHash   4fca772d class-info        javax.ws.rs.ext.RuntimeDelegate
>  code-source       
> /usr/bigtop/3.2.0/usr/lib/hbase/lib/javax.ws.rs-api-2.1.1.jar
>  name              javax.ws.rs.ext.RuntimeDelegate
>  isInterface       false
>  isAnnotation      false
>  isEnum            false
>  isAnonymousClass  false
>  isArray           false
>  isLocalClass      false
>  isMemberClass     false
>  isPrimitive       false
>  isSynthetic       false
>  simple-name       RuntimeDelegate
>  modifier          abstract,public
>  annotation
>  interfaces
>  super-class       +-java.lang.Object
>  class-loader      +-sun.misc.Launcher$AppClassLoader@4fca772d
>                      +-sun.misc.Launcher$ExtClassLoader@436a4e4b
>  classLoaderHash   4fca772dAffect(row-cnt:3) cost in 112 ms. {code}
> By removing the jersey-core-1.19.3.jar file from 
> /usr/bigtop/3.2.0/usr/lib/hbase/lib/ranger-hbase-plugin-impl/, we can see 
> that the abstract class javax.ws.rs.ext.RuntimeDelegate is loaded by the 
> AppClassLoader from the javax.ws.rs-api-2.1.1.jar file located in 
> /usr/bigtop/3.2.0/usr/lib/hbase/lib/.
> At the same time, the implementation of javax.ws.rs.ext.RuntimeDelegate, 
> which is com.sun.jersey.server.impl.provider.RuntimeDelegateImpl, is loaded 
> from the jersey-server-1.19.jar file located in 
> /usr/bigtop/3.2.0/usr/lib/hadoop/lib/. Note that the hadoop lib directory is 
> appended to HBase's classpath when HBase is started, which is why it can be 
> loaded.
> Additionally, the abstract class 
> com.sun.jersey.core.spi.factory.AbstractRuntimeDelegate, which inherits from 
> RuntimeDelegate, is loaded from the jersey-core-1.19.jar file located in 
> /usr/bigtop/3.2.0/usr/lib/hadoop-hdfs/lib/.
> However, even after removing the jersey-core-1.19.3.jar file, we can still 
> see that HBase loads the same version of jersey-core-1.19.jar from the hadoop 
> lib directory. Therefore, the root cause of the error is not a class not 
> found due to a version conflict, but rather due to the order in which the 
> class loader loads the classes.
>  
> To verify this conclusion, the simplest way is to:
>  # Before deleting the jersey-core-1.19.3.jar file from 
> /ranger-hbase-plugin-impl/, print out the loading information of all the 
> classes involved in the stack trace of the heap dump exception in the log.
>  # After deleting the jersey-core-1.19.3.jar file, print out the loading 
> information of all the classes involved in the stack trace of the heap dump 
> exception in the log.
>  # Use regular expressions to batch delete the timestamps from the log, and 
> then compare the two log files to see any differences in the class loading 
> information.
> In the Ranger 2.4 source code, Ranger implements its own class loader, 
> RangerPluginClassLoader, which inherits from URLClassLoader. During 
> initialization, it is passed the path to the 
> ranger-\{componentname}{-}plugin-impl directory, and all the classes in this 
> directory will be loaded by RangerPluginClassLoader. The parent is set to 
> null, which in my understanding, is to block delegation loading. This is 
> because all the classes in the ranger{-}{componentname}-plugin-impl directory 
> are dependencies of the Ranger plugin. For example, if the version of a jar 
> that it depends on is lower, if the delegation loading mechanism is used, it 
> is easy to load the higher version of the class under the component/lib 
> directory, leading to class conflict issues. Therefore, parent is set to null.
> Internally, RangerPluginClassLoader first tries to load the jar files under 
> the ranger-\{componentname}-plugin-impl directory using the parent 
> URLClassLoader. If it can't be loaded, it uses the componentClassLoader, 
> which is the current thread context's class loader, to load it.
> !image-2023-04-27-16-13-44-504.png!
> Next, you can take a look at the source code of the 
> "RangerAuthorizationCoprocessor" class in Ranger. This class initializes an 
> instance of "rangerPluginClassLoader" and activates it. Within this class, 
> there are pre and post hooks for various HBase operations, primarily for 
> performing range permission-related operations. This triggers the loading of 
> Ranger-related classes by the rangerPluginClassLoader.
> !image-2023-04-27-16-14-10-803.png!
> Why does the hook activate the Ranger class loader at the beginning and 
> de-activate it after the hook method ends? Doesn't this approach impact 
> performance?
> !image-2023-04-27-16-14-37-202.png!
> The reason for de-activating the Ranger class loader after the hook method 
> ends is because the rangerPluginClassLoader code sets itself as the current 
> thread's context class loader. If it's not deactivated, it can cause 
> conflicts with the lower version packages loaded in the 
> .../ranger-hbase-plugin-impl/ directory, which can cause issues during 
> subsequent operations. Therefore, the conclusion is that this involves the 
> rangerPluginClassLoader and the AppClassLoader of the thread's context class 
> loader.
> We also need to understand how to load an instance of "RuntimeDelegate" and 
> how it searches for the implementation of "javax.ws.rs.ext.RuntimeDelegate". 
> We should also investigate why it cannot find the implementation class and 
> instead looks for "org.glassfish.jersey.internal.RuntimeDelegateImpl", 
> causing an error.
> First, the "RuntimeDelegate" class is loaded via the 
> "javax.ws.rs.ext.RuntimeDelegate.findDelegate" method, which calls 
> "FactoryFinder.find" to load the class. Once loaded, the instance must be of 
> type "RuntimeDelegate".
> {code:java}
> private static RuntimeDelegate findDelegate() {
>     try {
>       Object delegate = FactoryFinder.find("javax.ws.rs.ext.RuntimeDelegate", 
> "org.glassfish.jersey.internal.RuntimeDelegateImpl", RuntimeDelegate.class);
>       if (!(delegate instanceof RuntimeDelegate)) {
>         Class<RuntimeDelegate> pClass = RuntimeDelegate.class;
>         String classnameAsResource = pClass.getName().replace('.', '/') + 
> ".class";
>         ClassLoader loader = pClass.getClassLoader();
>         if (loader == null)
>           loader = ClassLoader.getSystemClassLoader(); 
>         URL targetTypeURL = loader.getResource(classnameAsResource);
>         throw new LinkageError("ClassCastException: attempting to cast" + 
> delegate
>             .getClass().getClassLoader().getResource(classnameAsResource) + " 
> to " + targetTypeURL);
>       } 
>       return (RuntimeDelegate)delegate;
>     } catch (Exception ex) {
>       throw new RuntimeException(ex);
>     } 
>   } {code}
> The process of loading the class via "FactoryFinder.find" is contained in the 
> "javax.ws.rs.ext.FactoryFinder.find" method, as shown in the following code:
> {code:java}
>     /**
>      * Finds the implementation {@code Class} for the given factory name,
>      * or if that fails, finds the {@code Class} for the given fallback
>      * class name and create its instance. The arguments supplied MUST be
>      * used in order. If using the first argument is successful, the second
>      * one will not be used.
>      * <p>
>      * This method is package private so that this code can be shared.
>      *
>      * @param factoryId         the name of the factory to find, which is
>      *                          a system property.
>      * @param fallbackClassName the implementation class name, which is
>      *                          to be used only if nothing else.
>      *                          is found; {@code null} to indicate that
>      *                          there is no fallback class name.
>      * @param service           service to be found.
>      * @param <T>               type of the service to be found.
>      * @return the instance of the specified service; may not be {@code null}.
>      * @throws ClassNotFoundException if the given class could not be found
>      *                                or could not be instantiated.
>      */
>     static <T> Object find(final String factoryId, final String 
> fallbackClassName, Class<T> service) throws ClassNotFoundException {
>         ClassLoader classLoader = getContextClassLoader();        try {
>             Iterator<T> iterator = ServiceLoader.load(service, 
> FactoryFinder.getContextClassLoader()).iterator();            
> if(iterator.hasNext()) {
>                 return iterator.next();
>             }
>         } catch (Exception | ServiceConfigurationError ex) {
>             LOGGER.log(Level.FINER, "Failed to load service " + factoryId + 
> ".", ex);
>         }        try {
>             Iterator<T> iterator = ServiceLoader.load(service, 
> FactoryFinder.class.getClassLoader()).iterator();            
> if(iterator.hasNext()) {
>                 return iterator.next();
>             }
>         } catch (Exception | ServiceConfigurationError ex) {
>             LOGGER.log(Level.FINER, "Failed to load service " + factoryId + 
> ".", ex);
>         }        // try to read from $java.home/lib/jaxrs.properties
>         FileInputStream inputStream = null;
>         String configFile = null;
>         try {
>             String javah = System.getProperty("java.home");
>             configFile = javah + File.separator + "lib" + File.separator + 
> "jaxrs.properties";
>             File f = new File(configFile);
>             if (f.exists()) {
>                 Properties props = new Properties();
>                 inputStream = new FileInputStream(f);
>                 props.load(inputStream);
>                 String factoryClassName = props.getProperty(factoryId);
>                 return newInstance(factoryClassName, classLoader);
>             }
>         } catch (Exception ex) {
>             LOGGER.log(Level.FINER, "Failed to load service " + factoryId
>                     + " from $java.home/lib/jaxrs.properties", ex);
>         } finally {
>             if (inputStream != null) {
>                 try {
>                     inputStream.close();
>                 } catch (IOException ex) {
>                     LOGGER.log(Level.FINER, String.format("Error closing %s 
> file.", configFile), ex);
>                 }
>             }
>         }        // Use the system property
>         try {
>             String systemProp = System.getProperty(factoryId);
>             if (systemProp != null) {
>                 return newInstance(systemProp, classLoader);
>             }
>         } catch (SecurityException se) {
>             LOGGER.log(Level.FINER, "Failed to load service " + factoryId
>                     + " from a system property", se);
>         }        if (fallbackClassName == null) {
>             throw new ClassNotFoundException(
>                     "Provider for " + factoryId + " cannot be found", null);
>         }        return newInstance(fallbackClassName, classLoader);
>     }
> } {code}
> To summarize the "FactoryFinder.find" method, it uses the thread context 
> class loader to load "javax.ws.rs.ext.RuntimeDelegate". If that fails, it 
> attempts to load it from system properties or alternative class names. If it 
> still cannot be found, it tries to load 
> "org.glassfish.jersey.internal.RuntimeDelegateImpl". If it cannot be loaded, 
> it throws an exception.
> When the 
> /usr/bigtop/3.2.0/usr/lib/hbase/lib/ranger-hbase-plugin-impl/jersey-core-1.19.3.jar
>  file was not deleted, the class loading order was as follows:
> javax.ws.rs.ext.RuntimeDelegate(appClassLoader) -> 
> javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate(RangerPluginClassLoader) -> 
> javax.ws.rs.ext.RuntimeDelegate.HeaderDelegateProvider(RangerPluginClassLoader
>  jersey-core-1.19.3.jar ranger-hbase-plugin-impl/jersey-core-1.19.3.jar).
> The RangerPluginClassLoader searched for the 
> com.sun.jersey.spi.HeaderDelegateProvider implementation class in the 
> META-INF/services/com.sun.jersey.spi.HeaderDelegateProvider file of the 
> jersey-core-1.19.3.jar file, found the 
> com.sun.jersey.core.impl.provider.header.LocaleProvider class in 
> ranger-hbase-plugin-impl/jersey-core-1.19.3.jar, and returned it.
> However, javax.ws.rs.ext.RuntimeDelegate.findDelegate would fail because 
> delegate instanceof RuntimeDelegate returned false.
> As a fallback, it searched for 
> org.glassfish.jersey.internal.RuntimeDelegateImpl, which was not found in the 
> hbase classpath and caused an exception to be thrown.
> After removing ranger-hbase-plugin-impl/jersey-core-1.19.3.jar, HBase can be 
> started normally. The class loading order is as follows:
> javax.ws.rs.ext.RuntimeDelegate is loaded from 
> /usr/lib/hadoop/lib/javax.ws.rs-api-2.1.1.jar. Then, the implementation class 
> of javax.ws.rs.ext.RuntimeDelegate is searched for, which is found in 
> /usr/lib/hadoop/lib/jersey-server-1.19.jar->META-INF/services/javax.ws.rs.ext.RuntimeDelegate->com.sun.jersey.server.impl.provider.RuntimeDelegateImpl,
>  and successfully loaded.
> The above class loading order was determined by modifying the code in the 
> RangerPluginClassLoader to print out the process of loading all classes.
> !image-2023-04-27-16-15-44-539.png!
> The following is a log that includes the class loading order. By analyzing 
> this log in conjunction with the Ranger class loader code, the above results 
> can be determined.
> [^hbase-hbase-master.err.log]
> [^hbase-hbase-master.log]



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to