New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
transient lazy val: broken by design!? #1574
Comments
Imported From: https://issues.scala-lang.org/browse/SI-1574?orig=1 |
Jan Kriesten (jkriesten) said: I would find it more plausible for transient lazy vals having their bitfield reset on deserialization. |
@dragos said: |
Alexey Ermakov (zee) said: |
Romain Reuillon (elmariachi) said: For now, in Java I am expected to use an aspect to avoid polluting my serialized business classes with technical stuff in a transversal thread safe manner (using transient fields and a transient lock with late initialization for each of them is ugly): class A {
@Cachable
public B lazyMethod() {
return new B();
}
} And the code of the aspect looking for method with @cachable annotation invocation (I have also implemented a way to invalidate the cache but I don't know if it could be the point here): public aspect CachingAspect {
MethodCache methodCache = new MethodCache();
WeakLockRepository lockRepo = new WeakLockRepository();
LockRepository<Object> objectLockRepository = new LockRepository<Object>();
Object around(): execution(* *(..)) && @annotation(org.openmole.commons.aspect.caching.Cachable) {
Object object = thisJoinPoint.getThis();
String method = thisJoinPointStaticPart.getSignature().toString();
Object ret = methodCache.getCachedMethodResult(object, method);
if(ret != null) return ret;
Lock lock = lockRepo.getLockFor(object, method);
lock.lock();
try {
objectLockRepository.lock(object);
try{
ret = methodCache.getCachedMethodResult(object, method);
if(ret == null) {
ret = proceed();
methodCache.putCachedMethodResult(object, method, ret);
}
return ret;
} finally {
objectLockRepository.unlock(object);
}
} finally {
lock.unlock();
}
}
before() : execution(* *(..)) && @annotation(org.openmole.commons.aspect.caching.ChangeState) {
Object object = thisJoinPoint.getThis();
objectLockRepository.lock(object);
try {
methodCache.clear(object);
softMethodCache.clear(object);
} finally {
objectLockRepository.unlock(object);
}
}
} Basically the method cache is a WeakHashMap of Object -> Map( Method -> Cache ). This is pretty inefficient because it requires accessing 2�maps for a getting to the cached object. |
@hubertp said: |
Taking a closer look at transient lazy vals, I suspect it could be actually broken by design.
Given the following source:
This results into the following fields in the class:
That means, if an instance is serialized, the bitmap$$0 goes into the stream, the classval will be thrown away.
When deserialization takes place, classval will be null. But bitmap$$0 will have the init-flag for classval still set, i.e. classval wont be initialized again! ==> NPE!
I don't think that's the intended behavior.
The text was updated successfully, but these errors were encountered: