Skip to content
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

Closed
scabug opened this issue Dec 10, 2008 · 7 comments
Closed

transient lazy val: broken by design!? #1574

scabug opened this issue Dec 10, 2008 · 7 comments
Assignees

Comments

@scabug
Copy link

scabug commented Dec 10, 2008

Taking a closer look at transient lazy vals, I suspect it could be actually broken by design.

Given the following source:

@serializable
class testimpl {
  @transient lazy val classval: String = ""
}

This results into the following fields in the class:

  public volatile int bitmap$$0;
  private transient String classval;

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.

@scabug
Copy link
Author

scabug commented Dec 10, 2008

Imported From: https://issues.scala-lang.org/browse/SI-1574?orig=1
Reporter: Jan Kriesten (jkriesten)

@scabug
Copy link
Author

scabug commented Dec 10, 2008

Jan Kriesten (jkriesten) said:
Actually, the behavior of nulling out classval after deserialization and still having the bitfield set might be corresponding to the behavior of normal (non-lazy) transient fields. It's just that Java doesn't have a comparable lazy type, so this behavior isn't really well defined.

I would find it more plausible for transient lazy vals having their bitfield reset on deserialization.

@scabug
Copy link
Author

scabug commented Dec 11, 2008

@dragos said:
Indeed, this is something that we hadn't thought about. We need to have different bitmaps for transient and non-transient lazy vals.

@scabug
Copy link
Author

scabug commented Dec 16, 2009

Alexey Ermakov (zee) said:
Any updates?

@scabug
Copy link
Author

scabug commented Aug 25, 2010

Romain Reuillon (elmariachi) said:
I would be very interested in such a feature.

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.

@scabug
Copy link
Author

scabug commented Oct 20, 2010

@hubertp said:
Since I am handling all the lazy val bugs, I can take this one as well.

@scabug
Copy link
Author

scabug commented Nov 2, 2010

@hubertp said:
Fixed in r23435 (commit message accidentally said that it fixed #1573 not #1574).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants