I know the Java compiler generates different classes for lambda functions depending on the context and closure they have. When I receive the lambda as a parameter (using the Consumer<> class), may I know the lifetime of the parameter?
For example, I have the following Observable class, that keeps a weak reference to its observes.
class Observable {
private final List<WeakReference<Consumer<Object>>> observables = new ArrayList<>();
private Object obj;
public Observable(Object obj){
this.obj = obj;
}
public void observe(Consumer<Object> cons){
this.observables.add(new WeakReference<>(cons));
}
public void set(Object obj){
this.obj = obj;
// notify observes
for(WeakReference<Consumer<Object>> cons : this.observables){
if(cons.get() != null)
cons.get().accept(this.obj);
// clearing the non-existing observes from the list is ommited for simplicity
}
}
}
Now I use it as follows.
public class Main {
public static void main(String[] args) {
Object c = new Object();
Observable obs = new Observable(c);
new ContainingClass(obs);
obs.set(c);
System.gc();
obs.set(c);
}
}
The code just creates the object and its observer and creates ContainingClass (definition follows) that observes. Then the object is set once, garbage collector explicitly called (so the created ContainingClass is deleted) and set the object a second time.
Now, as long as the lambda is instance-specific (reference either this or its instances method) it's called only once (because it is destroyed by the GC).
public class ContainingClass {
public ContainingClass(Observable obs){
obs.observe(this::myMethod);
}
private void myMethod(Object obj) {
System.out.println("Hello here");
}
}
public class ContainingClass {
private Object obj;
public ContainingClass(Observable obs){
obs.observe(obj -> {
this.obj = obj;
System.out.println("Hello here");
});
}
}
But as the lambda becomes static, it is called twice, even after GC.
public class ContainingClass {
public ContainingClass(Observable obs){
obs.observe((obj) -> System.out.println("Hello here"));
}
}
The reference to this lambda is never destroyed and therefore add as an observer every time ContainingClass instance is created. As a result, it will be stuck in observers until the program ends.
Is there a way to detect this and at least show a warning, that the lambda will be never removed?
One thing I figured out is that lambda with instance lifetime has arg$1 property, so I can ask about the number of properties.
public void observe(Consumer<Object> cons){
if(cons.getClass().getDeclaredFields().length == 0)
System.out.println("It is static lifetime lambda");
this.observables.add(new WeakReference<>(cons));
}
Is it a universal approach? May there be a situation when this doesn't work?
I think a good solution would be the one hinted by #Olivier: you can return an object with a remove method that removes your Consumer from your list when called, like the following example:
#FunctionalInterface
public interface Registration {
void remove();
}
class Observable {
private final List<Consumer<Object>> observables = new ArrayList<>();
private Object obj;
public Observable(Object obj) {
this.obj = obj;
}
public Registration observe(Consumer<Object> cons) {
this.observables.add(cons);
return () -> this.observables.remove(cons);
}
public void set(Object obj) {
[...]
}
}
The alternative would be to check if the class the lambda belongs to is static or not, as suggested by #kutschkem, but I don't like resorting to introspection if there is a good alternative.
As already stated by #shalk, relying on WeakReference to handle GC can lead to unwanted behaviours, because there is no way to ensure that your Consumer isn't referenced (maybe by mistake) somewhere else.
Your question is similar to this question, so the answers there apply here too.
A static nested class has a flag that can be checked:
Modifier.isStatic(clazz.getModifiers()) // returns true if a class is static, false if not
Related
the usage of method references as listeners in an observer pattern does not work.
Example:
public class ObserverWithMethodReferenceAsListenerTest {
class ListenerCurator {
private final Set<Consumer<String>> listeners = new HashSet<>();
public boolean register(final Consumer<String> consumer) {
return this.listeners.add(consumer);
}
public boolean unregister(final Consumer<String> consumer) {
return this.listeners.remove(consumer);
}
public int getListenersCount() {
return this.listeners.size();
}
}
class MyListenerLeaks {
public void theListener(final String someString) {
// the listener
}
}
class MyListenerWorks {
public Consumer<String> consumer = str -> {
theListener(str);
};
public void theListener(final String someString) {
// the listener
}
}
#Test
public void testListenerLeak() {
ListenerCurator lc = new ListenerCurator();
MyListenerLeaks ml = new MyListenerLeaks();
lc.register(ml::theListener);
Assert.assertEquals(1, lc.getListenersCount());
lc.register(ml::theListener);
// expected 1 but there are 2 listeners
lc.unregister(ml::theListener);
// there are 2 listeners registered here
}
#Test
public void testListenerWorks() {
ListenerCurator lc = new ListenerCurator();
MyListenerWorks ml = new MyListenerWorks();
lc.register(ml.consumer);
Assert.assertEquals(1, lc.getListenersCount());
lc.register(ml.consumer);
Assert.assertEquals(1, lc.getListenersCount());
lc.unregister(ml.consumer);
Assert.assertEquals(0, lc.getListenersCount());
}
}
Conclusion: each referencing of the listener method with ml::theListener generates a new object id for the reference? Right? Therefore there a multiple listeners registered and cannot be removed individually?
The MyListenerWorks class uses a member with a "constant" object id and works. Is there another workaround for this? Are my assumptions correct?
After I added some breakpoints to the HashSet#add and remove function.
I got some results for your questions in the images below:
1. each referencing of the listener method with ml::theListener generates a new object id for the reference? Right?
Ans: No. It would generate a new memory address into the HashSet. There would not be an object id. So in the test function:testListenerLeak, you cannot remove the listener correspondingly. Since you didn't get the listeners from the set before you remove it.
2. The MyListenerWorks class uses a member with a "constant" object id and works. Is there another workaround for this? Are my assumptions correct?
You could take a look of the Observer pattern in Spring, Vue, or some other famous project. they have something similar to what you want. But mostly I have ever read about this pattern is in the Event-driven model. They use the "instanceOf" to check the subclasses and their superclass.
From the Oracle documentation on Method References:
Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.
A method reference is not a constant.
This is a question for Java. I have an interface called IMyObjectPredicate which implements a single test method to apply to an input:
public interface IMyObjectPredicate {
boolean test(MyObject x);
}
What I would like is to be able to pass an instance of IMyObjectPredicate around between objects and have the test function update its references to variables to those of the new object it is being passed to. For instance, consider a class which makes use of this predicate:
public class Tester {
MyObject o;
IMyObjectPredicate myTestFunction;
int myThreshold;
public Tester(/*stuff*/) {
/*Code here which initialises the Tester instance and 'myThreshold'*/
myTestFunction = new IMyObjectPredicate() {
#Override
public boolean test(MyObject o) {
return (o.value() > myThreshold);
}
};
}
public boolean isGood() {
return myTestFunction.test(o);
}
}
I would like to be able to perform a deep clone of the Tester object for reasons I won't go into here. But the idea is that the cloned instance of Tester should test the predicate against its own value of myThreshold, not reference the myThreshold of the first instance. But if I pass myTestFunction to a new instance of Tester, I guess it will still be referencing the myThreshold value of the first instance, instead of dynamically evaluating myThreshold based on the reference of the enclosing class.
How can I accomplish the passing of a IMyObjectPredicate object whose test function uses references to the fields of the new object it is passed to?
Edit:
A complicating factor is that, in general, it will not be possible to reconstruct myTestFunction solely from the fields within a Tester object. myTestFunction may be overwritten by other parts of the program in a way that does not correlate with the other fields of Tester. I can sacrifice this functionality if need be, but I would rather not for the sake of elegance.
Java does not have an API to replace enclosed context of anonymous class.
The simplest solution I can see from your simplified example is to add threshold to the signature of test function. As I understand the threshold is going to be there anyway.
public interface IMyObjectPredicate {
boolean test(MyObject x, int threshold);
}
Another approach would use some factory method that will create a predicate for provided threshold like
class PredicateFactory {
IMyObjectPredicate thresholdPredicate(int threshold) {
return new IMyObjectPredicate {
//...
}
}
}
then you can pas this factory to object that will use it's own threshold to construct new instance of predicate
factory.thresholdPredicate(myThreshold);
It is a lot easier if ImObjectPredicate is an class that simply stores a reference to a predicate instead of an interface. If you're able to make that change, each predicate can store its own threshold, which solves the issue.
public IMyObjectPredicate {
private int threshold;
private Predicate<MyObject> pred;
public int getThreshold() {
return threshold;
}
public Predicate<MyObject> getPredicate() {
return pred;
}
public IMObjectPredicate(int threshold, Predicate<MyObject> pred) {
this.threshold = threshold;
this.pred = pred;
}
public boolean test(MyObject o) {
return pred.test(o);
}
}
public class Tester {
MyObject o;
IMyObjectPredicate myTestFunction;
IMyObjectPredicate myTestFunctionCopyWithDiffThreshold;
int myThreshold;
public Tester(/*stuff*/) {
/*Code here which initialises the Tester instance and 'myThreshold'*/
myTestFunction =
new IMyObjectPredicate(myThreshold, o -> o.value() > getThreshold());
myTestFunctionCopyWithDiffThreshold =
new ImObjectPredicate(5, myTestFunction.getPredicate());
}
public boolean isGood() {
return myTestFunction.test(o);
}
}
This is the most sensible solution, as ImObjectPredicate should store its own threshold if that value uniquely refers to that ImObjectPredicate.
This question already has answers here:
How to create a variable that can be set only once but isn't final in Java
(12 answers)
Closed 8 years ago.
class A {
Object obj;
}
Say I have this class with the field obj. I want to make this field's value fixed once assigned.
The problem is that I don't want to assign the value in the constructor thus I cannot make the field final. Then it came up with me another solution:
class A {
Object obj;
public void setObj(Object obj) {
if (obj ==null)
this.obj = obj;
}
}
I wonder if there is a better (more elegant) one.
An alternative is to use functional programming idiom, and make sure your objects are immutable, by returning a new object.
The idea is the "new object" does not let you modify the field, and the "old object" is creating a new instance (and returning it) instead of simply setting the field, when asked to. This guaranteed your field is still final, and you can only change it once.
class B {
private static class ValuedB extends B {
public ValuedB(Object obj) {
super(obj);
}
#Override
public Object getObj() {
return super.obj;
}
#Override
public B setObj(Object obj) {
return this;
}
}
public B() {
this(null);
}
private B(Object obj) {
this.obj = obj;
}
private final Object obj;
public Object getObj() { return null;/* or raise exception */ }
public B setObj(Object obj) {
return new ValuedB(obj);
}
}
Invoking with myB = b.setObj(...);
Draw back is of course if you already possess multiple references to an instance of B, only one will me modified, so if it is the case - this idiom might not fit.
For example, running:
public static void main(String[] args) {
B b = new B();
System.out.println(b.getObj());
b = b.setObj("asdf");
System.out.println(b.getObj());
b = b.setObj("qwerty");
System.out.println(b.getObj());
}
will yield, as expected:
null
asdf
asdf
Let's say I have a class called Object and a thread called ObjectCreator that manages the creation of an Object. For the sake of simplicity, Object has attributes: objectNumber and objectName.
If I were to create an instance of Object called instance, it would be held by ObjectCreator. Now let's say I needed another thread (let's call it ObjectChanger) to be able to see and manipulate instance; does it make sense to turn instance into a static Object?
I've managed to see results by making instance static so now I can do something like:
ObjectCreator.instance.getName();
Where getName() is a method of Object. From what I've read from answers to similar questions, static things are evil and there's always workarounds. One suggestion I've read is to pass instance to ObjectChanger as an argument for its constructor but what if instance wasn't created yet at the time I need to create an ObjectChanger?
Perhaps this question is more about OOP concepts than multi-threading or it may be a duplicate so forgive me but I'm quite lost here.
EDIT: To address frankie's and Jim's suggestions, here are some code snippets:
Object:
class Object
{
private String objectName = "Something";
private int objectNumber = 1;
public synchronized void changeNumber(int newNumber)
{
objectNumber = newNumber;
}
}
ObjectCreator:
class ObjectCreator extends Thread
{
static Object instance;
public ObjectCreator (Object something)
{
instance = something;
}
static void createObject()
{
...
}
static Object getObject()
{
return instance;
}
}
ObjectChanger:
public class ObjectChanger extends Thread
{
private Object currentInstance = null;
private int instanceNumber = null;
public void run()
{
currentInstance = ObjectCreator.getObject(); //If I were to make getObject() non-static, this line churns up an error
instanceNumber = currentInstance.getObjectNumber();
currentInstance.changeNumber(2); //valid?
}
}
If you want a thread to obtain access to an object not created within it, you must ensure that said thread has a path of references which it can follow, leading to the new object.
Consider the following code, with no threads involved.
class MyObject { /* ... */ }
interface MyObjectProvider {
MyObject getMyObject();
}
class Creator implements MyObjectProvider {
private MyObject obj;
/* ... */
#Override
public MyObject getMyObject() {
return obj;
}
/** Invoked at some point in time. */
void createMyObject() {
obj = new MyObject();
}
}
class Consumer {
private MyObjectProvider provider;
Consumer(MyObjectProvider mop) {
provider = mop;
}
void consume() {
// At some point in time...
MyObject o = provider.getMyObject();
}
}
Example of a program:
public static void main(String[] args) {
Creator creator = new Creator();
Consumer consumer = new Consumer(creator);
creator.createMyObject();
consumer.consume();
}
When you add threads to the mix, some code has to change, but the struture is the same.
The idea is to run the Creator in a thread, and the Consumer in another, as you've pointed out.
So, in short, these are the things you should be looking into:
Concurrency control: look into data races, synchronized, mutual exclusion, and their friends. Start here.
wait and notify, if the Consumer should wait for MyObject to be created. Look here.
When you have a nice grasp on these concepts, you may look into the volatile keyword (watch out for its pitfalls), and the java.util.concurrent package which provides better concurrency primitives, concurrent collections, and atomic variables.
You can put your objects in a list structure like Vector and store them in the ObjectCreator. Add a getter method to ObjectCreator which will accept an index of the object to be received.
This is just a skeleton showing the basic structure. Error handling is left as an exercise :-)
public class MyObject { ... }
...
public class MyObjectCreator {
private Map<String,MyObject> createdObjects = new HashMap<>();
public MyObject makeNewObject(int objNum, String objName)
{
MyObject o = new MyObject(objNum, objName);
this.createdObjects.put(objName,o);
}
public MyObject getObject(String objName)
{
return this.createdObjects.get(objName);
}
}
...
public class MyProgram {
public static void main(String[] args)
{
MyObjectCreator oc = new MyObjectCreator();
MyObject mo = oc.makeNewObject(10,"aNewObject");
...
MyObject o = oc.get("aNewObject");
...
If you only want to change the values of the fields of your class, you should just pass the object into your newly created thread. Then there is really no need to keep a static reference around in a holder class.
But as commented already, we need a bit more information to get to what you want to do with your object and thread.
Why cant you just make an getter in the ObjectCreator class that retrieves said Object?
ex: ObjectCreater.getMyObject()
EDIT:
I think you're looking for something like this if Im not mistaken:
public class ObjectCreator{
ArrayList<Object> children;
public ObjectCreator(){
children = new ArrayList<Object>();
}
//returns back index in children array (for accessing from other threads)
public int createObject( whatever params here ){
Object o = new Object( params );
children.add(o);
return children.size()-1;
}
}
since I dont know much about the problem you're trying to solve, Im not sure if it has to be thread safe, if you want these objects mapped, or accessed differently, but Im confused where all the confusion about static is coming...
With the introduction of generics, I am reluctant to perform instanceof or casting as much as possible. But I don't see a way around it in this scenario:
for (CacheableObject<ICacheable> cacheableObject : cacheableObjects) {
ICacheable iCacheable = cacheableObject.getObject();
if (iCacheable instanceof MyObject) {
MyObject myObject = (MyObject) iCacheable;
myObjects.put(myObject.getKey(), myObject);
} else if (iCacheable instanceof OtherObject) {
OtherObject otherObject = (OtherObject) iCacheable;
otherObjects.put(otherObject.getKey(), otherObject);
}
}
In the above code, I know that my ICacheables should only ever be instances of MyObject, or OtherObject, and depending on this I want to put them into 2 separate maps and then perform some processing further down.
I'd be interested if there is another way to do this without my instanceof check.
Thanks
You could use double invocation. No promises it's a better solution, but it's an alternative.
Code Example
import java.util.HashMap;
public class Example {
public static void main(String[] argv) {
Example ex = new Example();
ICacheable[] cacheableObjects = new ICacheable[]{new MyObject(), new OtherObject()};
for (ICacheable iCacheable : cacheableObjects) {
// depending on whether the object is a MyObject or an OtherObject,
// the .put(Example) method will double dispatch to either
// the put(MyObject) or put(OtherObject) method, below
iCacheable.put(ex);
}
System.out.println("myObjects: "+ex.myObjects.size());
System.out.println("otherObjects: "+ex.otherObjects.size());
}
private HashMap<String, MyObject> myObjects = new HashMap<String, MyObject>();
private HashMap<String, OtherObject> otherObjects = new HashMap<String, OtherObject>();
public Example() {
}
public void put(MyObject myObject) {
myObjects.put(myObject.getKey(), myObject);
}
public void put(OtherObject otherObject) {
otherObjects.put(otherObject.getKey(), otherObject);
}
}
interface ICacheable {
public String getKey();
public void put(Example ex);
}
class MyObject implements ICacheable {
public String getKey() {
return "MyObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
class OtherObject implements ICacheable {
public String getKey() {
return "OtherObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
The idea here is that - instead of casting or using instanceof - you call the iCacheable object's .put(...) method which passes itself back to the Example object's overloaded methods. Which method is called depends on the type of that object.
See also the Visitor pattern. My code example smells because the ICacheable.put(...) method is incohesive - but using the interfaces defined in the Visitor pattern can clean up that smell.
Why can't I just call this.put(iCacheable) from the Example class?
In Java, overriding is always bound at runtime, but overloading is a little more complicated: dynamic dispatching means that the implementation of a method will be chosen at runtime, but the method's signature is nonetheless determined at compile time. (Check out the Java Language Specification, Chapter 8.4.9 for more info, and also check out the puzzler "Making a Hash of It" on page 137 of the book Java Puzzlers.)
Is there no way to combine the cached objects in each map into one map? Their keys could keep them separated so you could store them in one map. If you can't do that then you could have a
Map<Class,Map<Key,ICacheable>>
then do this:
Map<Class,Map<Key,ICacheable>> cache = ...;
public void cache( ICacheable cacheable ) {
if( cache.containsKey( cacheable.getClass() ) {
cache.put( cacheable.getClass(), new Map<Key,ICacheable>() );
}
cache.get(cacheable.getClass()).put( cacheable.getKey(), cacheable );
}
You can do the following:
Add a method to your ICachableInterface interface that will handle placing the object into one of two Maps, given as arguments to the method.
Implement this method in each of your two implementing classes, having each class decide which Map to put itself in.
Remove the instanceof checks in your for loop, and replace the put method with a call to the new method defined in step 1.
This is not a good design, however, because if you ever have another class that implements this interface, and a third map, then you'll need to pass another Map to your new method.