RE: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-17 Thread Jeroen Frijters
Nick Williams wrote:
 What if we also added a getStackFrames() method to Throwable? That would
 meet my needs but it would also satisfy what I'm observing is a desire
 to have a new API for this (StackFrame) instead of adding it to
 StackTraceElement. I'm very open to how it's implemented, as long as it
 satisfies my use case. :-)
 
 The stack trace of a Throwable can be filled in on demand when
 getStackTrace() is called the first time, so that the overhead isn't
 incurred when creating and throwing the exception. Presumably, we would
 need to do something similar with getStackFrames(), especially since
 calling it would be less common.
 
 Thoughts on this?

Yes that is reasonable, but I'd add a static method to StackFrame instead. 
Something like StackFrame[] capture(Throwable).

Regards,
Jeroen



Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-17 Thread Peter Levart

On 06/17/2013 08:06 AM, Jeroen Frijters wrote:

Nick Williams wrote:

What if we also added a getStackFrames() method to Throwable? That would
meet my needs but it would also satisfy what I'm observing is a desire
to have a new API for this (StackFrame) instead of adding it to
StackTraceElement. I'm very open to how it's implemented, as long as it
satisfies my use case. :-)

The stack trace of a Throwable can be filled in on demand when
getStackTrace() is called the first time, so that the overhead isn't
incurred when creating and throwing the exception. Presumably, we would
need to do something similar with getStackFrames(), especially since
calling it would be less common.

Thoughts on this?

Yes that is reasonable, but I'd add a static method to StackFrame instead. 
Something like StackFrame[] capture(Throwable).


New API could be entirely unrelated to Throwable, if there was support 
for it in native code. Since there would have to be changes to the 
native code anyway to support this, why not create a separate API?


Regards, Peter



Regards,
Jeroen





Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-17 Thread Nick Williams

On Jun 17, 2013, at 1:12 AM, Peter Levart wrote:

 On 06/17/2013 08:06 AM, Jeroen Frijters wrote:
 Nick Williams wrote:
 What if we also added a getStackFrames() method to Throwable? That would
 meet my needs but it would also satisfy what I'm observing is a desire
 to have a new API for this (StackFrame) instead of adding it to
 StackTraceElement. I'm very open to how it's implemented, as long as it
 satisfies my use case. :-)
 
 The stack trace of a Throwable can be filled in on demand when
 getStackTrace() is called the first time, so that the overhead isn't
 incurred when creating and throwing the exception. Presumably, we would
 need to do something similar with getStackFrames(), especially since
 calling it would be less common.
 
 Thoughts on this?
 Yes that is reasonable, but I'd add a static method to StackFrame instead. 
 Something like StackFrame[] capture(Throwable).
 
 New API could be entirely unrelated to Throwable, if there was support for it 
 in native code. Since there would have to be changes to the native code 
 anyway to support this, why not create a separate API?

I'm not sure who's misunderstanding who. :-)

If some third party code that I have no control over throws an exception and I 
catch that exception, or some other code catches the exception and passes it to 
my code (because my code is a logging framework), I need to get the 
StackFrame[] for _when the exception was thrown_. Not the StackFrame[] related 
to my current method execution. How can that possibly be entirely unrelated to 
throwable?

The way I understand Jereon's suggestion, I'm thinking StackFrame would look 
like this:

public final class StackFrame {
 public Executable method();
 public String getFileName();
 public int getLineNumber();
 /** Shortcut for getModifiers() and Modifiers.NATIVE */
 public int isNativeMethod();
 /** Format exactly like StackTraceElement#toString() */
 public String toString();

 /** Gets current executing stack with number of frames skipped and max length 
*/
 public static StackFrame[] capture(int skipFrames, int maxLength, boolean 
includeSourceInfo);
 /** Gets current executing stack with no frames skipped and no max length */
 public static StackFrame[] capture();
 /** Gets stack from when Throwable was created. */
 public static StackFrame[] capture(Throwable t);
}

But perhaps I am missing something.

Nick

Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-17 Thread Peter Levart

On 06/15/2013 09:59 PM, Nick Williams wrote:

On Jun 15, 2013, at 2:22 PM, Remi Forax wrote:


Could you be a little more clear why you need a class for your logging API, 
exactly, why the class name is not enough for logging purpose ?

Certainly. Log4j 2 offers extended stack trace patterns. When exceptions or 
stack traces are logged, or when displaying the location that the logging statement 
originated from, the stack trace/log also reveals the resource (JAR file, directory, 
etc.) that the class was loaded from and the implementation version from the package the 
class is in. This helps reveal possible class loading issues (among other things), which 
can be an extremely valuable tool when troubleshooting problems with an application.

