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

ThreadSafeDoubleCheckLocking.java: Instantiating by Reflection call will be successful if you do that firstly #761

Closed
DovahYol opened this issue Jun 24, 2018 · 10 comments

Comments

@DovahYol
Copy link

DovahYol commented Jun 24, 2018

if (instance != null) {
throw new IllegalStateException("Already initialized.");
}

Instance will be null, and you can create a singleton object by reflection without an exception.

@DovahYol DovahYol changed the title Instantiating by Reflection call will be successful if you do that firstly ThreadSafeDoubleCheckLocking.java: Instantiating by Reflection call will be successful if you do that firstly Jun 24, 2018
@iluwatar
Copy link
Owner

iluwatar commented Jul 7, 2018

Yes, that is true. But I think that is the way the code is supposed to work. It allows creating one and only one instance, right?

@DovahYol
Copy link
Author

DovahYol commented Jul 7, 2018

Actually you can create another instance via ThreadSafeDoubleCheckLocking.getInstance(), or as many instances as possible via reflection.

@iluwatar
Copy link
Owner

Can someone verify this?

@npathai
Copy link
Contributor

npathai commented Aug 15, 2018

@iluwatar Sure. I will have a look at it.

@npathai npathai self-assigned this Aug 15, 2018
@AnaghaSasikumar
Copy link
Contributor

AnaghaSasikumar commented Sep 29, 2018

I tried testing this and it is still possible to create multiple instances if only using reflection. I saw this solution on StackOverflow which will not allow reflection to access private methods and it worked for me.

So I made this change:

private ThreadSafeDoubleCheckLocking() {
// to prevent instantiating by Reflection call
checkPermission();
if (instance != null) {
throw new IllegalStateException("Already initialized.");
}
numOfInstances++;
}

void checkPermission() {
Class self = sun.reflect.Reflection.getCallerClass(1);
Class caller = sun.reflect.Reflection.getCallerClass(3);
if (self != caller) {
throw new java.lang.IllegalAccessError();
}
}

I would really appreciate feedback.

@IAmPramod
Copy link

I think we can create multiple instances of a singleton class only in case of lazy initialization as in the above example.
If we change that to eager initialization, this check will be sufficient to create multiple instances of this class.

@AnaghaSasikumar
Copy link
Contributor

Using sun.reflect.Reflection is not recommended and I don't really understand why it is able to create multiple instances inspite of what you have done in the constructor to try to avoid it, but this is something that can be done. Using reflection is not allowed on Google App Engine, I just saw, so maybe people are working around the security threat in that way. I found this solution here btw, forgot to mention in the previous comment: https://stackoverflow.com/questions/7566626/how-to-restrict-developers-to-use-reflection-to-access-private-methods-and-const

@Azureyjt
Copy link
Contributor

Azureyjt commented Sep 5, 2019

@iluwatar May I pick this up?

@iluwatar
Copy link
Owner

iluwatar commented Sep 5, 2019

@Azureyjt please go ahead

Azureyjt added a commit to Azureyjt/java-design-patterns that referenced this issue Sep 5, 2019
…ing by Reflection call will be successful if you do that firstly
@Azureyjt Azureyjt mentioned this issue Sep 5, 2019
@Azureyjt
Copy link
Contributor

Azureyjt commented Sep 5, 2019

PR created. Please kindly review it :) @iluwatar

iluwatar pushed a commit that referenced this issue Sep 7, 2019
…eflection call will be successful if you do that firstly (#920)
@iluwatar iluwatar added this to the 1.21.0 milestone Sep 7, 2019
@iluwatar iluwatar closed this as completed Sep 7, 2019
iluwatar pushed a commit that referenced this issue Oct 8, 2019
* Fix issue #761: ThreadSafeDoubleCheckLocking.java: Instantiating by Reflection call will be successful if you do that firstly

* Create leader election module

* Create Interface of Instance and MessageManager

* Create implementations with token ring algorithm

* Change package structure.
Create basic message system.

* Implement heartbeat and heartbeat invoking message system

* Implement election message handler

* Add leader message handler

* Add main entry point

* Add comments

* Update README.md

* Fix checkstyle issue

* Add Unit Tests

* Add Unit Tests

* Add bully leader selection

* Change System.out to log print.
Add MIT license in each file.

* Add More java doc comments

* Add unit test

* Add unit tests
iluwatar pushed a commit that referenced this issue Oct 16, 2019
* Fix issue #761: ThreadSafeDoubleCheckLocking.java: Instantiating by Reflection call will be successful if you do that firstly

* Create leader election module

* Create Interface of Instance and MessageManager

* Create implementations with token ring algorithm

* Change package structure.
Create basic message system.

* Implement heartbeat and heartbeat invoking message system

* Implement election message handler

* Add leader message handler

* Add main entry point

* Add comments

* Update README.md

* Fix checkstyle issue

* Add Unit Tests

* Add Unit Tests

* Add bully leader selection

* Change System.out to log print.
Add MIT license in each file.

* Add More java doc comments

* Add unit test

* Add unit tests

* Add subclass-sandbox

* Add Unit Test

* Add Unit Test

* Fix Typo

* Move dependency into parent pom.xml

* Change local valuable reference to be var
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants