初始化lambda函数时的NPE
我有一个BytecodeCacheService类,它被设计成singlton。在初始化过程中,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
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'