一.场景

当在Flink中使用POJO时,经常会出现该异常,代码如下:
1.POJO类:

class WordWithCount(word : String, count : Int){
  def this(){
    this(null, 0)
  }
}

2.逻辑代码

  val input = execution.fromElements(
      new WordWithCount("hello", 1),
      new WordWithCount("word", 2))

    val result = input
      .groupBy("word")
      .sum("count") // 分组求和
      .setParallelism(1)  // 设置并行度
      .sortPartition("count", Order.DESCENDING) // 降序排序

    result.print()

3.报错信息

Exception in thread "main" java.lang.NoClassDefFoundError: org/objenesis/strategy/InstantiatorStrategy
	at org.apache.flink.api.java.typeutils.GenericTypeInfo.createSerializer(GenericTypeInfo.java:90)
	at org.apache.flink.api.scala.ExecutionEnvironment.fromCollection(ExecutionEnvironment.scala:421)
	at org.apache.flink.api.scala.ExecutionEnvironment.fromElements(ExecutionEnvironment.scala:455)
	at cn.demo.SZTest$.main(SZTest.scala:36)
	at cn.demo.SZTest.main(SZTest.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.ClassNotFoundException: org.objenesis.strategy.InstantiatorStrategy
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 10 more

二.原因分析

1.objenesis简介
objenesis是一个小型Java类库用来实例化一个特定class的对象。

2.使用场合
Java已经支持使用Class.newInstance()动态实例化类的实例。但是类必须拥有一个合适的构造器。有很多场景下不能使用这种方式实例化类,比如:

  • 构造器需要参数
  • 构造器有side effects
  • 构造器会抛异常

因此,在类库中经常会有类必须拥有一个默认构造器的限制。Objenesis通过绕开对象实例构造器来克服这个限制。但是在Scala中不支持!

3.典型使用
实例化一个对象而不调用构造器是一个特殊的任务,然而在一些特定的场合是有用的:

  • 序列化,远程调用和持久化 -对象需要实例化并存储为到一个特殊的状态,而没有调用代码。
  • 代理,AOP库和Mock对象 -类可以被子类继承而子类不用担心父类的构造器。
  • 容器框架 -对象可以以非标准的方式被动态实例化。

三.解决方案

对于使用Scala作为编程语言的程序来说,Scala对objenesis不支持,因此,不建议使用POJO类而改用样例类!

case class WordWithCount(word : String, count : Int){
  def this(){
    this(null, 0)
  }
}

执行结果:

更多推荐

Flink报org.objenesis.strategy.InstantiatorStrategy原因及解决方案