Separate logging for JPMS module/layer
Luke Hutchison
luke.hutch at gmail.com
Fri Oct 5 20:45:36 UTC 2018
On Fri, Oct 5, 2018 at 1:58 PM Ralph Goers <rgoers at apache.org> wrote:
> I didn’t write this particular test. I will have to find it.
>
I'm curious to see the test as well, especially to see what the
"defaultJava8" test is. Is that a method for getting the stack frames using
Exception::getStackTrace or something?
On Fri, Oct 5, 2018 at 11:55 AM David Lloyd <david.lloyd at redhat.com> wrote:
> Something to consider is _how_ the StackWalker is used. It's
> potentially quite expensive in that it produces a Stream in its full
> usage mode. Have you compared using the stream + lambda approach
> versus extracting the stream iterator and iterating in the classic
> Java fashion? I doubt it would make the benchmark competitive, but it
> might help a little bit.
In my own code, I used StackWalker::forEach rather than StalkWalker::walk,
since the stream API has such high overhead. Even lambdas have a high
startup overhead for some reason (I think it was 20ms of incurred latency
when you first use a lambda, last time I measured it?), but at least
forEach should deliver much higher throughput than walk.
The code I'm using currently is below. I have a few questions:
(1) Is it correct to try both StackWalker and SecurityManager first with
doPrivileged, and then if that fails, without doPrivileged? (i.e. I think
it is possible for doPrivileged to fail when non-doPrivileged doesn't fail,
*or* vice versa, depending on the security configuration?) -- sorry for the
newbie question re. JVM security, I'm having a hard time getting my head
around it...
(2) Is it reasonable to fail over from StackWalker to SecurityManager? Or
if StackWalker fails due to security limitations, will SecurityManager
always fail due to the same security limitations? (Are their security
models a 1:1 match?)
(3) Under what circumstances can StackWalker and/or SecurityManager obtain
more information about a stacktrace than Exception::getStackTrace?
----
private static final class CallerResolver extends SecurityManager {
@Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
}
}
private static Class<?>[] getCallStack() {
// Try StackWalker (JDK 9+)
PrivilegedAction<Object> stackWalkerAction = new
PrivilegedAction<Object>() {
@Override
public Object run() {
List<Class<?>> stackFrameClasses = new ArrayList<>();
StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
.forEach(sf ->
stackFrameClasses.add(sf.getDeclaringClass()));
return stackFrameClasses.toArray(new Class<?>[0]);
}
};
try {
// Try with doPrivileged()
return (Class<?>[])
AccessController.doPrivileged(stackWalkerAction);
} catch (Exception e) {
}
try {
// Try without doPrivileged()
return (Class<?>[]) stackWalkerAction.run();
} catch (Exception e) {
}
// Try SecurityManager
PrivilegedAction<Object> callerResolverAction = new
PrivilegedAction<Object>() {
@Override
public Object run() {
return new CallerResolver().getClassContext();
}
};
try {
// Try with doPrivileged()
return (Class<?>[])
AccessController.doPrivileged(callerResolverAction);
} catch (Exception e) {
}
try {
// Try without doPrivileged()
return (Class<?>[]) callerResolverAction.run();
} catch (Exception e) {
}
// As a fallback, use getStackTrace() to try to get the call stack
try {
throw new Exception();
} catch (final Exception e) {
final List<Class<?>> classes = new ArrayList<>();
for (final StackTraceElement elt : e.getStackTrace()) {
try {
classes.add(Class.forName(elt.getClassName()));
} catch (final Throwable e2) {
// Ignore
}
}
if (classes.size() > 0) {
return classes.toArray(new Class<?>[0]);
} else {
// Last-ditch effort -- include just this class in the call
stack
return new Class<?>[] { Java9Scanner.class };
}
}
}
More information about the jigsaw-dev
mailing list