Log4j 2 accomplishes this by getting the class associated with a 
StackTraceElement (as outlined below), and then 1) getting the Package from the 
Class and the version from the Package, and 2) getting the ProtectionDomain 
from the Class, getting the CodeSource from the ProtectionDomain, and getting 
the JAR/URL from the CodeSource. The last two parts are easy. It's getting the 
Class from the StackTrace that is extremely inefficient if not done right. Java 
8 took away the best way we had found to do that (which, admittedly, was 
because we were relying on a non-standard class, which isn't recommended).



On 06/17/2013 08:12 AM, Peter Levart wrote:
New API could be entirely unrelated to Throwable, if there was support 
for it in native code. Since there would have to be changes to the 
native code anyway to support this, why not create a separate API? 


If I understand this correctly, one part of your code is displaying the 
resource location of each method's declaring class in the stack trace 
when such extended stack trace is configured. Therefore you need this 
API to capture the class-enriched-stack-trace at the time the Throwable 
instance is constructed. No special Throwable-unrelated API to return 
the stack trace would be suitable for this purpose then.


But for the purpose of displaying the resource location of the class 
invoking the logging API, you don't need the entire stack trace, just 
the immediate caller class, right? When @CallerSensitive internal 
annotation was introduced (and Reflection.getCallerClass(int frames) was 
dropped), there was some debate about possible introduction of public 
API that could be used to reveal the caller's class. Perhaps there's 
still time to create such API for JDK8? At least one part of your 
logging functionality would be covered with such API.


Suppose the API to obtain the immediate caller class (j.l.Class object) 
was public and fast, so you could do that for each call to the logging 
API eagerly (after initial check for logging level). Now, could you 
delay the evaluation of extended stack trace pattern to the latest 
time possible, when you must format the stack-trace? Would calling 
Class.forName(name, false, classLoader) for each individual 
StackTraceElement, using the ClassLoader of the caller class, still 
present a performance problem? You would only get locations for classes 
that the caller has access to, so no inaccessible information could be 
revealed.


Regards, Peter



Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-17 Thread Nick Williams

On Jun 17, 2013, at 1:55 AM, Peter Levart wrote:

 On 06/15/2013 09:59 PM, Nick Williams wrote:
 On Jun 15, 2013, at 2:22 PM, Remi Forax wrote:
 
 Could you be a little more clear why you need a class for your logging API, 
 exactly, why the class name is not enough for logging purpose ?
 Certainly. Log4j 2 offers extended stack trace patterns. When exceptions 
 or stack traces are logged, or when displaying the location that the logging 
 statement originated from, the stack trace/log also reveals the resource 
 (JAR file, directory, etc.) that the class was loaded from and the 
 implementation version from the package the class is in. This helps reveal 
 possible class loading issues (among other things), which can be an 
 extremely valuable tool when troubleshooting problems with an application.
 
 Log4j 2 accomplishes this by getting the class associated with a 
 StackTraceElement (as outlined below), and then 1) getting the Package from 
 the Class and the version from the Package, and 2) getting the 
 ProtectionDomain from the Class, getting the CodeSource from the 
 ProtectionDomain, and getting the JAR/URL from the CodeSource. The last two 
 parts are easy. It's getting the Class from the StackTrace that is extremely 
 inefficient if not done right. Java 8 took away the best way we had found to 
 do that (which, admittedly, was because we were relying on a non-standard 
 class, which isn't recommended).
 
 
 On 06/17/2013 08:12 AM, Peter Levart wrote:
 New API could be entirely unrelated to Throwable, if there was support for 
 it in native code. Since there would have to be changes to the native code 
 anyway to support this, why not create a separate API? 
 
 If I understand this correctly, one part of your code is displaying the 
 resource location of each method's declaring class in the stack trace when 
 such extended stack trace is configured. Therefore you need this API to 
 capture the class-enriched-stack-trace at the time the Throwable instance is 
 constructed. No special Throwable-unrelated API to return the stack trace 
 would be suitable for this purpose then.

Yes, this is correct. This is the primary use case that needs satisfying.

 But for the purpose of displaying the resource location of the class 
 invoking the logging API, you don't need the entire stack trace, just the 
 immediate caller class, right? When @CallerSensitive internal annotation was 
 introduced (and Reflection.getCallerClass(int frames) was dropped), there was 
 some debate about possible introduction of public API that could be used to 
 reveal the caller's class. Perhaps there's still time to create such API for 
 JDK8? At least one part of your logging functionality would be covered with 
 such API.

I would love for this to be part of the public API, but since it's 
annotation-based we wouldn't be able to use it for probably six or seven years. 
For the foreseeable future Log4j must compile on Java 6.

 Suppose the API to obtain the immediate caller class (j.l.Class object) was 
 public and fast, so you could do that for each call to the logging API 
 eagerly (after initial check for logging level). Now, could you delay the 
 evaluation of extended stack trace pattern to the latest time possible, 
 when you must format the stack-trace? Would calling Class.forName(name, 
 false, classLoader) for each individual StackTraceElement, using the 
 ClassLoader of the caller class, still present a performance problem?

Yes. Our _primary_ concern here is locating the source information for 
Throwable stack traces. (In fact, if you want, just forget about the source 
info for the calling class. That's easy. Let's focus JUST on Throwables.) 
Class.forName() is orders of magnitude slower that 
SecurityManager#getClassContext() and Reflection#getCallerClass(). And that's 
not even considering the fact that getClassContext() and getCallerClass() can 
only fill in _part_ of the stack trace (because they don't line up; one is from 
Throwable, the other is from current stack). If we could actually obtain the 
entire stack trace's source info without Class.forName(), it would be even 
faster. That's why I thought the _simplest_ approach would be to add the 
getElementClass() method to StackTraceElement ... it works everywhere.

If the proposed solution is a StackFrame class instead, that's fine by me. I 
just need to be able to get the StackFrame[] for a Throwable.

Nick

Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-16 Thread Nick Williams

On Jun 16, 2013, at 1:25 AM, Jeroen Frijters wrote:

 Nick Williams wrote:
 I'm going to stick by my original assessment that I'm not convinced
 there's a security issue. It's possible that getClassContext() filters
 out classes the caller can't access, but nothing in the documentation
 indicates that's the case, so I'm operating under the assumption that it
 doesn't.
 
 SecurityManager.getClassContext() is not available to unpriviliged callers, 
 so I don't think this a valid argument.

Can you define what is not available to unprivileged callers means a little 
better? We use it in Log4j 2 when getCallerClass() isn't available, and it 
works just fine. I took a look at the Java code, and it's native, so there's no 
check there. (You can't instantiate a SecurityManager unless there's not 
currently a SecurityManager installed _OR_ the installed SecurityManager allows 
the creation (installation privilege isn't checked) of another SecurityManager. 
Is that what you're talking about?) I took a look at the native code, and I 
don't see anything there that would represent a privilege check that I 
recognized, but if I understood what you meant a little better I might see 
where I'm wrong.

 Given the security implications, the serialization issue and the need for 
 weak references, it seems to me that adding this to Throwable would be way 
 too expensive. 

The only expense I'm seeing here is the security implications, and I'm still 
not convinced that they exist. We have all agreed now that making this 
transient is okay, and adding the transient keyword to a field only takes 5 
seconds. And I certainly don't believe that declaring the field as 
WeakReferenceClass? elementClass instead of Class? elementClass takes 
more than 30 seconds longer, but maybe I'm missing something, so that's not 
expensive either.

Also, to be clear, I'm not suggesting adding it to Throwable specifically, I'm 
suggesting adding it to StackTraceElement (which would apply anywhere that a 
stack trace is filled in, including Throwable). A stack trace is filled in with 
one native code method, so updating that method will make this work in 
Throwable, Thread, and anywhere else that you can get a stack trace. I know 
this is a nitpicky distinction, but it could be important.

 
 Adding a new API to collect a stack trace seems like a far better approach.
 
 Here's my off the cuff proposal:
 
 public final class StackFrame {
  public Executable method();
  public String getFileName();
  public int getLineNumber();
 
  public static StackFrame[] capture(int skipFrames, int maxLength, boolean 
 includeSourceInfo);
 }
 

I'm not opposed to the StackFrame class as suggested, it just doesn't meet my 
needs. At all. I can already successfully get this information using the stack 
trace and getClassContext(), so I wouldn't be compelled to switch. I need to 
efficiently get the Class from a stack trace generated by a Throwable, which 
this does not solve. Right now I'm having to resort to getting that Class using 
inefficient methods.

Nick

Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-16 Thread Alan Bateman

On 16/06/2013 15:29, Nick Williams wrote:

On Jun 16, 2013, at 1:25 AM, Jeroen Frijters wrote:


:
SecurityManager.getClassContext() is not available to unpriviliged callers, so 
I don't think this a valid argument.

Can you define what is not available to unprivileged callers means a little 
better? We use it in Log4j 2 when getCallerClass() isn't available, and it works just 
fine. I took a look at the Java code, and it's native, so there's no check there. (You 
can't instantiate a SecurityManager unless there's not currently a SecurityManager 
installed _OR_ the installed SecurityManager allows the creation (installation privilege 
isn't checked) of another SecurityManager. Is that what you're talking about?) I took a 
look at the native code, and I don't see anything there that would represent a privilege 
check that I recognized, but if I understood what you meant a little better I might see 
where I'm wrong.
The main thing is that the hack to extend SecurityManager (so that you 
can call the protected getClassContext method) is unlikely to work when 
there is security manager set. I can't tell what environments you have 
tested with but usually it means setting up the security policy so that 
the code base of your library is granted the permission. Even then you 
might still have an issue because there will likely be frames associated 
with other untrusted code on the stack. Maybe your code attempts to 
create the security manager does do with so privileges enabled, therwise 
everything that could potentially call you would also needed to be 
granted this permission.


-Alan.


Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-16 Thread Nick Williams

On Jun 16, 2013, at 9:29 AM, Nick Williams wrote:

 
 On Jun 16, 2013, at 1:25 AM, Jeroen Frijters wrote:
 
 Nick Williams wrote:
 I'm going to stick by my original assessment that I'm not convinced
 there's a security issue. It's possible that getClassContext() filters
 out classes the caller can't access, but nothing in the documentation
 indicates that's the case, so I'm operating under the assumption that it
 doesn't.
 
 SecurityManager.getClassContext() is not available to unpriviliged callers, 
 so I don't think this a valid argument.
 
 Can you define what is not available to unprivileged callers means a little 
 better? We use it in Log4j 2 when getCallerClass() isn't available, and it 
 works just fine. I took a look at the Java code, and it's native, so there's 
 no check there. (You can't instantiate a SecurityManager unless there's not 
 currently a SecurityManager installed _OR_ the installed SecurityManager 
 allows the creation (installation privilege isn't checked) of another 
 SecurityManager. Is that what you're talking about?) I took a look at the 
 native code, and I don't see anything there that would represent a privilege 
 check that I recognized, but if I understood what you meant a little better I 
 might see where I'm wrong.
 
 Given the security implications, the serialization issue and the need for 
 weak references, it seems to me that adding this to Throwable would be way 
 too expensive. 
 
 The only expense I'm seeing here is the security implications, and I'm still 
 not convinced that they exist. We have all agreed now that making this 
 transient is okay, and adding the transient keyword to a field only takes 5 
 seconds. And I certainly don't believe that declaring the field as 
 WeakReferenceClass? elementClass instead of Class? elementClass 
 takes more than 30 seconds longer, but maybe I'm missing something, so that's 
 not expensive either.
 
 Also, to be clear, I'm not suggesting adding it to Throwable specifically, 
 I'm suggesting adding it to StackTraceElement (which would apply anywhere 
 that a stack trace is filled in, including Throwable). A stack trace is 
 filled in with one native code method, so updating that method will make this 
 work in Throwable, Thread, and anywhere else that you can get a stack trace. 
 I know this is a nitpicky distinction, but it could be important.
 
 
 Adding a new API to collect a stack trace seems like a far better approach.
 
 Here's my off the cuff proposal:
 
 public final class StackFrame {
 public Executable method();
 public String getFileName();
 public int getLineNumber();
 
 public static StackFrame[] capture(int skipFrames, int maxLength, boolean 
 includeSourceInfo);
 }
 
 
 I'm not opposed to the StackFrame class as suggested, it just doesn't meet my 
 needs. At all. I can already successfully get this information using the 
 stack trace and getClassContext(), so I wouldn't be compelled to switch. I 
 need to efficiently get the Class from a stack trace generated by a 
 Throwable, which this does not solve. Right now I'm having to resort to 
 getting that Class using inefficient methods.

What if we also added a getStackFrames() method to Throwable? That would meet 
my needs but it would also satisfy what I'm observing is a desire to have a new 
API for this (StackFrame) instead of adding it to StackTraceElement. I'm very 
open to how it's implemented, as long as it satisfies my use case. :-)

The stack trace of a Throwable can be filled in on demand when 
getStackTrace() is called the first time, so that the overhead isn't incurred 
when creating and throwing the exception. Presumably, we would need to do 
something similar with getStackFrames(), especially since calling it would be 
less common.

Thoughts on this?

Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Nick Williams
Bug 4851444 [1] was filed just over 10 years ago and has languished without so 
much as a comment ever since. I hate to revive something so old, but I'd like 
to see what everyone thinks.

I'm working on the Apache project Log4j2. Our problem is we need to get the 
Class object that belongs to a particular element on the stack trace. We use 
three different methods, failing over from one to the next, in order to get the 
Class object.

1. If sun.reflect.Reflection#getCallerClass(int) exists, we repeatedly call 
it--increasing the depth each time--to fill up a java.util.Stack, then compare 
it to the exception stack trace and match as many of the elements as we can to 
Classes returned by getCallerClass. This is surprisingly fast, but some 
elements don't match and we have to fail over to 3.

2. If sun.reflect.Reflection.getCallerClass(int) does not exist, we create a 
SecurityManager and call getClassContext(), use it to fill up a 
java.util.Stack, and do the same thing we would normally do with 1. This is 
about two times slower than 1--not terrible.

3. If the element in a stack trace doesn't match a class found in methods 1 or 
2, we load the class with the ClassLoader using the class name in the 
StackTraceElement. This is more than TEN TIMES SLOWER than 1--terrible.

As you can see, it greatly benefits us to have some kind of efficient mechanism 
to match a StackTraceElement to a Class, so that's why we resort to using a 
non-public API (with the understanding that we must have backup options since 
this class will not always be present).

Where I came in is when the change was made in 1.8.0-ea-b87 to remove the 
parameter from sun.reflect.Reflection#getCallerClass(). Now getCallerClass() 
can ONLY be used to retrieve the immediate caller, not callers at various 
depth, making method 1 unusable in Java 8. This led me to look for an 
alternative.

Looking at Throwable.java and Throwable.c, getStackTrace() ultimately calls 
JVM_GetStackTraceElement. Looking at jvm.c from Java 6 (I can't find 
JVM_GetStackTraceElement in newer versions of Java), JVM_GetStackTraceElement 
calls CVMgetStackTraceElement. 
CVMgetStackTraceElement, in turn, then gets a copy of the native version of the 
Class object and uses it to populate the StackTraceElement's data. This leads 
me to believe that the task of adding a getElementClass() method to 
StackTraceElement would be as simple as:

1) Adding a new constructor to StackTraceElement to preserve backwards 
compatibility, with the Class being null by default.
2) Add the getStackTraceElement() method and backing private field.
3) Add a CVMID_fieldWriteRef call to set the class to the backing private field.

I'm sure there are some idiosyncrasies I'm missing here, but overall this seems 
like a pretty trivial change. What do people think? Can this be worked in? .NET 
has had this ability since .NET 1.1 with the StackFrame class [2] and the 
StackTrace [3], which contains StackFrames. It provides more than just the 
Class (Type in .NET), it also provides the Method (MethodBase in .NET). It 
would greatly improve the efficiency of certain tasks not only in Log4j, but 
also in many other projects that I have found using getCallerClass() for the 
same purpose.

[1] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4851444
[2] http://msdn.microsoft.com/en-us/library/system.diagnostics.stackframe.aspx
[3] http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx



Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Remi Forax

On 06/15/2013 08:33 PM, Nick Williams wrote:

Bug 4851444 [1] was filed just over 10 years ago and has languished without so 
much as a comment ever since. I hate to revive something so old, but I'd like 
to see what everyone thinks.


Hi Nick,
first 4851444 should be closed in my opinion, given that 1.6 introduces 
the ServiceLoader class which is the way to load implementation of a 
service.

JAXP and JAXB now use the ServiceLoader.

Could you be a little more clear why you need a class for your logging 
API, exactly, why the class name is not enough for logging purpose ?


And about adding a way to store the class in the StackTraceElement, one 
issue is that stack trace element are Serializable, so if an error 
occurs on a server, the exception can be serialized to the client which 
is a really nice feature, but if a stack trace element embed the class 
object, then it means that all the class that are available at server 
side should also be available at client side.

I have no idea how Microsoft solve this issue.

cheers,
Rémi



I'm working on the Apache project Log4j2. Our problem is we need to get the 
Class object that belongs to a particular element on the stack trace. We use 
three different methods, failing over from one to the next, in order to get the 
Class object.

1. If sun.reflect.Reflection#getCallerClass(int) exists, we repeatedly call 
it--increasing the depth each time--to fill up a java.util.Stack, then compare 
it to the exception stack trace and match as many of the elements as we can to 
Classes returned by getCallerClass. This is surprisingly fast, but some 
elements don't match and we have to fail over to 3.

2. If sun.reflect.Reflection.getCallerClass(int) does not exist, we create a 
SecurityManager and call getClassContext(), use it to fill up a 
java.util.Stack, and do the same thing we would normally do with 1. This is 
about two times slower than 1--not terrible.

3. If the element in a stack trace doesn't match a class found in methods 1 or 
2, we load the class with the ClassLoader using the class name in the 
StackTraceElement. This is more than TEN TIMES SLOWER than 1--terrible.

As you can see, it greatly benefits us to have some kind of efficient mechanism 
to match a StackTraceElement to a Class, so that's why we resort to using a 
non-public API (with the understanding that we must have backup options since 
this class will not always be present).

Where I came in is when the change was made in 1.8.0-ea-b87 to remove the 
parameter from sun.reflect.Reflection#getCallerClass(). Now getCallerClass() 
can ONLY be used to retrieve the immediate caller, not callers at various 
depth, making method 1 unusable in Java 8. This led me to look for an 
alternative.

Looking at Throwable.java and Throwable.c, getStackTrace() ultimately calls 
JVM_GetStackTraceElement. Looking at jvm.c from Java 6 (I can't find 
JVM_GetStackTraceElement in newer versions of Java), JVM_GetStackTraceElement 
calls CVMgetStackTraceElement.
CVMgetStackTraceElement, in turn, then gets a copy of the native version of the 
Class object and uses it to populate the StackTraceElement's data. This leads 
me to believe that the task of adding a getElementClass() method to 
StackTraceElement would be as simple as:

1) Adding a new constructor to StackTraceElement to preserve backwards 
compatibility, with the Class being null by default.
2) Add the getStackTraceElement() method and backing private field.
3) Add a CVMID_fieldWriteRef call to set the class to the backing private field.

