Here is my sample java code:
public class Test {
public static void main(String[] args) {
methodDepth0(
()->
methodDepth1(
()->
methodDepth2()
)
);
}
static Object methodDepth2() {
return null;
}
interface MyIF {
void call();
}
static void methodDepth0(MyIF myIf){
myIf.call();
}
interface MyIF2 {
void call();
}
static void methodDepth1(MyIF2 myIf2){
myIf2.call();
}
}
When I open call hierarchy of method methodDepth2() from Eclipse(4.4),
open call hierarchy stop searching next caller:
What I expect is like opening call hierarchy of method methodDepth1() which show until the main method.
From what I can tell the lack of call hierarchy depth is due to (re)evaluation of code at runtime. It is explained in 15.27.4 Run-Time Evaluation of Lambda Expressions in the Java Language Specification.
At run time, evaluation of a lambda expression is similar to evaluation of a class instance creation expression, insofar as normal completion produces a reference to an object. Evaluation of a lambda expression is distinct from execution of the lambda body.
As the second picture clearly shows, Eclipse is able to trace the call hierarchy through the method call myIf.call() inside methodDepth0. This is correct, because the (outer) lambda implements method MyIF.call().
The fact that the same pattern does not work in the next nesting level looks like a bug. Please consider filing a bug for JDT/UI. TIA.
Just note, that for lambdas implementing library types like Consumer<T>, the number of callers into accept(T) in a workspace may easily become unmanageable, similar to any call hierarchy through, e.g, Runnable.run() - but that doesn't question the general usefulness of call hierarchies through lambdas.
Related
Q1 : (removed)
Q2 : try-with-resource to create own resource implement AutoCloseable interface and override close() method.
From javadoc
Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
So, here I created a simple program MyAuto.java
class Demo implements AutoCloseable {
public void show() {
System.out.println("show");
}
public void close() {
System.out.println("close from demo");
}
}
class MyAuto {
public static void main(String[] args) {
try(Demo d = new Demo()) {
int x = 10/0;
d.show();
}catch(ArithmeticException e) {
System.out.println(e);
}
}
}
This program runs fine. :) and giving output
close from demo : as expected, no matters exception occurs, d will be closed.
But my question is I didn't write any code that close this resource, I simply put a print statement. What here actually closing a resource mean ? Assigning null to reference variable of resource or anything else ?
Or JVM runs any other method after running close() behind the scene.
And finally the most important question..
Q3 : In the above scenario if I add my own interface AutoCloseable
interface AutoCloseable {
void close() throws Exception;
}
It gives compile time error on compiling MyAuto.java
error: incompatible types: try-with-resources not applicable to variable type
try(Demo d = new Demo()) {
^
(Demo cannot be converted to AutoCloseable).
So, please give me answer why it's happening. Why can't we create and use our own Interfaces instead of provided by java. What is difference between my interface and the one predefined, although both are same.
What is difference between my interface and the one predefined, although both are same.
They're not the same. Not by a long shot.
The AutoCloseable required for try-with-resources is java.lang.AutoCloseable. Your custom AutoCloseable doesn't come from that package, so Java isn't going to respect it.
Above all, introducing that would not be the best approach, since it'll only lead to confusing semantics and a bad experience later down the road, even if you elected to have your interface extend java.lang.AutoCloseable for whatever reason.
In the same vein...
...I didn't write any code that close this resource, I simply put a print statement. What here actually closing a resource mean ? Assigning null to reference variable of resource or anything else ? Or JVM runs any other method after running close() behind the scene.
The interface can't enforce anything like that. All it can do is provide a mechanism that, if well-implemented, will behave as you expect.
I try to do the following refactoring steps in Eclipse IDE (JDT) and can not find the required refactoring and can not remember the name of all of the steps. I checked the refactoring at SourceMacking and do not find the correct one.
Let's take for example the following scenario:
class A {
method(B b) {
doSomethingWithA();
b.doSomethingWithB();
}
[...]
}
class B {
[...]
}
1) Make method static (missing name of the refactoring?):
class A {
static method(A a, B b) {
a.doSomethingWithA();
b.doSomethingWithB();
}
[...]
}
class B {
[...]
}
2) Move method:
class A {
[...]
}
class B {
static method(A a, B b) {
a.doSomethingWithA();
b.doSomethingWithB();
}
[...]
}
3) Convert to instance method:
class A {
[...]
}
class B {
method(A a) {
a.doSomethingWithA();
doSomethingWithB();
}
[...]
}
So anyone knowing something to do this step by step in Eclipse or do know the name of the refactoring is welcome. The goal is to have IDE support for every step.
Unfortunately, Eclipse's refactoring functionality is not as complete as other IDEs (for example Jetbrains' IntelliJ). I'll include instructions on how to perform each of the refactorings you requested with both IntelliJ and Eclipse.
With IntelliJ
Make Method Static
Move Instance Method
Convert to Instance Method
With Eclipse
Make Method Static: Eclipse doesn't directly support it, but we can achieve this using two other refactorings.
1.1. Introduce Indirection
Result
public static void method(A a, B b) {
a.method(b);
}
public void method(B b){
doSomethingWithA();
b.doSomethingWithB();
}
1.2. Inline
Result
public static void method(A a, B b) {
a.doSomethingWithA();
b.doSomethingWithB();
}
Move Static Members
Convert to Instance Method: Now, this is where it gets tricky. If you want to go from step 1 to step 3, you could just use Eclipse's Move Method and it'll handle everything perfectly fine. However, there are no ways that I know of to go from step 2 to step 3 using Eclipse's automated refactorings.
After having learned the refactoring is called 'Convert to Instance Method' I searched the bug database of Eclipse JDT and I found bad news:
Bug 10605
Bug 118032
Bug 338449
So basically it is a Won't-Fix noone cares feature request and so it might be time that I also switch to IntelliJ. I have to contemplate about this... .
Emond Papegaaij suggested in the discussion of Bug 118032 a work around:
A simple workaround is to create the static method, call this static method from the method you want to become static and inline the method call. This works for me in 4.3.1.
This is interesting but again would not be an automatic refactoring and defeat the purpose of refactoring in the first place. Adding someone's own code introduce the chance of failure and requires the rerun of the test-suite resulting in no chance of safely refactoring legacy code.
I have a peculiar requirement where I need ensure that only a particular method from one class is allowed to call a public (non-static) method from a second class. Inheritance cannot be used.
One option is to use StackTrace as follows:
ClassA.java
package org.rnd.stack;
public class ClassA {
public void methodA() throws IllegalAccessException {
Exception fake = new Exception("FAKE-IGNORE");
StackTraceElement[] stack = fake.getStackTrace();
StackTraceElement st = stack[1];
if ("org.rnd.stack.ClassB".equals(st.getClassName())
&& "methodB".equals(st.getMethodName())) {
System.out.println("You are allowed to call");
} else {
throw new IllegalAccessException("You are not allowed to call");
}
}
}
ClassB.java
package org.rnd.stack;
public class ClassB {
public void methodB() throws IllegalAccessException {
new ClassA().methodA();
}
public void illegalMethod() throws IllegalAccessException {
new ClassA().methodA();
}
public static void main(String[] args) {
try {
new ClassB().methodB();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now the above solution works fine, but due to quality control in code audit I need to come up with another (or rather) better solution. Is there a better way to achieve this?
The right thing to do would be to revisit your requirement. A method that can only be called by certain other code paths is not compatible with public. The general best practice is to use package-private to prevent external callers, and accept that any code in the package could call the method, but won't because you or your team is auditing it.
Method visibility is ultimately not a secure solution to preventing execution; someone has your .class files and the ability to execute them on a machine, they can do just about anything they want. You shouldn't spend too much time trying to lock down method calls. Instead, document the intent of the method clearly (e.g. "Helper function for methodB(), please do not use elsewhere.") and trust the people developing with you know what they're doing. You can even give the method a clear name, like dangerousMethodBForInternalUseOnly() if you really want to beat people over the head about it.
You may also be interested in dependency-injection, which is a design pattern that uses the type system to protect (not prevent) people from executing dangerous code. Here's a couple of talks on Guice, a popular DI framework, that goes into more detail about the concept:
Google I/O 2009 - Big Modular Java with Guice
Java on Guice: Dependency Injection, the Java Way
All of that said, as an academic exercise here's one option for restricting method invocation to a fixed number of codepaths - rely on a shared secret. Add an Object secret field to your locked-down method, and cause the method to fail if the passed secret does not match a hard-coded value (private static final Object SECRET = new Object()). You can then use other mechanisms to share the secret only to code paths you allow (e.g. have a static initializer in your locked-down class publish it to classes you explicitly trust).
Obviously this can still be worked-around by a malicious developer, and it's pretty gross, but it would provide some sort of locking behavior assuming you can trust your locked-down class won't be changed without your knowledge.
A way to improve you method is that you don't need to create an exception to get the stacktrace, you can use the thread methods.
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Also maybe you want to use the class instead of handwriting the package. For example:
if (ClassB.class.getName().equals(st.getClassName())
&& "methodB".equals(st.getMethodName())) {
System.out.println("You are allowed to call");
} else {
throw new IllegalAccessException("You are not allowed to call");
}
Apart from that I don't know how you can do it better without changing your logic or using inheritance.
Pass caller as an argument and check if the caller is instanceof required class - multithreaded solution, cannot bypass by reflecion.
Get thread stack dump and check top entry - weird, heavy but possible
Create proxy - but that will be overheaded variation of solution 1.
You may be able to satisfy this requirement by using the class Class method getEnclosingMethod(). This is how it works (docs here):
If this Class object represents a local or anonymous class within a method, returns a Method object representing the immediately enclosing method of the underlying class.
The signature for methodA() should be changed to accept a Class object as parameter.
public void methodA(Class c) { }
The legal method from ClassB should create an anonymous class object, and pass its class as argument to methodA().
public void methodB() throws IllegalAccessException, NoSuchMethodException {
new ClassA().methodA(new Object(){}.getClass());
}
Then methodA() should check if the class enclosing method is indeed methodB() from ClassB.
public void methodA(Class c) throws IllegalAccessException, NoSuchMethodException {
if (c.getEnclosingMethod().equals(ClassB.class.getMethod("methodB"))) {
System.out.println("You are allowed to call");
} else {
throw new IllegalAccessException("You are not allowed to call");
}
}
Disadvantages:
You must instantiate a new object every time you call methodB(). This may get expensive depending on how many times you do it. Instead, you could create a local class inside methodB() so there is no object creation overhead:
public void methodB() throws IllegalAccessException, NoSuchMethodException {
class Local {};
new ClassA().methodA(Local.class);
}
You need to handle NoSuchMethodException and change the code if methodB() name changes;
Someone with access to the code could still modify methodB() to return the anonymous object class to another method, and use it to call methodA() from there. So this is not a perfect solution, but may be enough for your use case.
I'm building a parser for a compiler, and what I would like to have a class (static) method for each term the parser finds. This method should return a regular expression which can be used to determine whether the token that the Scanner provided is that term and express it as a boolean value. It should be a static method that all derivative classes are guaranteed to have.
Unfortunately, the Java language does not take kindly to this kind of method extension. The code would either not compile, or reference the wrong edition of the method. I'm sure I'll come up with a few workarounds myself, probably involving reflection or a careful HashMap; but this isn't the first time I've run into a problem like this one, and I'm curious. Has anyone else here come up with a solution that provides passable extensibility of static methods?
Okay, let met clarify. I am not looking for a why-doesn't-this-compile, nor am I looking for a how-do-I-make-this-work. I am looking for a method by which I can check a method, which does not require the class to yet be instantiated, which can be relied upon to exist for any extending class. And, it needs to work in my weapon of choice for this project, that is, Java.
As we all know that what I am discussing is in fact not a static method (pardon me, I thought I was clear about that), there is no code to show you; and what I do have is largely tangential. What I have come up with is this, in an abstract constructor:
public Item(String token) {
if(!check(token)) {
throw new MismatchException(this.getClass() + " cannot be instantiated for \"" + token + "\"");
}
this.setData(derive(token));
}
public abstract boolean check(String token);
Meanwhile, creation of each token (and in this instance, addition to the abstract parse tree) goes like this (though I believe that it's still in need of a little polishing):
for(Sting token : tokenList) {
for(Class<?> cls : buildables) {
try {
Constructor constructor = cls.getConstructor(String.class);
result.add((Buildable)constructor.newInstance(c.toString()));
} catch(InvocationTargetException ex) {
//"MismatchException" is my own creation, for this exact purpose
if(ex.getTargetException() instanceof MismatchException)
continue;
} catch (Exception ex) {
//Again, a point for polishing:
ex.printStackTrace();
continue;
}
}
}
So, the problem is solved, as long as all extensions fit those parameters. If you have another suggestion on how this can be done, I'm game for it.
As an addendum, for those who really want to see the code of my current project, you can grab everything completed (and pushed) from github at https://github.com/MichaelEricOberlin/Builder-Tutorial . It's of course meant to be public anyway.
Edit (David Wallace):
So we have a class Foo with a method public static void bar() - or possibly a different signature. Then we have subclasses RedFoo, GreenFoo and BlueFoo each with its own version of public static void bar(). Obviously, this is illegal in Java. The question is how to work around this.
I solved it more or less as follows:
A class Symbol for terminal symbols (one RegexSymbol suffices) and nonterminal symbols (NonTerminalSymbol, SequenceSymbol, AlternativesSymbol, ...). The child classes may be package local.
A class Token with a field Symbol, and a start and end position: a symbol occurrence.
A class Grammar which has factory methods for symbols.
Grammar myGrammar = new Grammar() {
Symbol op = regex("\\+|-|\\*|/");
Symbol number = regex("\\d+");
Symbol expr = nonterminal();
{
define(expr,
alternatives(seq(number, op, expr),
number));
}
};
Not sure, how this maps on your case. But I separate grammar (Symbol) from the AST abstract syntax trees or parsed token occurrences.
The latest security breach in Java7, where a applet can execute untrusted code on users machine. More information is available at http://www.h-online.com/security/features/The-new-Java-0day-examined-1677789.html.
But the question I have is: It is mentioned that all this is possible due to the execute() method introduced in Expression class. But there is nothing special that it does, which was not possible in previous versions. Here is the source:
#Override
public void execute() throws Exception {
setValue(invoke());
}
and for getValue() which exists since java1.4:
public Object getValue() throws Exception {
if (value == unbound) {
setValue(invoke());
}
return value;
}
getValue() does everything that execute() does. Then why so much fuss about the execute method??
If you look closely, the exploit code also calls .getValue(). Clearly, the vulnerability lies within invoke. execute is essentially a public interface to call the private invoke.
I reported a bug several years ago where the access checking in Expression isn't identical to the compiler's. Possibly this is another example.