Java-使用特定名称创建匿名Exception子类 [英] Java - Create anonymous Exception subclass with a certain name

查看:140
本文介绍了Java-使用特定名称创建匿名Exception子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用Fabric / Crashlytics将非崩溃问题发送到他们的服务器,然后再检查日志和堆栈跟踪。



不幸的是,Crashlytics API要求对不同的问题类型使用不同的Exception子类实例。 (在iOS SDK中,您可以仅将字符串用于不同的问题类型,而在Android版本中则不能。)

  public static void craslyticsRecordError(String issueType,String errorMsg)
{
Exception e = new Exception(issueType +- + errorMsg);
Crashlytics.logException(e);
}

现在我们有很多不同的问题类型,我们也可以在运行时(从字符串部分一起构建)。所以问题是,是否可以使用某些Java Vodoo / Hacks(reflection?)在运行时创建具有特定名称(我们用作问题类型的字符串的名称)的子类并从中创建实例。 / p>

这有可能吗?






我现在在摆弄与ByteBuddy一起使用,试图使其正常工作-但我一直坚持让动态类正确调用超类构造函数。另外,我不太确定以后是否可以强制转换为Exception。






感谢Rafael Winterhalter I是使此功能正常工作的又一步;)我已经完全尝试了您提供的功能:

  public static void craslyticsRecordError (字符串issueType,字符串errorMsg)
{
Class< ;?扩展Exception> dynamicType = new ByteBuddy()
.subclass(Exception.class)
.name(issueType)
.make()
.load(Fabric.class.getClassLoader(),ClassLoadingStrategy .Default.WRAPPER)
.getLoaded();
try
{
例外e = dynamicType.getConstructor(String.class).newInstance(errorMsg);

GameLog.d( [Fabric]内部异常: + e);
Crashlytics.logException(e);
}
catch(异常e1)
{
异常e =新的异常(issueType +- + errorMsg);
GameLog.d( [Fabric]错误一);
Crashlytics.logException(e);
e1.printStackTrace();
}
}

现在我遇到了这个运行时异常:

  java.lang.NoClassDefFoundError:net.bytebuddy.dynamic.loading.NoOpClassFileTransformer 
at net.bytebuddy.dynamic.loading .ByteArrayClassLoader。(ByteArrayClassLoader.java:136)
在net.bytebuddy.dynamic.loading.ByteArrayClassLoader.of(ByteArrayClassLoader.java:187)
在net.bytebuddy.dynamic.loading中。 ByteArrayClassLoader.load(ByteArrayClassLoader.java:212)
在net.bytebuddy.dynamic.loading.ClassLoadingStrategy $ Default $ WrappingDispatcher.load(ClassLoadingStrategy.java:285)
在net.bytebuddy.dynamic.loading中。 ClassLoadingStrategy $ Default.load(ClassLoadingStrategy.java:120)
在net.bytebuddy.dynamic.TypeResolutionStrategy $ Passive.initialize(TypeResolutionStrategy.java:79)
在net.bytebuddy.dynamic.DynamicType $ Default $ Unloaded.load(DynamicType.java:4376)
在org.utils.Fabric.craslyticsRecordErr或(Fabric.java:47)
(在android.os.MessageQueue.nativePollOnce(本地方法)
在android.os.MessageQueue.next(MessageQueue.java:323)
在android。 os.Looper.loop(Looper.java:143)
在android.app.ActivityThread.main(ActivityThread.java:7224)
在java.lang.reflect.Method.invoke(本机方法)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1230)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)






现在,使用以下Android专用代码:

  Class< ;?扩展Exception> dynamicType = new ByteBuddy()
.subclass(Exception.class)
.name(issueType)
.make()
.load(Fabric.class.getClassLoader(),AndroidClassLoadingStrategy .Default.WRAPPER)
.getLoaded();

并使用Android特定的gradle编译行:

 编译'net.bytebuddy:byte-buddy-android:1.7.3'

我仍然面临与以前相同的运行时异常。

解决方案