I'm sure there are some idiosyncrasies I'm missing here, but overall this seems 
like a pretty trivial change. What do people think? Can this be worked in? .NET 
has had this ability since .NET 1.1 with the StackFrame class [2] and the 
StackTrace [3], which contains StackFrames. It provides more than just the 
Class (Type in .NET), it also provides the Method (MethodBase in .NET). It 
would greatly improve the efficiency of certain tasks not only in Log4j, but 
also in many other projects that I have found using getCallerClass() for the 
same purpose.

[1] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4851444
[2] http://msdn.microsoft.com/en-us/library/system.diagnostics.stackframe.aspx
[3] http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx





Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Nick Williams

On Jun 15, 2013, at 2:22 PM, Remi Forax wrote:

 On 06/15/2013 08:33 PM, Nick Williams wrote:
 Bug 4851444 [1] was filed just over 10 years ago and has languished without 
 so much as a comment ever since. I hate to revive something so old, but I'd 
 like to see what everyone thinks.
 
 Hi Nick,
 first 4851444 should be closed in my opinion, given that 1.6 introduces the 
 ServiceLoader class which is the way to load implementation of a service.
 JAXP and JAXB now use the ServiceLoader.

There are really two parts to this bug: what the user needed to accomplish 
(which ServiceLoader accomplishes), and the suggestion for exposing 
getCallerClass() (which has broader implications than just his particular 
use-case).

 
 Could you be a little more clear why you need a class for your logging API, 
 exactly, why the class name is not enough for logging purpose ?

