私が経験している問題は次のとおりです。注釈を使用して収集される一連のクラスがあります。それらはすべて同じフォルダにあり、特定のアノテーションがある場合はReflections
libraryでインスタンス化されます。これらのクラスはインスタンス化されていますが、静的なファクトリを呼び出す静的な初期化子があり、構造体を構築します。ファクトリで作成されたオブジェクトを取得しようとすると、JavaはInvocationTargetException
エラーをスローします。具体的には、ITE
のスタックトレースを出力するときに、ファクトリにオブジェクトを要求する静的初期化子を直接指しています。Javaの `InvocationTargetException`は、リフレクションによるクラスのインスタンス化
以下は、問題を再現するために使用するコードです。私は、パッケージinference.rules
内のクラスのいくつかの数にその注釈を適用InferenceRule.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface funRule {
String ruleName();
String ruleType();
String analyze() default "node";
}
:
私は、アノテーションを持って
@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 IdentifierFactory {
private static final Identifier identifier;
static {
if (ConfigFactory.getConfig().isDebEnabled()) {
identifier = new DBIdentifier();
} else {
identifier = new NaiveIdentifier();
}
}
public static Identifier getIdentifier() {
return identifier;
}
}
:あなたが見ることができるようにAssign
とNodeAnalyzer
でインスタンス化パスから、
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());
}
}
}
}
、それはIdentifierFactory
クラスを呼び出す必要があります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
、私は十分に根本的な原因が何であるかを見分けることはできませんスロー
正確な例外は次のようになります。これをさらに複雑にするために、私は他の入力ファイルを使ってこれを実行しようとしました。
public class NaiveIdentifier {
private Set<Integer> unknowns = new HashSet<Integer>() {{
unknowns.add(0);
// add more here.
}}; // (<- added missing brace here)
public NaiveIdentifier() {} // empty default constructor
}
を考慮することができる根本的な原因は、 'NaiveIdentifier'クラス(または多分匿名の内部クラス)のコンストラクタでスローNPEように見えます。質問を編集してこのクラスのコードを含めることができますか? 2番目のエラーメッセージは「クラスを初期化できませんでした...」は、既に静的初期化に失敗したクラスをロードしようとすると起こります。 Javaは、これらを初期化するための2回目の試みを気にしません。 –
私は関連コードを追加しました。コードのすべての行をステップ実行した後、問題はNaiveIdentifierの 'HashSet'のインスタンス化によるものと思われました。それがなぜNPEを投げるのか理解できません。 – lilott8
二重中括弧の初期化は反パターンです。実際に何が起こっているのかを隠しています(実際にインスタンス化したい型をサブクラス化する内部クラスのインスタンスを作成します)。 (要素); 'fieldName.add(要素);の代わりに'。皮肉なことに、 'unknowns.add(0);'と書かれているように、文字を保存するのではなく、内部クラスのコンストラクタから 'unknowns 'フィールドにアクセスしてコード全体を破壊する前に、構築されたオブジェクトがフィールドに割り当てられています。 – Holger