ProGuard removing method call creating useless code - java

So I have small interface
public interface IPlayersStorage
{
// other methods...
public boolean addException(final String nick);
// other methods...
}
and class "PlayersStorage" that implements it: (only used part)
public class PlayersStorage implements IPlayersStorage
{
private static final PlayersStorage inst = new PlayersStorage();
private final Set<String> exceptions = new HashSet<>(50);
#Override
public boolean addException(final String nick)
{
return ! this.exceptions.add(nick);
}
public static PlayersStorage getStorage()
{
return inst;
}
}
And in some place I use that method using that code:
for (final String player : this.cfg.getStringList("Exceptions"))
{
PlayersStorage.getStorage().addException(player);
}
And ProGuard change it to:
for (Iterator localIterator1 = this.cfg.getStringList("Exceptions").iterator(); localIterator1.hasNext();)
{
localIterator1.next();
PlayersStorage.getStorage(); // it's get object, but don't do anything with it...
}
The only possible fix that I found, is add static method to PlayersStorage
public static boolean staticAddException(final String nick)
{
return inst.addException(nick);
}
And then use it (instead of old code)
for (final String player : this.cfg.getStringList("Exceptions"))
{
PlayersStorage.staticAddException(player);
}
Then works... (ProGuard keep method call) but adding static methods for every method from interface isn't good idea.

ProGuard only removes method invocations if they don't have any effect (doesn't seem to be the case here), or if you have specified -assumenosideffects for the methods. You should check your configuration and remove any such option.
Alternatively, your decompiler may be having problems decompiling the code. You should then check the actual bytecode with javap -c.

Related

Improve Intellij Code Inspection for may produce NullPointerException warnings

I have a class with a hasField function that checks if a field is present and not null, and a getField function that returns the value of the field (or null if not present).
In my code when I call getField right after checking hasField, I know that getField is not going to return null, but the IDE Inspection (Constant Conditions and Exceptions) doesn't know that. I get a bunch of method method name may produce a NullPointerException
I'm trying to find a clean way to make this warning go away.
Workarounds
Here are some workarounds I could do but I find all of these hacky:
Surround getField with Objects.requireNotnull, the code would be no-op. Would prefer not doing that as it makes the code slightly less readable.
Suppress warnings where I know this is safe. Again not preferred as this is going to happen at a bunch of places in our code.
Ignore warnings. In this case we might miss legit warnings just because warnings section will be too noisy.
Ideal solution
Would I be able to somehow set up the warnings in such a way that if hasField is true, then getField will return a non-null? I looked into JetBrains Contract Annotations but doing what I want here seems to be beyond what is supported with #Contract
Code Sample
Here's a minimum working code sample that demonstrates the issue:
import javax.annotation.Nullable;
public class Hello {
private Hello(){}
public static void main(String[] args) {
TestClass test1 = new TestClass(null);
if (test1.hasSample()) {
System.out.println(test1.getSample().equals("abc"));
}
}
}
class TestClass {
private final String sample;
TestClass(String field) { this.sample = field; }
boolean hasSample() { return sample != null; }
#Nullable public String getSample() { return sample; }
}
I get the following warning
Method invocation equals may produce NullPointerException
I'd ideally want to be able to tell IDE that getSample is not null when hasSample is true.
Disclosure I'm IntelliJ IDEA developer responsible for this subsystem
No, it's not possible now. There's no better solution than possible workarounds you already listed, assuming that you cannot change the API. The closest thing we have is the inlining of very trivial methods. However, it works only if:
The methods like hasSample() and getSample() are called from the same class
The called methods cannot be overridden (private/static/final/declared in final class)
E.g. this feature works in the following code:
final class TestClass { // if final is removed, the warning will appear again
private final String sample;
TestClass(String field) { this.sample = field; }
boolean hasSample() { return sample != null; }
#Nullable
public String getSample() { return sample; }
#Override
public String toString() {
if (hasSample()) {
return "TestClass: "+getSample().trim(); // no warning on trim() invocation here
}
return "TestClass";
}
}
For now, I can only suggest refactoring your APIs to Optionals like this:
import java.util.Optional;
public class Hello {
private Hello(){}
public static void main(String[] args) {
TestClass test1 = new TestClass(null);
test1.getSample().ifPresent(s -> System.out.println(s.equals("abc")));
// or fancier: test1.getSample().map("abc"::equals).ifPresent(System.out::println);
}
}
final class TestClass {
private final String sample;
TestClass(String field) { this.sample = field; }
public Optional<String> getSample() { return Optional.ofNullable(sample); }
}

Handling of multiple delegates

