微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

创建一个转换器以使用ByteBuddy从代理添加类

如何解决创建一个转换器以使用ByteBuddy从代理添加类

我正在尝试从使用ByteBuddy实现的代理加载类。我在代理中定义了一个类,并希望将其加载到目标程序中。这是我的变压器的样子:

public class ClassLoaderTransformer implements AgentBuilder.Transformer {
    private final Class<?> targetClass;

    public ClassLoaderTransformer(Class<?> targetClass) {
        this.targetClass = targetClass;
    }

    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,TypeDescription typeDescription,ClassLoader classLoader,JavaModule module) {
        try {
            final Class<?> aClass = Class.forName(typeDescription.getName());

            resolveClassLoadingStrategy(aClass).load(classLoader,singletonMap(
                    new TypeDescription.ForLoadedType(targetClass),ClassFileLocator.ForClassLoader.read(targetClass)
            ));
        } catch (Exception e){
            System.out.println("Something went terribly wrong: " + e.getMessage());
        }

        return builder;
    }

    private static ClassLoadingStrategy<ClassLoader> resolveClassLoadingStrategy(Class<?> targetClass) throws illegalaccessexception {
        if ( !ClassInjector.UsingLookup.isAvailable() ) {
            return new ClassLoadingStrategy.ForUnsafeInjection(targetClass.getProtectionDomain() );
        }

        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandles.Lookup privateLookup = MethodHandles.privateLookupIn(targetClass,lookup);

        return ClassLoadingStrategy.UsingLookup.of( privateLookup );
    }
}

但是,此代码无法正常工作。它将引发以下错误

tech.ikora.seleniumagent.helpers.sourcePageFetcher must be defined in the same package as org.openqa.selenium.remote.RemoteWebDriver

,堆栈跟踪如下:

java.lang.IllegalArgumentException: tech.ikora.seleniumagent.helpers.sourcePageFetcher must be defined in the same package as org.openqa.selenium.remote.RemoteWebDriver
        at net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup.injectRaw(ClassInjector.java:1414)
        at net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase.inject(ClassInjector.java:110)
        at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$UsingLookup.load(ClassLoadingStrategy.java:492)
        at tech.ikora.seleniumagent.ClassLoaderTransformer.transform(ClassLoaderTransformer.java:27)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:10364)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10302)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1600(AgentBuilder.java:10068)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmdispatcher.run(AgentBuilder.java:10761)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmdispatcher.run(AgentBuilder.java:10699)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10258)
        at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(UnkNown Source)
        at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
        at java.base/java.lang.classLoader.defineClass1(Native Method)
        at java.base/java.lang.classLoader.defineClass(ClassLoader.java:1016)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
        at java.base/java.net.urlclassloader.defineClass(urlclassloader.java:515)
        at java.base/java.net.urlclassloader$1.run(urlclassloader.java:423)
        at java.base/java.net.urlclassloader$1.run(urlclassloader.java:417)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:689)
        at java.base/java.net.urlclassloader.findClass(urlclassloader.java:416)
        at java.base/java.lang.classLoader.loadClass(ClassLoader.java:588)
        at java.base/java.lang.classLoader.loadClass(ClassLoader.java:521)
        at org.apache.maven.surefire.booter.IsolatedClassLoader.loadClass(IsolatedClassLoader.java:97)
        at java.base/java.lang.classLoader.defineClass1(Native Method)
        at java.base/java.lang.classLoader.defineClass(ClassLoader.java:1016)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
        at java.base/java.net.urlclassloader.defineClass(urlclassloader.java:515)
        at java.base/java.net.urlclassloader$1.run(urlclassloader.java:423)
        at java.base/java.net.urlclassloader$1.run(urlclassloader.java:417)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:689)
        at java.base/java.net.urlclassloader.findClass(urlclassloader.java:416)
        at java.base/java.lang.classLoader.loadClass(ClassLoader.java:588)
        at java.base/java.lang.classLoader.loadClass(ClassLoader.java:521)
        at org.apache.maven.surefire.booter.IsolatedClassLoader.loadClass(IsolatedClassLoader.java:97)
        at base.BaseTest.setup(BaseTest.java:31)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:132)
        at org.testng.internal.MethodInvocationHelper.invokeMethodConsideringTimeout(MethodInvocationHelper.java:61)
        at org.testng.internal.ConfigInvoker.invokeConfigurationMethod(ConfigInvoker.java:366)
        at org.testng.internal.ConfigInvoker.invokeConfigurations(ConfigInvoker.java:320)
        at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:176)
        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:122)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
        at org.testng.TestRunner.privateRun(TestRunner.java:764)
        at org.testng.TestRunner.run(TestRunner.java:585)
        at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
        at org.testng.SuiteRunner.run(SuiteRunner.java:286)
        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1218)
        at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
        at org.testng.TestNG.runSuites(TestNG.java:1069)
        at org.testng.TestNG.run(TestNG.java:1037)
        at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:77)
        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:159)
        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:99)
        at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:106)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.plugin.surefire.InPluginVMSurefireStarter.runSuitesInProcess(InPluginVMSurefireStarter.java:80)
        at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:724)
        at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeallProviders(AbstractSurefireMojo.java:682)
        at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:648)
        at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:586)
        at org.apache.maven.plugin.DefaultBuildpluginManager.executeMojo(DefaultBuildpluginManager.java:137)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)

在此示例中,SourcePageFetcher是targetClass,RemoveWebDriverTypeDescription提供的类。

该类加载器的目标是加载类,这些类将作为我为检测代码而创建的某些Advice的帮助者。我是否应该尝试以其他方式使用ClassInjector?还是我以错误的方式看到问题?还是应该只使用另一个ClassLoadingStrategy?

解决方法

如错误消息所提示:查找仅允许您在指定查找类的包中定义类。如果套件与您的套件有所不同:

tech.ikora.seleniumagent.helpers 
org.openqa.selenium.remote

JVM不允许这样做。但是,您还可以从代理程序使用UsingUnsafe策略,因为Instrumentation实例可以授予您对JVM内部的访问权限。否则,您需要将注入连接到正确程序包中的类。

请注意,您可以直接使用ClassInjector而不是使用ClassLoadingStrategy

,

遵循@RafaelWinterhalter的建议,对我有用的解决方案是将ClassInjector与UsingUnsafe一起使用。这将导致以下工作代码:

public class ClassLoaderTransformer implements AgentBuilder.Transformer {
    private final Class<?> targetClass;

    public ClassLoaderTransformer(Class<?> targetClass) {
        this.targetClass = targetClass;
    }

    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,TypeDescription typeDescription,ClassLoader classLoader,JavaModule module) {
        try {
            ClassInjector.UsingUnsafe.ofBootLoader().inject(singletonMap(
                    new TypeDescription.ForLoadedType(targetClass),ClassFileLocator.ForClassLoader.read(targetClass)
            ));
        } catch (Throwable e){
            System.out.println("Something went terribly wrong: " + e.getMessage());
        }

        return builder;
    }
}

请注意,在这种情况下,该类正在引导类加载器中加载,因此我们应该尝试使加载的类尽可能简单。此外,这里加载的类似乎无法访问子类加载器加载的类,因此,我再次不得不将这些类保持为最小。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。