Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggesting improve initialization performance #753

Open
wants to merge 9 commits into
base: v2.8
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*/
public final class LegacyJavaRuntime extends AbstractJavaRuntime {

private static final Timestamp startTime = new LegacyTimestamp(ManagementFactory.getRuntimeMXBean().getStartTime());
private static final Timestamp startTime = new LegacyTimestamp(System.currentTimeMillis());

private final boolean hasSunReflection;
private final Method stackTraceElementGetter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
package org.tinylog.runtime;

import java.lang.StackWalker.StackFrame;
import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.Locale;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
Expand All @@ -30,11 +30,9 @@
@IgnoreJRERequirement
final class ModernJavaRuntime extends AbstractJavaRuntime {

private static final ClassContextSecurityManager securityManager = new ClassContextSecurityManager();

private static final Timestamp startTime = new PreciseTimestamp(
ManagementFactory.getRuntimeMXBean().getStartTime(),
0
System.currentTimeMillis(),
0
);

private final ProcessHandle currentProcess = getCurrentProcess();
Expand All @@ -60,29 +58,14 @@ public Timestamp getStartTime() {

@Override
public String getCallerClassName(final int depth) {
Class<?>[] classes = securityManager.getClassContext();
return classes.length > depth + 1 ? classes[depth + 1].getName() : null;
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
return walker.walk(new ClassNameExtractorByDepth(depth));
}

@Override
public String getCallerClassName(final String loggerClassName) {
Class<?>[] classes = securityManager.getClassContext();
int index = 0;

while (index < classes.length) {
if (loggerClassName.equals(classes[index++].getName())) {
break;
}
}

while (index < classes.length) {
String className = classes[index++].getName();
if (!loggerClassName.equals(className)) {
return className;
}
}

return null;
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
return walker.walk(new ClassNameExtractorByLoggerClassName(loggerClassName));
}

@Override
Expand Down Expand Up @@ -112,27 +95,65 @@ public TimestampFormatter createTimestampFormatter(final String pattern, final L
*
* @return Process handle of current process
*/
@IgnoreJRERequirement
private static ProcessHandle getCurrentProcess() {
try {
return (ProcessHandle) ProcessHandle.class.getDeclaredMethod("current").invoke(null);
} catch (ReflectiveOperationException ex) {
return ProcessHandle.current();
} catch (SecurityException ex) {
InternalLogger.log(Level.ERROR, ex, "Failed to receive the handle of the current process");
return null;
}
}

@IgnoreJRERequirement
private static final class ClassNameExtractorByDepth implements Function<Stream<StackFrame>, String> {
private final int depth;

private ClassNameExtractorByDepth(final int depth) {
this.depth = depth;
}

@Override
public String apply(final Stream<StackFrame> frames) {
return frames.skip(depth)
.findFirst()
.map(new ClassNameMapper())
.orElse(null);
}
}

@IgnoreJRERequirement
private static final class ClassNameExtractorByLoggerClassName implements Function<Stream<StackFrame>, String> {
private final String loggerClassName;

private ClassNameExtractorByLoggerClassName(final String loggerClassName) {
this.loggerClassName = loggerClassName;
}

@Override
public String apply(final Stream<StackFrame> stream) {
return stream.map(new ClassNameMapper()).dropWhile(new Predicate<String>() {
@Override
public boolean test(final String name) {
return !name.equals(loggerClassName);
}
}).skip(1).findFirst().orElse(null);
}
}

/**
* Security manager with accessible {@link SecurityManager#getClassContext()}.
* Mapper for getting the class name from a {@link StackFrame}.
*/
private static final class ClassContextSecurityManager extends SecurityManager {
@IgnoreJRERequirement
private static final class ClassNameMapper implements Function<StackFrame, String> {

/** */
private ClassContextSecurityManager() {
private ClassNameMapper() {
}

@Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
public String apply(final StackFrame stackFrame) {
return stackFrame.getClassName();
}

}
Expand Down Expand Up @@ -196,5 +217,5 @@ public StackFrame apply(final Stream<StackFrame> stream) {
return null;
}
}

}
Loading