I have a java application for which I want to add an extension to execute groovy scripts. So far, so good the parsing, compiling and execution is not the problem!
For reasons of simplification I want to keep the groovy syntax as simple as possible (e.g. no OO-skills required). Furthermore, the groovy scripts shall be able to access library functions which are initialized by the java classes. This is the part where the #Delegate comes into play!
Currently, I came up with two different solutions which are not completely satisfying for me:
GroovyService.java
public interface GroovyService { }
MyService.java
public class MyService implements GroovyService {
public static final MyService INSTANCE = new MyService();
private MyService() { /* ... */ }
public void method1() { /* ... */ }
public void method2() { /* ... */ }
}
Solution #1 - For each delegated method define a method shortcut
ServicesFacade.java
public class ServicesFacade {
public static final ServicesFacade INSTANCE = new ServicesFacade();
#Delegate MyService myService;
// Further #Delegate of services ...
private ServicesFacade() {
myService = MyService.INSTANCE;
}
}
GroovyScript.groovy
def method1 = myService.&method1
def method2 = myService.&method2
if (method1()) {
method2()
}
The code part with the method shortcuts could be prepended to the string result read from the groovy file content. Without the shortcuts it would fulfill my expectations, but I'm looking for a solution for which I don't have to keep track about all the shortcuts.
Solution #2 - Use a list of the service type and the method wildcard access
ServicesFacade.java
public class ServicesFacade {
public static final ServicesFacade INSTANCE = new ServicesFacade();
#Delegate private final List<GroovyService> services = new ArrayList<>();
private ServicesFacade() {
this.services.add(MyService.INSTANCE);
}
public void addService(GroovyService service) {
this.services.add(service);
}
}
GroovyScript.groovy
if (services*.method1()) {
services*.method2()
}
The advantage of this solution is that I can use a fixed member name for any service (services*), but I'm not so impressed by the syntax.
The groovy scripts are used as follows:
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setScriptBaseClass(DelegatingScript.class.getName());
GroovyShell groovyShell = new GroovyShell(compilerConfiguration);
DelegatingScript script = (DelegatingScript) groovyShell.parse(fileContent);
if (script != null) {
script.setDelegate(ServicesFacade.INSTANCE);
scripts.add(script);
}
/* ... */
scripts.forEach(s -> {
s.run();
});
Is there a better way in achieving a direct method call of the delegated methods?
I came up with a good solution in which I wrote an analogous Script class similar to DelegatingScript. It looks as follows:
import groovy.lang.Binding;
import groovy.lang.MetaClass;
import groovy.lang.MissingMethodException;
import org.codehaus.groovy.runtime.InvokerHelper;
import java.util.HashMap;
import java.util.Map;
public abstract class MultiDelegatingScript extends groovy.lang.Script {
private final Map<Object, MetaClass> delegateMap = new HashMap<>();
protected MultiDelegatingScript() {
super();
}
protected MultiDelegatingScript(Binding binding) {
super(binding);
}
public void setDelegate(Object delegate) {
this.delegateMap.put(delegate, InvokerHelper.getMetaClass(delegate.getClass()));
}
#Override
public Object invokeMethod(String name, Object args) {
for (Map.Entry<Object, MetaClass> delegate : this.delegateMap.entrySet()) {
try {
// Try to invoke the delegating method
return delegate.getValue().invokeMethod(delegate.getKey(), name, args);
} catch (MissingMethodException mme) {
// Method not found in delegating object -> try the next one
continue;
}
}
// No delegating method found -> invoke super class method for further handling
return super.invokeMethod(name, args);
}
}
Using this class instead of DelegatingScript will completely fulfill my expectations!

Junit test cases

I am writing test cases for this code.
But I am not able to write junit test cases for this. I am having problem to write junit test cases for this.
Please help to write mockito or junit test case for this.
public class BasicCacheManager implements CacheManager {
private ConcurrentHashMap<String, BasicCache> cacheMap;
private String defaultCache;
public BasicCacheManager() {
this.cacheMap = new ConcurrentHashMap<String, BasicCache>();
}
public BasicCacheManager(List<String> cacheNames) {
this.cacheMap = new ConcurrentHashMap<String, BasicCache>();
addCache(cacheNames);
}
#Override
public BasicCache getCache(){
return getCache(defaultCache);
}
#Override
public BasicCache getCache(String name) {
return cacheMap.get(name);
};
#Override
public void addCache(BasicCache cache) {
cacheMap.put(cache.getName(), cache);
};
#Override
public void removeCache(String name) {
cacheMap.remove(name);
};
#Override
public void removeAll() {
cacheMap = new ConcurrentHashMap<String, BasicCache>();
};
#Override
public boolean cacheExists(String name) {
return cacheMap.containsKey(name);
};
#Override
public void removeElement(String cacheName, String element){
BasicCache cache = getCache(cacheName);
if(cache != null){
cache.remove(element);
}
}
// added final to avoid any child classes from overriding this method
private final void addCache(List<String> cacheNames) {
for (String cacheName : cacheNames) {
BasicCache cache = new BasicCache(cacheName);
addCache(cache);
}
}
}
You don't need mocking here.
Your CUT (class under test) has very clear semantics; and interfaces that basically guide you into writing testcases. What you have to do: create objects of your cache class; and then use its methods to modify it; and asserts to verify.
Example:
#Test
public void testNewCacheIsEmpty() {
BasicCache underTest = new BasicCache();
assertThat(underTest.isEmpty(), is(true));
}
(in case you dont have an isEmpty() yet, you could add that one as package-protected method; just to allow for such tests).
Then you write other tests; for example that make sure that adding a certain cache-key ... actually does what you expect that to do.
So, the primary thing to understand here: you should design your whole cache so that you can test it ... without knowing what exactly it is doing.
Of course, you could create a mocked ConcurrentHashMap object and pass that into your class; to verify that exactly those calls that you expect for some operation to take place really happen. But that means: testing implementation details. And you want to avoid that if possible.
And just for the record: your field defaultCache doesn't make any sense in the code you are showing. It is null initially, there is no setter for it; so it has absolutely no purpose.