Certainly. Log4j 2 offers extended stack trace patterns. When exceptions or 
stack traces are logged, or when displaying the location that the logging 
statement originated from, the stack trace/log also reveals the resource (JAR 
file, directory, etc.) that the class was loaded from and the implementation 
version from the package the class is in. This helps reveal possible class 
loading issues (among other things), which can be an extremely valuable tool 
when troubleshooting problems with an application.

Log4j 2 accomplishes this by getting the class associated with a 
StackTraceElement (as outlined below), and then 1) getting the Package from the 
Class and the version from the Package, and 2) getting the ProtectionDomain 
from the Class, getting the CodeSource from the ProtectionDomain, and getting 
the JAR/URL from the CodeSource. The last two parts are easy. It's getting the 
Class from the StackTrace that is extremely inefficient if not done right. Java 
8 took away the best way we had found to do that (which, admittedly, was 
because we were relying on a non-standard class, which isn't recommended).

 
 And about adding a way to store the class in the StackTraceElement, one issue 
 is that stack trace element are Serializable, so if an error occurs on a 
 server, the exception can be serialized to the client which is a really nice 
 feature, but if a stack trace element embed the class object, then it means 
 that all the class that are available at server side should also be available 
 at client side.
 I have no idea how Microsoft solve this issue.

Classes are Serializable in Java, so it shouldn't cause a problem with 
serialization. The elementClass property will be properly serialized and 
deserialized. If I understand you correctly, you're expressing concern that 
this could actually be a problem; that we don't want Classes transferred to the 
client and deserialized. The Class class has a special serialized form that is 
unlike other classes and is very efficient. Only a descriptor for the class 
(including its serialVersionUID value) is transmitted, just enough to give the 
endpoint enough information to locate the class. There won't be a performance 
issue here, as far as I can tell. However, I can foresee one potential problem 
when deserializing the StackTraceElement: if the Class isn't on the class path 
on the deserializing JVM. This could be handled two possible ways:

1) Mark the elementClass property on StackTraceElement transient so that it 
isn't serialized.
2) Add a special deserialization rule (not unprecedented by any means) for 
StackTraceElement that says that StackTraceElement will not fail to deserialize 
if the elementClass property can't be deserialized because it couldn't be 
loaded. (This would be my suggestion.)

