Ok so I'm trying to keep a singleton instance of GetItemQuery which is a POJO to hold the requests and response fields needed for Retrofit API calls. I dont need to create a new GetItemQuery every time I make a call, hence I'm using the singleton pattern to set the fields of the existing GetItemQuery instance.
public class GetItemQuery {
// request data
private String itemId;
private int numberToLoad;
// response data
private Item item;
private static class Loader {
static final GetItemQuery sInstance = new GetItemQuery();
}
public static GetItemQuery getInstance(Item item) {
GetItemQuery instance = Loader.sInstance;
instance.setItem(item);
return instance;
}
public Item getItem() {
if (item == null) {
item = new Item();
}
return item;
}
public void setItem(Item item) {
this.item = item;
}
// other getters and setters
}
in my Android app. At what points should I be worried that getInstance() will be garbage collected so all the fields are cleared? Or is there a way for me to manually garbage collect so I ensure some fields don't become null unexpectedly?
Like described in this answer:
When would the garbage collector erase an instance of an object that uses Singleton pattern?
It will not be garbage collected, because there is a static reference
Related
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
In this Singleton instance, can this private Long severDate become garbage collected when the singleton instance is still not null?
I encountered this is in an Android app. Wondering Android OS somehow freeing unused individual memory values.
public class DataHolder {
private static DataHolder self;
private Long severDate;
private int numb;
public static synchronized DataHolder getInstance() {
if (self == null) {
self = new DataHolder();
}
return self;
}
}
Until "Long severDate" has a references to it, GC wont be deleting it. Now it all depends on the useCase whether u have created the instance of this singleton class in some classes or not.
P.S: In android make sure that u create the obj of this class in onCreate method.
There are several activities and fragments that need access to a specific data, so i created a singleton object to store data in that. The problem is after a long time that the app is in background, that singleton object will disapear and become null, so when i open my app again the app crashes and throws null pointer exception to that object. What should I do? How should i share that data between activities and fragments?
Is it a good practice to store that data in database? Or bundle? or whatever?
This is my singleton:
public class Book {
private static Book ourInstance;
private int FLNB;
private Book() {
}
public static Book getInstance() {
if (ourInstance == null) {
ourInstance = new Book();
}
return ourInstance;
}
public void setFLNB(int FLNB) {
this.FLNB = FLNB;
}
public int getFLNB() {
return this.FLNB;
}
}
I set FLNB, and when singleton is gone, the value of FLNB is cleared and I need to access this value after re-initial singleton.
I'm working with the Java AWS API to monitor some EC2 instances and on every refresh I need to query the service which returns a bunch of Instance objects (freshly constructed). I want to extend the functionality of these objects, I figure I can maintain a map of MyInstance objects which can be refreshed with the new Instances on each poll.
Now I could easily do this with a simple wrapper class that holds the original Instance as a property the issue is I would like to keep access to the base Instance API as I already use these functions in my code. Would it be possible to replace only the super-class parts of an instantiated object? Contrived example of what I'm going for:
class Instance {
protected int prop;
public Instance(int prop) {
this.prop = prop;
}
}
class MyInstance extends Instance {
protected int prop2;
public MyInstance(int prop, int prop2) {
super(prop);
this.prop2 = prop2;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.prop == 3
Obviously this example would be trivial to transform but in my actual case there are far more properties that need to be transferred. Can Reflection do this? What kind of performance impact am I looking at if I use Reflection for 10 of these every second? Thanks for reading!
The best solution is to combine both your ideas:
Wrap the original Instance in a class that extends the Instance class. (In the constructor of the child class, you can create a new Instance object and set it)
Delegate all methods to the wrapped instance (and add new properties)
In your foster method, you simply change the wrapped Instance.
class Instance {
private int prop;
public Instance(int prop) {
this.prop = prop;
}
public int getProp() {
return prop;
}
}
class MyInstance extends Instance {
private Instance delegate;
private int prop2;
public MyInstance(Instance delegate, int prop2) {
super(prop);
this.delegate = delegate;
this.prop2 = prop2;
}
#Override
public int getProp() {
return delegate.getProp();
}
public int getProp2() {
return prop2;
}
public void foster(Instance i) {
delegate = i;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.getProp() == 3
In Java, I have created a singleton class as follows:
public class Singleton
{
private Singleton() { print("Singleton Constructor"); }
private static Singleton pointer = new Singleton();//static here so only one object
public static Singleton makeSingleton()
{
return pointer;
}
public static void main (String args[])
{
Singleton nuReference = Singleton.makeSingleton();
if(nuReference == pointer)
{
print("Both are references for same object.");
}
}
}
Here, only the reference to an already-created object of Singleton class is being returned. How can I create a class so that only, say, four objects of that class are allowed to be created? Can I use this Singleton class for that or do I have to make it from scratch?
Oh, and print() is my custom method here. Works the same as System.out.println(), just with fewer keystrokes :)
That should work:
public class Singleton
{
private Singleton()
{
print("Constructor");
}
private static Singleton instances[] = new Singleton[4];
private static Boolean initiated = false;
public static Singleton getInstance(int index)
{
tryInitiate();
if(instances[index] == null)
{
instances[index] = new Singleton();
}
return instances[index];
}
private static Boolean tryInitiate()
{
if(initiated) return false;
for (int i = 0; i < instances.length; i++)
{
instances[i] == null;
}
initiated = true;
return true;
}
}
Instead of initiating the objects with "null" you could also instantiate the objects during the initiation. But this way only the needed objects are instantiated.
Add a static int count = numyouwant; to your code, every time the static creation method is called, reduce the count by 1. and more importantly, check whether count is 0 before call the private constructor in the creation method~
Singletons, by definition, only have a single instance of itself. What you're suggesting sounds like you would make better use of a Factory-type paradigm, along with a counter/limiter (built into the class).
Make a Factory class that contains a counter (or a list to store created objects, if you prefer) and a createObject method. In the method, do your logic for determining whether there are too many objects, and therefore you may limit creation of the objects.
Here's an example of a Factory with a max limit on created objects. The object in question is an inner class for simplicity.
public class Factory {
private final int maxObj = 4;
public class MyObject {
MyObject() { print("Constructor"); }
}
private List<MyObject> objects = new List<Object>();
// Returns new MyObject if total MyObject
// count is under maxObj, null otherwise
public MyObject makeObject() {
if (objects.length() >= maxObj)
return null;
MyObject obj = new MyObject();
objects.add(obj);
return obj;
}
}
create a variable x
increase its value every time when makeSingleton is called
if x<4 then return pointer
else return null
Create a field of List<Singleton> mySingletons; and a field int singletonCounter=0;
in makeSingleton() method add 1 to counter if it is equal to 4 return null or return a singleton of 4.If counter is less than 4 then create a singleton.
my question is that how can i create a class so that say only 4 objects of that class are allowed to be created. any help ?
can i use this Singleton class for that or do i have to make it from scratch ?
I believe you want to keep a pool of objects of a class . You can't do it through a Singleton class , which by definition should return the only instance it has.
Suggested reads:
Object Pool in Java
.
Build your own ObjectPool
You could add a Queue of 4 instances of the same object, and manage the queue/dequeue operations.
Beware: Sounds you should apply thread-safety for those operations.
I created one with Thread Safty
import java.util.ArrayList;
import java.util.List;
public class SingletonLimit{
private List<SingletonLimit> inst_Obj= new ArrayList<>();
private static final int maxLimit=4;
private SingletonLimit(){
}
public SingletonLimit getInstance(){
if(inst_Obj.size()>=maxLimit)
return null;
SingletonLimit singleLimit=null;
synchronized(SingletonLimit.class){
singleLimit= new SingletonLimit();
inst_Obj.add(singleLimit);
}
return singleLimit;
}
}