初始化lambda函数时的NPE

初始化lambda函数时的NPE,lambda,java-8,Lambda,Java 8,我有一个BytecodeCacheService类,它被设计成singlton。在初始化过程中,NPE异常被抛出 代码如下所示: public class BytecodeCacheService { public final static class CachePlacer{ public final static BytecodeCacheService _instance = new BytecodeCacheService(); } p

我有一个BytecodeCacheService类,它被设计成singlton。在初始化过程中,NPE异常被抛出

代码如下所示:

public class BytecodeCacheService {

    public final static class CachePlacer{
        public final static BytecodeCacheService _instance = new BytecodeCacheService();    
    }

    private static ICache _cacheInstance = null ;
    static{
        _cacheInstance = new GlobalCache();
        System.out.println("Init "+_cacheInstance);

    }


    private BytecodeCacheService(){
        _logger.debug("Start Bytecode Cache Service");
    }

public static BytecodeCacheService get(){
    return CachePlacer._instance;
}
    public static void main(String[] args){
        ICache cache = new GlobalCache();
        System.out.println(cache.toString());
    }
}

class GlobalCache implements ICache{

    private ConcurrentMap<IGraphNode, BytecodeResource> _map = new ConcurrentHashMap<IGraphNode, BytecodeResource>();

    //Customize below values via annotation (xml configurtion or others)
    private final int MAX_ENTITES = Config.CACHE_GLOBAL_CACHE_SIZE;  // The maximal entities allowed in the GlobalCache (This is in theory).
    private final float _ratio = Config.CACHE_GLOBAL_CACHE_RATIO;   // Each purge removes (1-_ratios)*entities. 

    ScheduledExecutorService exec = Executors.newScheduledThreadPool(1,  new ThreadFactory(){
        final AtomicInteger count = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread thread  = new Thread();
            thread.setName("GLobalCache: purge "+count.getAndIncrement());
            thread.setDaemon(true);
            return thread;
        }

    });

    public GlobalCache(){
        System.out.println("init 1...");
   line 171: exec.scheduleAtFixedRate(()->{      
            //@TODO the future developer can think up better purge policy. Here I only use a simple NON-STRICT Longest un-used first. 
//          if(_map.size() > MAX_ENTITES*_ratio){
//              int len = (int) (MAX_ENTITES*(1-_ratio));
//              while(len>0){
//                  IGraphNode longest = null;
//                  long max=-1;
//                  Iterator<IGraphNode> iter = _map.keySet().iterator();
//                  //It is NON-Strict because during iteration the BytecodeClass in global Cache might be updated. 
//                  while(iter.hasNext()){
//                      IGraphNode node = iter.next();
//                      BytecodeResource resource = _map.get(node);
//                      if(longest == null || max < resource.getLife()){
//                          longest = node;
//                          max = _map.get(longest).getLife();
//                      }
//                  }
//                  if(longest!=null)
//                      _map.remove(longest);
//              }
//              len--;
//          }
            System.out.println("Smile...");

        }, 1, 2, TimeUnit.SECONDS);
        System.out.println("init 2...");
    }
}
2) ,运行BytecodeCacheService.get(),它报告:

init 1...
29/Mar/2016:16:19:03:347 -0300 [main] DEBUG c.j.a.services.BytecodeCacheService - Start Bytecode Cache Service
java.lang.invoke.ConstantObjectHandle
J9VMInternals.java:137:in `ensureError': java.lang.ExceptionInInitializerError
    from J9VMInternals.java:126:in `recordInitializationFailure'
    from BytecodeGenerator.java:59:in `action'
    from BytecodeGenerator.java:333:in `run'
    from BytecodeGenerator.java:328:in `generate'
    from CallSite.java:137:in `jitMethodHandle'
    from MutableCallSite.java:61:in `<init>'
    from SwitchPoint.java:135:in `<init>'
    from FailoverSwitchPointInvalidator.java:34:in `<clinit>'
    from OptoFactory.java:72:in `newGlobalInvalidator'
    from Ruby.java:5047:in `<init>'
    from Ruby.java:329:in `newInstance'
    from Main.java:272:in `internalRun'
    from Main.java:231:in `run'
    from Main.java:200:in `main'
Caused by:

BytecodeCacheService.java:171:in `<init>': java.lang.NullPointerException
    from BytecodeCacheService.java:40:in `<clinit>'
    from BytecodeGenerator.java:59:in `action'
    from BytecodeGenerator.java:333:in `run'
    from BytecodeGenerator.java:328:in `generate'
    from CallSite.java:137:in `jitMethodHandle'
    from MutableCallSite.java:61:in `<init>'
    from SwitchPoint.java:135:in `<init>'
    from FailoverSwitchPointInvalidator.java:34:in `<clinit>'
    from OptoFactory.java:72:in `newGlobalInvalidator'
    from Ruby.java:5047:in `<init>'
    from Ruby.java:329:in `newInstance'
    from Main.java:272:in `internalRun'
    from Main.java:231:in `run'
    from Main.java:200:in `main'