I'm not sure how .NET handles it either, but it clearly does, as its StackFrame 
class is the equivalent of Serializable.

Nick

 
 cheers,
 Rémi
 
 
 I'm working on the Apache project Log4j2. Our problem is we need to get the 
 Class object that belongs to a particular element on the stack trace. We use 
 three different methods, failing over from one to the next, in order to get 
 the Class object.
 
 1. If sun.reflect.Reflection#getCallerClass(int) exists, we repeatedly call 
 it--increasing the depth each time--to fill up a java.util.Stack, then 
 compare it to the exception stack trace and match as many of the elements as 
 we can to Classes returned by getCallerClass. This is surprisingly fast, but 
 some elements don't match and we have to fail over to 3.
 
 2. If sun.reflect.Reflection.getCallerClass(int) does not exist, we create a 
 SecurityManager and call getClassContext(), use it to fill up a 
 java.util.Stack, and do the same thing we would normally do with 1. This is 
 about two times slower than 1--not terrible.
 
 3. If the element in a stack trace doesn't match a class found in methods 1 
 or 2, we load the class with the ClassLoader using the class name in the 
 StackTraceElement. This is more than TEN TIMES SLOWER than 1--terrible.
 
 As you can see, it greatly benefits us to have 

Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Alan Bateman

On 15/06/2013 19:33, Nick Williams wrote:

