@CallerSensitive as public API ?

Dr Heinz M. Kabutz heinz at javaspecialists.eu
Wed Jun 26 01:10:51 UTC 2013


Hi Peter,

here is another use case, where someone might want to use this:

3 - in a static context, find out what the class is that you are in.

For example, if you want to create a logger, instead of doing this:

private static final Logger log = Logger.getLogger(SomeClass.class);

we could instead have a magic method that figures out what class this is 
being called from and then sets the class automatically.

There are two other ways to do this, but they are a lot slower than 
Reflection.getCallerClass():

1. http://www.javaspecialists.eu/archive/Issue137.html - create an 
exception and figure out who the calling class is

2. Or we can use the SecurityManager to get us a stack of contexts.

For example, in the exercises for my courses, some students had problems 
with the JUnit plugin.  So each test case also contains the main method, 
but it is always the same:

    public static void main(String[] args) {
        UnitTestRunner.run();
    }

My UnitTestRunner then depends on the security manager to decide what 
the actual class is and then uses the JUnit4TestAdapter to call the methods:

import junit.framework.*;
import junit.textui.*;

public class UnitTestRunner {
    private static void run(Class clazz) {
        System.out.println("Running unit tests for " + clazz);
        TestRunner.run(new JUnit4TestAdapter(clazz));
    }

    public static void run() {
        MySecurityManager sm = new MySecurityManager();
        Class clazz = sm.getClassContext()[2];
        run(clazz);
    }

    private static class MySecurityManager extends SecurityManager {
        public Class[] getClassContext() {
            return super.getClassContext();
        }
    }
}

Works like a charm.  Fortunately this is not affected by the 
Reflection.getCallerClass() bug.

Just my 2c :-)

Regards

Heinz
-- 
Dr Heinz M. Kabutz (PhD CompSci)
Author of "The Java(tm) Specialists' Newsletter"
Oracle Java Champion 2005-2013
JavaOne Rock Star Speaker 2012
http://www.javaspecialists.eu
Tel: +30 69 75 595 262
Skype: kabutz



Peter Levart wrote:
> Hi,
>
> I know that @CallerSensitive annotation was introduced to bring some 
> order to JDK internal plumbings. It's scope was to support JDK 
> internal usage, so it's use is limited to classes loaded by bootstrap 
> or extension class-loaders. In JDK-internal code it is used mainly for 
> implementing security-sensitive decisions. But since the 
> sun.reflect.Reflection.getCallerClass(int) was public and 
> unrestricted, it found it's way out into user code, where at least I 
> know that it is used in two areas:
>
> 1 - to locate callers in the whole call-stack so that their location 
> in class-path can be reported (Log4J is an example)
> 2 - to locate immediate caller so that some resources associated with 
> it can be located and used (for example localization data in GUI 
> applications)
>
> I don't know how wide-spread 1st usecase is, but the 2nd is common, 
> since it's use enables APIs that need not explicitly pass-in the 
> calling class in order to locate resources associated with it (and/or 
> the class-loader of it). So it would be nice to have such supported 
> API in JDK8 at least.
>
> I'm asking here, to hear any arguments against making such API 
> supported and public. Are there any security or other issues? If there 
> aren't, what steps should be taken to introduce such API in the JDK8 
> timeframe? I'm thinking of a no-arg method, say j.l.Class.getCaller() 
> and moving @CallerSensitive to a supported package + enabling it to 
> mark methods in any class (not just system and ext classes)...
>
> Regards, Peter
>
>



More information about the core-libs-dev mailing list