默认情况下,字节好友复制其超类的构造函数。在您的情况下,它将复制所有 Exception 构造函数,并且您可以生成这样的异常:

  Class< ;?扩展Exception> dynamicType = new ByteBuddy()
.subclass(Exception.class)
.name(issueType)
.make()
.load(Fabric.class.getClassLoader(),ClassLoadingStrategy .Default.WRAPPER)
.getLoaded();

异常e = dynamicType.getConstructor(String.class).newInstance(errorMsg);


We're using Fabric / Crashlytics for sending non-crash issues to their servers and later checking out the logs and stacktraces.

Unfortunately, the Crashlytics API requires to use a different Exception subclass instance for different issue types. (In the iOS SDK, you can simply use a string for different issue types, but in the Android version, you can't).

public static void craslyticsRecordError(String issueType, String errorMsg)
{
    Exception e = new Exception(issueType + "-" + errorMsg);
    Crashlytics.logException(e);
}

Now we have quite a few different issue types, that we also dynamically define at runtime (build together from string parts). So the questions is, is it possible with some Java Vodoo / Hacks (reflection?) to create a subclass at runtime with a certain name (the name of the string that we use as the issue type) and create and instance from it.

Is this somehow possible?


I'm now fiddling with ByteBuddy, trying to get it to work - but I'm stuck at getting my dynamic class call the superclass constructor correctly. Also I'm not quite sure if I'm allowed to cast to Exception later on.


Thanks to Rafael Winterhalter I'm one step further into getting this thing to work ;) I've tried exactly the you provided:

public static void craslyticsRecordError(String issueType, String errorMsg)
{
    Class<? extends Exception> dynamicType = new ByteBuddy()
            .subclass(Exception.class)
            .name(issueType)
            .make()
            .load(Fabric.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
            .getLoaded();
    try
    {
        Exception e = dynamicType.getConstructor(String.class).newInstance(errorMsg);

        GameLog.d("[Fabric] Inner Exception: " + e);
        Crashlytics.logException(e);
    }
    catch (Exception e1)
    {
        Exception e = new Exception(issueType + "-" + errorMsg);
        GameLog.d("[Fabric] ERROR ONE");
        Crashlytics.logException(e);
        e1.printStackTrace();
    }
}

and now I'm facing this runtime exception:

java.lang.NoClassDefFoundError: net.bytebuddy.dynamic.loading.NoOpClassFileTransformer
     at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.<init>(ByteArrayClassLoader.java:136)
     at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.of(ByteArrayClassLoader.java:187)
     at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.load(ByteArrayClassLoader.java:212)
     at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$WrappingDispatcher.load(ClassLoadingStrategy.java:285)
     at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default.load(ClassLoadingStrategy.java:120)
     at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:79)
     at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4376)
     at org.utils.Fabric.craslyticsRecordError(Fabric.java:47)
     at android.os.MessageQueue.nativePollOnce(Native Method)
     at android.os.MessageQueue.next(MessageQueue.java:323)
     at android.os.Looper.loop(Looper.java:143)
     at android.app.ActivityThread.main(ActivityThread.java:7224)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)


After now using this Android-specific code:

Class<? extends Exception> dynamicType = new ByteBuddy()
        .subclass(Exception.class)
        .name(issueType)
        .make()
        .load(Fabric.class.getClassLoader(), AndroidClassLoadingStrategy.Default.WRAPPER)
        .getLoaded();

and using the Android-specific gradle compile line:

compile 'net.bytebuddy:byte-buddy-android:1.7.3'

I'm still facing the same runtime Exception as before.

解决方案

By default, Byte Buddy copies the constructors of its super class. In your case, it copies all Exception constructors and you can generate an exception like this:

Class<? extends Exception> dynamicType = new ByteBuddy()
  .subclass(Exception.class)
  .name(issueType)
  .make()
  .load(Fabric.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded();

 Exception e = dynamicType.getConstructor(String.class).newInstance(errorMsg);

这篇关于Java-使用特定名称创建匿名Exception子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