:

Looking at Throwable.java and Throwable.c, getStackTrace() ultimately calls 
JVM_GetStackTraceElement. Looking at jvm.c from Java 6 (I can't find 
JVM_GetStackTraceElement in newer versions of Java), JVM_GetStackTraceElement 
calls CVMgetStackTraceElement.
CVMgetStackTraceElement, in turn, then gets a copy of the native version of the 
Class object and uses it to populate the StackTraceElement's data. This leads 
me to believe that the task of adding a getElementClass() method to 
StackTraceElement would be as simple as:

1) Adding a new constructor to StackTraceElement to preserve backwards 
compatibility, with the Class being null by default.
2) Add the getStackTraceElement() method and backing private field.
3) Add a CVMID_fieldWriteRef call to set the class to the backing private field.

I'm sure there are some idiosyncrasies I'm missing here, but overall this seems 
like a pretty trivial change. What do people think? Can this be worked in? .NET 
has had this ability since .NET 1.1 with the StackFrame class [2] and the 
StackTrace [3], which contains StackFrames. It provides more than just the 
Class (Type in .NET), it also provides the Method (MethodBase in .NET). It 
would greatly improve the efficiency of certain tasks not only in Log4j, but 
also in many other projects that I have found using getCallerClass() for the 
same purpose.


Here's a discussion from last year on this topic:

http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-October/011665.html

-Alan.


Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Nick Williams

On Jun 15, 2013, at 3:21 PM, Alan Bateman wrote:

 On 15/06/2013 19:33, Nick Williams wrote:
 :
 
 Looking at Throwable.java and Throwable.c, getStackTrace() ultimately calls 
 JVM_GetStackTraceElement. Looking at jvm.c from Java 6 (I can't find 
 JVM_GetStackTraceElement in newer versions of Java), 
 JVM_GetStackTraceElement calls CVMgetStackTraceElement.
 CVMgetStackTraceElement, in turn, then gets a copy of the native version of 
 the Class object and uses it to populate the StackTraceElement's data. This 
 leads me to believe that the task of adding a getElementClass() method to 
 StackTraceElement would be as simple as:
 
 1) Adding a new constructor to StackTraceElement to preserve backwards 
 compatibility, with the Class being null by default.
 2) Add the getStackTraceElement() method and backing private field.
 3) Add a CVMID_fieldWriteRef call to set the class to the backing private 
 field.
 
 I'm sure there are some idiosyncrasies I'm missing here, but overall this 
 seems like a pretty trivial change. What do people think? Can this be worked 
 in? .NET has had this ability since .NET 1.1 with the StackFrame class [2] 
 and the StackTrace [3], which contains StackFrames. It provides more than 
 just the Class (Type in .NET), it also provides the Method (MethodBase in 
 .NET). It would greatly improve the efficiency of certain tasks not only in 
 Log4j, but also in many other projects that I have found using 
 getCallerClass() for the same purpose.
 
 Here's a discussion from last year on this topic:
 
 http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-October/011665.html
 
 -Alan.

