我遇到的问题是这样的:我有一系列通过注释收集的类。它们都位于同一个文件夹中,如果它们具有特定的注释,则它们将通过Reflections
library进行实例化。当这些类被实例化时,有一个静态初始化器调用一个静态工厂,它构建了一些结构。 Java会在尝试获取工厂创建的对象时抛出InvocationTargetException
错误。更具体地说,当我输出ITE
的堆栈跟踪时,它直接指向为工厂请求对象的静态初始化程序。Java`InvocationTargetException`通过反射类实例化
下面是我用来复制问题的代码。
我具有注释:InferenceRule.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface funRule {
String ruleName();
String ruleType();
String analyze() default "node";
}
我然后该注释适用于某些数目的类在包inference.rules
:
@InferenceRule(ruleName = "assign", ruleType = "term")
public class Assign extends NodeAnalyzer {
public Assign() {super();}
public Assign(String... args) { super(args); }
public Rule gatherAllCOnstraints(InstructionNode node) {
// use the Identifier object here.
}
// rest of class here
}
的NodeAnalyzer
类中,Assign
类的超级上述:
public abstract class NodeAnalyzer {
protected Identifier identifier;
protected NodeAnalyzer() {
// Construct things here
}
protected NodeAnalyzer(String... args) {
// Construct other things here
}
// Construct common things here
{
this.identifier = IdentifierFactory.getIdentifier();
}
// rest of class here
}
的Assign
类实例化在Inference
类,如下所述:
public class Inference {
public final String NODE_ANALYSIS = "NODE";
public static final String INFERENCE_PACKAGE = "inference.rules";
private final Map<String, NodeAnalyzer> nodeAnalyzer = new HashMap<>();
private final Map<String, EdgeAnalyzer> edgeAnalyzer = new HashMap<>();
public Inference() {
}
// other non-interesting things here
private void loadRules() {
Reflections reflection = new Reflections(INFERENCE_PACKAGE);
Set<Class<?>> annotated = reflection.getTypesAnnotatedWith(InferenceRule.class);
for(Class<?> clazz : annotated) {
try {
String name = clazz.getAnnotation(InferenceRule.class).ruleName();
String type = clazz.getAnnotation(InferenceRule.class).ruleType();
String analyze = clazz.getAnnotation(InferenceRule.class).analyze();
if (StringUtils.equalsIgnoreCase(analyze, NODE_ANALYSIS)) {
final NodeAnalyzer newInstance = (NodeAnalyzer) clazz.getConstructor(InferenceType.class).newInstance(InferenceType.valueOf(type));
this.nodeAnalyzer.put(name, newInstance);
}
// handle other cases...
} catch(InvocationTargetException ite) {
// For debugging, only
ite.printStackTrace();
logger.error(ite.getCause.getMessage());
logger.error(ite.getTargetException.getMessage());
}
}
}
}
正如你可以看到,从Assign
和NodeAnalyzer
实例化路径,它必须调用IdentifierFactory
类:
public class IdentifierFactory {
private static final Identifier identifier;
static {
if (ConfigFactory.getConfig().isDebEnabled()) {
identifier = new DBIdentifier();
} else {
identifier = new NaiveIdentifier();
}
}
public static Identifier getIdentifier() {
return identifier;
}
}
NaiveIdentifier
类别:
public class NaiveIdentifier {
private Set<Integer> unknowns = new HashSet<Integer>() {{
unknowns.add(0);
// add more here.
};
public NaiveIdentifier() {} // empty default constructor
}
该ConfigFactory
类遵循类似于IdentifierFactory
类的模式。它根据一定的输入建立一个配置。
抛出确切异常的样子:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at phases.inference.Inference.loadRules(Inference.java:197)
at phases.inference.Inference.<init>(Inference.java:76)
at phases.PhaseFacade$PHASES.getPhase(PhaseFacade.java:27)
at phases.PhaseFacade.<init>(PhaseFacade.java:42)
at compilation.Compiler.runPhases(Compiler.java:126)
at compilation.Compiler.runAllOps(Compiler.java:118)
at Main.main(Main.java:45)
Caused by: java.lang.ExceptionInInitializerError
at phases.inference.rules.NodeAnalyzer.<init>(NodeAnalyzer.java:35)
at phases.inference.rules.Assign.<init>(Assign.java:22)
... 11 more
Caused by: java.lang.NullPointerException
at typesystem.identification.NaiveIdentifier$1.<init>(NaiveIdentifier.java:23)
at typesystem.identification.NaiveIdentifier.<init>(NaiveIdentifier.java:22)
at typesystem.identification.IdentifierFactory.<clinit>(IdentifierFactory.java:25)
... 13 more
和:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at phases.inference.Inference.loadRules(Inference.java:197)
at phases.inference.Inference.<init>(Inference.java:76)
at phases.PhaseFacade$PHASES.getPhase(PhaseFacade.java:27)
at phases.PhaseFacade.<init>(PhaseFacade.java:42)
at compilation.Compiler.runPhases(Compiler.java:126)
at compilation.Compiler.runAllOps(Compiler.java:118)
at Main.main(Main.java:45)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class typesystem.identification.IdentifierFactory
at phases.inference.rules.NodeAnalyzer.<init>(NodeAnalyzer.java:35)
at phases.inference.rules.Assign.<init>(Assign.java:18)
... 11 more
从这些,我无法充分地看清楚的根本原因是什么。为了进一步复杂化,我试图用其他输入文件来运行它,它对这些工作很好。
根本原因似乎是一个NPE在构造函数中抛出了'NaiveIdentifier'类(也可能是一个匿名内部类)。你能否编辑这个问题来包含这个类的代码?第二个错误消息'Could not initialize class ...'是当你尝试加载一个已经失败的静态初始化的类时会发生什么。 Java不打算再次尝试初始化这些。 –
我加了相关的代码。在遍历*每行*代码之后,似乎问题出现在'NaiveIdentifier'中的'HashSet'的实例化中。我不明白为什么会抛出NPE。 – lilott8
双花括号初始化是一种反模式,隐藏幕后实际发生的事情(创建一个内部类的实例,继承你实际想要实例化的类型),所有这些都是为了能够编写'add (element);'而不是'fieldName.add(element);'。具有讽刺意味的是,你甚至没有用'unknowns.add(0);'这样的优点,而不是保存任何字符,而是通过在内部类的构造函数中访问'unknowns'字段来破坏整个代码。已构建的对象已分配给该字段。 – Holger