Allowing object construction only from some packages

I work on a game-like system. Users can submit .class and .java files for customized behaviour. Some objects are delivered to the user via callback, but if the user can construct these object himself (with custom parameters), it would mean an advantage to him. I will disallow reflection for the user and seal my packages. I can get this working if I abandon all package structure (and make the constructors package-private), but I would like not to do so.
Here is an example:
sscce.mycode.a.SomeClass.java:
package sscce.mycode.a;
import sscce.mycode.b.RestrictedObject;
import sscce.usercode.SomeUserClass;
public class SomeClass {
public static void main(String[] args) {
SomeUserClass userClass=new SomeUserClass();
// If I can create it from here, anyone can...
RestrictedObject object=new RestrictedObject();
userClass.someMethod(object);
}
}
sscce.mycode.b.Interface.java:
package sscce.mycode.b;
public interface Interface {
public void someMethod(RestrictedObject restrictedObject);
}
sscce.mycode.b.RestrictedObject.java:
package sscce.mycode.b;
public class RestrictedObject {
public RestrictedObject() {}
}
sscce.usercode.SomeUserClass.java:
package sscce.usercode;
import sscce.mycode.b.Interface;
import sscce.mycode.b.RestrictedObject;
public class SomeUserClass implements Interface {
#Override
public void someMethod(RestrictedObject restrictedObject) {
// It receives an instance, but cannot create it.
System.out.println("Got "+restrictedObject);
}
}
Motivation: Having everything in one package sounds messy...
Does anyone have ideas on how to accomplish this without flattening the packages?
Thanks in advance for any solutions, ideas or comments, Till
You could do it the following way, however you should carefully consider if you really want to use this approach as it is very slow and quite frankly, bad practice.
I'll put it up anyway as to how you can do it:
public final class Secured {
private static final Set<Class<?>> allowedCallers = new HashSet<>();
static {
allowedCallers.add(Allowed.class);
}
private static final class SecurityManagerExtension extends SecurityManager {
private static final int OFFSET = 4;
#Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
}
private Class<?> getCaller() {
try {
return getClassContext()[OFFSET];
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
}
private Secured() {
// protect against reflection attack
Class<?> caller = new SecurityManagerExtension().getCaller();
if (!this.getClass().equals(caller)) {
throw new IllegalStateException();
}
System.out.println("Secured instance constructed!");
}
public static Secured createInstance() {
// this gets the class name of the calling class
Class<?> caller = new SecurityManagerExtension().getCaller();
if (allowedCallers.contains(caller)) {
System.out.println("Created instance by '" + caller + "'!");
return new Secured();
} else {
System.out.println("No instance created because call was made by '" + caller + "'!");
return null;
}
}
}
Note the final keyword on the class to prevent subclassing. If you need to subclass the class yourself, move the final keyword to the factory method.
Also note that this is not protected against serialization attacks.

Class for Strong References in Java, for anonymous classes

I want a hard reference class in my Java code, but, of course, there isn't one. Is there some other way to do what I want, or should I make my own class?
This comes up with anonymous classes in methods where I want the anonymous class to set the return value for the method.
For example, given
interface Greeting {
void greet();
}
I want code like the following:
// Does not compile
static void hello(final String who) {
String returnValue;
Greeting hello = new Greeting() {
public void greet() {
returnValue = "hello" + who;
}
};
hello.greet();
System.out.println(returnValue);
}
I can fake it using a list:
static void hello(final String who) {
final List<String> returnValue = new ArrayList<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.add("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.iterator().next());
}
But I want to not use a list. I can write a StrongReference class that solves this:
static class StrongReference<T> {
private T referent;
public void set(T referent) {
this.referent = referent;
}
public T get() {
return referent;
}
}
which makes my method clearer:
static void hello(final String who) {
final StrongReference<String> returnValue = new StrongReference<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.set("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.get());
}
For my contrived example, I could have greet() return a String, but I'm working with much more complex classes, where the setting is deep within a database call that the base class manages. The instances have many different types they want to return, so I've just been using the List trick.
My questions are: Is there a better way to do this? What's wrong with my StrongReference class? Has anyone written a StrongReference in a library somewhere?
If you want something from the standard API, perhaps an AtomicReference would do?
It has void set(V value) and a V get() methods. Unless you have multiple threads involved, just see the synchronization mechanism as a bonus ;-)
A common idiom
final String[] result = { null };
result[0] = ...;
Looks good but I think you should make some kind of synchronization since another thread might set the value.

Categories

Resources