Indeed. Looks like the discussion died somewhat after a while. No conclusion 
was ever made. Based on the discussion it the email, I would add some 
additional observations/behavior that I think should be considered:

1) The elementClass property (getElementClass method) should be the Class that 
matches StackTraceElement's className property. It should not be the type of 
the object that received the method invocation. Perhaps, then, it would be 
better to call it frameClass (getFrameClass), to make it more obvious that it's 
the class for the frame on the stack.

2) If elementClass is made to be the type of the object that received the 
method invocation, then an getMethod() method should also be added so that the 
Class that defined the method that was executed can be obtained. This might 
actually be the most versatile option. However, Method is not Serializable, so 
that must then be considered.

3) I'm okay with making the elementClass transient. I don't have a particular 
need for it to be serialized, and making it transient is the easiest way to 
solve some problems.

4) Vitaly's email said that StackFrame exposes the MethodBase (Method), but not 
the Type (Class). This is correct. I wasn't clear on this earlier. To get the 
frame Type you would use stackFrameInstance.GetMethod().DeclaringType.

5) I do think the elementClass (or whatever) property should be Weak. If a 
particular piece of code (foolishly) hangs on to a StackTraceElement instance, 
it could cause a ClassLoader memory leak, particularly in Java EE containers. 
Making it Weak is the safest approach. Existing code written for earlier 
versions of Java may hang on to StackTraceElements for whatever reason, and 
problems wouldn't begin to arise from that until the code was run on Java 8.

6) I don't think security is a major issue here. There's not a lot you can do 
with a Class instance without involving existing security checks. For example, 
you can inspect the Class's name, Package, CodeSource, etc., but you can't 
invoke methods, manipulate fields, or create an instance of the Class without 
security checks being performed. Let's consider three possible scenarios:

A) A Class loaded by a parent class loader obtains a StackTraceElement 
containing Classes loaded by a child class loader. I don't see a major issue 
here. The obvious scenario is a library loaded by a Servlet container obtaining 
a Class loaded within one of the web application class loaders. It's much more 
likely that this code will be well behaved and already has some kind of power 
over the child class loader anyway.

B) A Class loaded by a child class loader obtains a StackTraceElement 
containing Classes loaded by a sibling class loader. This would obviously be 
the more dangerous scenario (think: one web application accessing another web 
application's classes), but I don't think it's actually possible. I don't think 
a stack trace generated in one class loader can possibly make its way into code 
in a sibling class loader, and I know that an execution stack can't contain 
classes from two sibling class loaders (only from class loaders with 
parent/child relationships).

C) A Class loaded by a child class loader obtains a StackTraceElement 
containing Classes loaded by a parent class loader. There's no issue here. 
Child class loaders can already access classes 

Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Peter Levart


On 06/15/2013 09:59 PM, Nick Williams wrote:

And about adding a way to store the class in the StackTraceElement, one issue 
is that stack trace element are Serializable, so if an error occurs on a 
server, the exception can be serialized to the client which is a really nice 
feature, but if a stack trace element embed the class object, then it means 
that all the class that are available at server side should also be available 
at client side.
I have no idea how Microsoft solve this issue.

Classes are Serializable in Java, so it shouldn't cause a problem with 
serialization. The elementClass property will be properly serialized and 
deserialized. If I understand you correctly, you're expressing concern that 
this could actually be a problem; that we don't want Classes transferred to the 
client and deserialized. The Class class has a special serialized form that is 
unlike other classes and is very efficient. Only a descriptor for the class 
(including its serialVersionUID value) is transmitted, just enough to give the 
endpoint enough information to locate the class.


That's true when  Class objects are serialized with a purpose and intent 
that they will be deserialized in an environment where correct versions 
of those classes are visible by class initiating deserialization. Stack 
trace can contain references to classes that are not visible even by the 
class that constructed the Throwable. By exposing Class objects that 
would otherwise not be obtainable, there could be security issues.



There won't be a performance issue here, as far as I can tell. However, I can 
foresee one potential problem when deserializing the StackTraceElement: if the 
Class isn't on the class path on the deserializing JVM. This could be handled 
two possible ways:

1) Mark the elementClass property on StackTraceElement transient so that it 
isn't serialized.
2) Add a special deserialization rule (not unprecedented by any means) for 
StackTraceElement that says that StackTraceElement will not fail to deserialize 
if the elementClass property can't be deserialized because it couldn't be 
loaded. (This would be my suggestion.)

I'm not sure how .NET handles it either, but it clearly does, as its StackFrame 
class is the equivalent of Serializable.