init1。。。
2016年3月29日:16:19:03:347-0300[main]调试c.j.a.services.BytecodeCacheService-启动字节码缓存服务
java.lang.invoke.ConstantObjectHandle
J9VMInternals.java:137:in'ensureError':java.lang.ExceptionInInitializeError
来自J9VMInternals.java:126:in`recordInitializationFailure'
来自BytecodeGenerator.java:59:in'action'
来自BytecodeGenerator.java:333:in'run'
来自BytecodeGenerator.java:328:in'generate'
来自CallSite.java:137:in'jitMethodHandle'
来自MutableCallSite.java:61:in`'
来自SwitchPoint.java:135:in`'
来自failoverswitchpointinvalidater.java:34:in`'
来自OptoFactory.java:72:in`newGlobalInvalidator'
来自Ruby.java:5047:in`'
来自Ruby.java:329:in'newInstance'
from Main.java:272:in'internalRun'
from Main.java:231:in'run'
from Main.java:200:in'Main'
原因:
BytecodeCacheService.java:171:in`:java.lang.NullPointerException
来自BytecodeCacheService.java:40:in`'
来自BytecodeGenerator.java:59:in'action'
来自BytecodeGenerator.java:333:in'run'
来自BytecodeGenerator.java:328:in'generate'
来自CallSite.java:137:in'jitMethodHandle'
来自MutableCallSite.java:61:in`'
来自SwitchPoint.java:135:in`'
来自failoverswitchpointinvalidater.java:34:in`'
来自OptoFactory.java:72:in`newGlobalInvalidator'
来自Ruby.java:5047:in`'
来自Ruby.java:329:in'newInstance'
from Main.java:272:in'internalRun'
from Main.java:231:in'run'
from Main.java:200:in'Main'
第171行是类
GlobalCache
中的
exec.scheduleAtFixedRate({}->{}..)
。我调试了它,并在此方法调用中引发异常


我使用lambda函数的方式是否有任何错误(我目前不熟悉此部分)?有人能解释1)和2)之间的不同结果吗?我在这里使用Java8和J9JVM

你的lambda在第一种情况下有效吗?我没有在任何日志中看到“微笑”。Plus exec.scheduleAtFixedRate不是一个集合,那么为什么要遍历它呢?您的代码毫无意义。您正在为
BytecodeCacheService
使用惰性实例化,但该实例化几乎是不可操作的。潜在的昂贵操作是
全局缓存的实例化,您可以在
静态
初始值设定项中非惰性地执行该操作,该初始值设定项将在调用
get()
之前执行。除此之外,永远不要在构造函数中启动新线程。在构造函数中发布异步操作,即使延迟1秒,也是一种错误的设计。通常,如果类初始化中存在循环依赖项,则根据触发初始化的方式,可能会出现不同的行为,但发布的代码没有此类依赖项。因此,除非
Executors.newScheduledThreadPool
返回
null
或字节码或堆栈跟踪已被操纵,否则无法使用该代码获取特定异常。
init 1...
29/Mar/2016:16:19:03:347 -0300 [main] DEBUG c.j.a.services.BytecodeCacheService - Start Bytecode Cache Service
java.lang.invoke.ConstantObjectHandle
J9VMInternals.java:137:in `ensureError': java.lang.ExceptionInInitializerError
    from J9VMInternals.java:126:in `recordInitializationFailure'
    from BytecodeGenerator.java:59:in `action'
    from BytecodeGenerator.java:333:in `run'
    from BytecodeGenerator.java:328:in `generate'
    from CallSite.java:137:in `jitMethodHandle'
    from MutableCallSite.java:61:in `<init>'
    from SwitchPoint.java:135:in `<init>'
    from FailoverSwitchPointInvalidator.java:34:in `<clinit>'
    from OptoFactory.java:72:in `newGlobalInvalidator'
    from Ruby.java:5047:in `<init>'
    from Ruby.java:329:in `newInstance'
    from Main.java:272:in `internalRun'
    from Main.java:231:in `run'
    from Main.java:200:in `main'
Caused by:

BytecodeCacheService.java:171:in `<init>': java.lang.NullPointerException
    from BytecodeCacheService.java:40:in `<clinit>'
    from BytecodeGenerator.java:59:in `action'
    from BytecodeGenerator.java:333:in `run'
    from BytecodeGenerator.java:328:in `generate'
    from CallSite.java:137:in `jitMethodHandle'
    from MutableCallSite.java:61:in `<init>'
    from SwitchPoint.java:135:in `<init>'
    from FailoverSwitchPointInvalidator.java:34:in `<clinit>'
    from OptoFactory.java:72:in `newGlobalInvalidator'
    from Ruby.java:5047:in `<init>'
    from Ruby.java:329:in `newInstance'
    from Main.java:272:in `internalRun'
    from Main.java:231:in `run'
    from Main.java:200:in `main'