I think that option #1 is the only realistic option. Who cares about 
classes in the de-serialized stack-trace. The only thing needed is their 
names so that the stack-trace can be printed.


Regards, Peter






Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Peter Levart


On 06/15/2013 11:06 PM, Nick Williams wrote:

B) A Class loaded by a child class loader obtains a StackTraceElement 
containing Classes loaded by a sibling class loader. This would obviously be 
the more dangerous scenario (think: one web application accessing another web 
application's classes), but I don't think it's actually possible. I don't think 
a stack trace generated in one class loader can possibly make its way into code 
in a sibling class loader, and I know that an execution stack can't contain 
classes from two sibling class loaders (only from class loaders with 
parent/child relationships).


Why not?  Consider this hypothetical code:

Parent class loader:

public class A {
public static final A INSTANCE = new A();
final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener 
pcl) { pcs.addPropertyChangeListener(pcl); }

String property;
public void setProperty(String property) {
pcs.firePropertyChange(property, this.property, 
this.property = property);

}
}

Child class loader 1:

static class B implements PropertyChangeListener {
B() {
A a = A.INSTANCE;
a.addPropertyChangeListener(this);
}

@Override
public void propertyChange(PropertyChangeEvent evt) {
StackTraceElement[] st = new Throwable().getStackTrace();
// can we see C.class in 'st' array?
}
}

Child class loader 2:

static class C {
void m() {
A a = A.INSTANCE;
a.setProperty(XYZ);
}
}



Regards, Peter



Re: Thoughts on adding getElementClass() method to StackTraceElement?

2013-06-15 Thread Nick Williams

On Jun 15, 2013, at 5:05 PM, Peter Levart wrote:

 
 On 06/15/2013 11:06 PM, Nick Williams wrote:
 B) A Class loaded by a child class loader obtains a StackTraceElement 
 containing Classes loaded by a sibling class loader. This would obviously be 
 the more dangerous scenario (think: one web application accessing another 
 web application's classes), but I don't think it's actually possible. I 
 don't think a stack trace generated in one class loader can possibly make 
 its way into code in a sibling class loader, and I know that an execution 
 stack can't contain classes from two sibling class loaders (only from class 
 loaders with parent/child relationships).
 
 Why not?  Consider this hypothetical code:
 
 Parent class loader:
 
 public class A {
 public static final A INSTANCE = new A();
 final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
 public void addPropertyChangeListener(PropertyChangeListener pcl) { 
 pcs.addPropertyChangeListener(pcl); }
 String property;
 public void setProperty(String property) {
 pcs.firePropertyChange(property, this.property, this.property = 
 property);
 }
 }
 
 Child class loader 1:
 
 static class B implements PropertyChangeListener {
 B() {
 A a = A.INSTANCE;
 a.addPropertyChangeListener(this);
 }
 
 @Override
 public void propertyChange(PropertyChangeEvent evt) {
 StackTraceElement[] st = new Throwable().getStackTrace();
 // can we see C.class in 'st' array?
 }
 }
 
 Child class loader 2:
 
 static class C {
 void m() {
 A a = A.INSTANCE;
 a.setProperty(XYZ);
 }
 }
 
 
 
 Regards, Peter

Huh. An interesting quandary. And definitely not desirable...

The first thing I would say is that the code you suggest isn't, in my opinion, 
responsible code, and in fact is dangerous. I know some guys over on the 
Tomcat mailing list that would possibly shriek in terror if they saw code like 
this. If an application server (parent class loader) had a class like A that 
allowed actions of one web application (class C) to trigger method calls in 
another web application (class B), nightmarish things would happen. In 
actuality, class A should have different contexts for different class loaders. 
If you write code like this and allow it to be used across sibling class 
loaders in this manner, you are asking for more trouble than you're going to 
get merely by having a Class instance in the StackTraceElement.

In fact, DriverManager is a perfect example. If a web application loads a JDBC 
driver from its WEB-INF/lib, that driver will immediately become visible to 
other web applications, and it will cause a memory leak. There was a recent 
discussion about this on the Tomcat mailing list, and the general tenor was 
DriverManager is hopelessly broken, don't put drivers there, they can only 
safely go in the container's class loader. I could argue that DriverManager 
has already created the very security issue that you propose exists by added a 
Class instance to the StackTraceElement, but that by itself doesn't make it OK 
(broken window syndrome/broken windows theory).

Still, in the scenario you propose there could be bigger security consequences 
than merely having an instance of Class in StackTraceElement. What if 
setProperty() takes an Object instead of a String (class loader leak). MOST 
IMPORTANTLY: What if class B extends SecurityManager, instantiates it (but 
doesn't install it), and calls SecurityManager#getClassContext() from 
B#propertyChange(). The getClassContext() method essential returns the stack 
trace of Classes instead of StackTraceElements.

I'm going to stick by my original assessment that I'm not convinced there's a 
security issue. It's possible that getClassContext() filters out classes the 
caller can't access, but nothing in the documentation indicates that's the 
case, so I'm operating under the assumption that it doesn't. If I'm right, 
there's no harm in StackTraceElement also having a Class instance. But 
understand getClassContext() does not fulfill my use case entirely. I need the 
Classes in a stack trace created when an exception is thrown, too, and 
getClassContext() only gives me those classes in my current executing stack.

Nick