Browse Source

change: TraceUtils uses external code from JDK8 / JDK11 module

new modules: assira.jdk8 / assira.jdk11
Ranides Atterwim 6 years ago
parent
commit
7a4cc8981a

+ 4 - 1
.gitignore

@@ -9,9 +9,12 @@
 /assira.benchmark/target/
 /assira.all/target/
 /assira.enterprise/target/
+/assira.lambda/target/
+/assira.jdk8/target/
+/assira.jdk11/target/
 pom.xml.versionsBackup
 nbproject
 /.idea/
 *.iml
 assira.asm/dependency-reduced-pom.xml
-assira.lambda/target/*
+

+ 12 - 0
assira.benchmark/pom.xml

@@ -15,6 +15,8 @@
     <properties>
         <jmh.version>1.12</jmh.version>
         <uberjar.name>benchmarks</uberjar.name>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
     </properties>
 
     <prerequisites>
@@ -37,6 +39,16 @@
             <groupId>net.ranides</groupId>
             <artifactId>assira</artifactId>
         </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira.jdk8</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira.jdk11</artifactId>
+            <scope>compile</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>

+ 64 - 0
assira.benchmark/src/main/java/net/ranides/assira/trace/Walker11Benchmark.java

@@ -0,0 +1,64 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.trace;
+
+import net.ranides.benchmark.app.BenchmarkName;
+import net.ranides.benchmark.app.BenchmarkRunner;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.runner.RunnerException;
+
+import java.io.IOException;
+
+/**
+ * Benchmark for JDK11 StackWalker
+ *
+ */
+public class Walker11Benchmark {
+
+    private static final FStackWalker11 walker = new FStackWalker11();
+
+    @Benchmark
+    @BenchmarkName("frameNative")
+    public int frameNative() {
+        return walker.getFrame(1).getLineNumber();
+    }
+
+
+    @Benchmark
+    @BenchmarkName("frameListNative")
+    public int frameListNative() {
+        int ret = 0;
+        for(StackTraceElement e : walker.getFrames()) {
+            ret += e.getLineNumber();
+        }
+        return ret;
+    }
+
+
+    @Benchmark
+    @BenchmarkName("list")
+    public int list() {
+        return walker.getTypes().size();
+    }
+
+    @Benchmark
+    @BenchmarkName("callee")
+    public int callee() {
+        return walker.getType(0).getName().length();
+    }
+
+    @Benchmark
+    @BenchmarkName("caller")
+    public int caller() {
+        return walker.getType(1).getName().length();
+    }
+
+    public static void main(String[] args) throws RunnerException, IOException {
+        BenchmarkRunner.run(Walker11Benchmark.class);
+    }
+    
+}

+ 52 - 13
assira.benchmark/src/main/java/net/ranides/assira/trace/StackInspectorBenchmark.java

@@ -9,7 +9,7 @@ package net.ranides.assira.trace;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
-import net.ranides.assira.trace.TraceUtils;
+
 import net.ranides.benchmark.app.BenchmarkName;
 import net.ranides.benchmark.app.BenchmarkRunner;
 import org.openjdk.jmh.annotations.Benchmark;
@@ -28,13 +28,52 @@ import org.openjdk.jmh.runner.RunnerException;
  * SunReflection gets caller ~10 times faster than stacktrace.
  * Best if you need first class.
  * It's nonportable, but it will work even if you disable SecurityManager.
+ *
+ * SecurityManager gets callee/caller ~2 times faster than JDK11 StackWalker.
+ * SecurityManager creates list ~5 times faster than JDK11 StackWalker.
+ *
  */
-public class StackInspectorBenchmark {
+public class Walker8Benchmark {
+
+    /*
+                              JDK8            JDK11
+    calleeSecurityManager     1439 ±   654     1254 ±   475
+    calleeException           2742 ±   942        x
+    calleeThread             17189 ±   729    36706 ±  3740
+
+    callerSecurityManager     1439 ±   849     1242 ±   344
+    callerException           3329 ±  1189        x
+    callerThread             37680 ± 22440    50715 ± 28560
+
+    frameNative               3173 ±   625        x
+    frameDefault             17181 ±  4192    34634 ±  4031
+
+    frameListNative          14383 ±   720        x
+    frameListDefault         17003 ±  4981    33575 ±  1432
+
+    listSecurityManager        951 ±    62     1774 ±  1251
+    listException            16285 ±   830    40529 ± 17486
+    listThread               16937 ±   775    43467 ±  8709
+
+    Walker11 JDK11
+    callee                    2648 ±  1012      1254  calleeSecurityManager
+    caller                    2366 ±   150      1242  callerSecurityManager
+    frameNative               6391 ±   838
+    frameListNative          33579 ±  1135
+    list                      6623 ±   242       951  listSecurityManager
+
+    FStackWalker11
+    callee                    1420 ±  1119      OK (because we use old security manager)
+    caller                    1060 ±    38      OK (because we use old security manager)
+    frameNative               6391 ±   838      JDK8 was 2x faster
+    frameListNative          33579 ±  1135      JDK8 was 2x faster
+    list                      1482 ±   444      OK (because we use old security manager)
+     */
     
     @Benchmark
     @BenchmarkName("frame[1]: native")
     public int frameNative() {
-        return TraceUtils.getFrames().get(1).getLineNumber();
+        return TraceUtils.getFrame(1).getLineNumber();
     }
     
     
@@ -67,55 +106,55 @@ public class StackInspectorBenchmark {
     @Benchmark
     @BenchmarkName("names: SecurityManager")
     public int listSecurityManager() {
-        return TraceUtils.test_getNames(TraceUtils.RESOLVER_SECURITY).size();
+        return FStackWalker8.test_getNames(FStackWalker8.RESOLVER_SECURITY).size();
     }
     
     @Benchmark
     @BenchmarkName("names: thread")
     public int listThread() {
-        return TraceUtils.test_getNames(TraceUtils.RESOLVER_THREAD).size();
+        return FStackWalker8.test_getNames(FStackWalker8.RESOLVER_THREAD).size();
     }
 
     @Benchmark
     @BenchmarkName("names: exception")
     public int listException() {
-        return TraceUtils.test_getNames(TraceUtils.RESOLVER_EXCEPT).size();
+        return FStackWalker8.test_getNames(FStackWalker8.RESOLVER_EXCEPT).size();
     }
     
     @Benchmark
     @BenchmarkName("callee: SecurityManager")
     public int calleeSecurityManager() {
-        return TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_SECURITY).length();
+        return FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_SECURITY).length();
     }
     
     @Benchmark
     @BenchmarkName("callee: thread")
     public int calleeThread() {
-        return TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_THREAD).length();
+        return FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_THREAD).length();
     }
 
     @Benchmark
     @BenchmarkName("callee: exception")
     public int calleeException() {
-        return TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_EXCEPT).length();
+        return FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_EXCEPT).length();
     }
     
     @Benchmark
     @BenchmarkName("caller: SecurityManager")
     public int callerSecurityManager() {
-        return TraceUtils.test_getCallerName(TraceUtils.RESOLVER_SECURITY).length();
+        return FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_SECURITY).length();
     }
     
     @Benchmark
     @BenchmarkName("caller: thread")
     public int callerThread() {
-        return TraceUtils.test_getCallerName(TraceUtils.RESOLVER_THREAD).length();
+        return FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_THREAD).length();
     }
 
     @Benchmark
     @BenchmarkName("caller: exception")
     public int callerException() {
-        return TraceUtils.test_getCallerName(TraceUtils.RESOLVER_EXCEPT).length();
+        return FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_EXCEPT).length();
     }
         
     private static List<StackTraceElement> getFramesArray() {
@@ -125,7 +164,7 @@ public class StackInspectorBenchmark {
     }
     
     public static void main(String[] args) throws RunnerException, IOException {
-        BenchmarkRunner.run(StackInspectorBenchmark.class);
+        BenchmarkRunner.run(Walker8Benchmark.class);
     }
     
 }

+ 19 - 1
assira.drafts/pom.xml

@@ -4,18 +4,36 @@
     <parent>
         <groupId>net.ranides</groupId>
         <artifactId>assira.project</artifactId>
-        <version>2.3.0</version>
+        <version>2.2.0</version>
         <relativePath>..</relativePath>
     </parent>
     <groupId>net.ranides</groupId>
     <artifactId>assira.drafts</artifactId>
     <packaging>jar</packaging>
 
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <compilerVersion>1.8</compilerVersion>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
     <dependencies>
         <dependency>
             <groupId>net.ranides</groupId>
             <artifactId>assira</artifactId>
         </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira.junit</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.linguafranca.pwdb</groupId>
             <artifactId>KeePassJava2</artifactId>

+ 70 - 0
assira.jdk11/pom.xml

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>assira.project</artifactId>
+        <groupId>net.ranides</groupId>
+        <version>2.3.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>assira.jdk11</artifactId>
+
+    <properties>
+        <assira.junit.debug>false</assira.junit.debug>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                    <compilerArgs>
+                        <argument>-Xlint:unchecked</argument>
+                        <argument>-Xlint:removal</argument>
+                        <argument>-parameters</argument>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>net/ranides/assira/test/**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira.junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 171 - 0
assira.jdk11/src/main/java/net/ranides/assira/trace/FStackWalker11.java

@@ -0,0 +1,171 @@
+package net.ranides.assira.trace;
+
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class FStackWalker11 implements TraceUtils.IStackWalker {
+
+    static final SecurityResolver RESOLVER_SECURITY = getSecurityResolver();
+
+    @Override
+    public List<StackTraceElement> getFrames() {
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(2).map(StackWalker.StackFrame::toStackTraceElement).collect(Collectors.toList()));
+    }
+
+    @Override
+    public List<Class<?>> getTypes() {
+        if(RESOLVER_SECURITY != null) {
+            return RESOLVER_SECURITY.list();
+        }
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(2).map(StackWalker.StackFrame::getDeclaringClass).collect(Collectors.toList()));
+    }
+
+    @Override
+    public List<String> getNames() {
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(2).map(StackWalker.StackFrame::getClassName).collect(Collectors.toList()));
+    }
+
+    @Override
+    public Optional<StackTraceElement> getFrame(Predicate<StackTraceElement> filter) {
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(2).map(StackWalker.StackFrame::toStackTraceElement).filter(filter).findFirst());
+    }
+
+    @Override
+    public Optional<Class<?>> getType(Predicate<Class<?>> filter) {
+        if(RESOLVER_SECURITY != null) {
+            return RESOLVER_SECURITY.stream().filter(filter).findFirst();
+        }
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(2).filter(f -> filter.test(f.getDeclaringClass())).findFirst().map(StackWalker.StackFrame::getDeclaringClass));
+    }
+
+    @Override
+    public Optional<String> getName(Predicate<String> filter) {
+        return StackWalker.getInstance()
+                .walk(s -> s.skip(2).filter(f -> filter.test(f.getClassName())).findFirst().map(StackWalker.StackFrame::getClassName));
+    }
+
+    @Override
+    public StackTraceElement getFrame(int index) {
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(index+2).findFirst().map(StackWalker.StackFrame::toStackTraceElement).get());
+    }
+
+    @Override
+    public Class<?> getType(int index) {
+        if(RESOLVER_SECURITY != null) {
+            return RESOLVER_SECURITY.type(index);
+        }
+        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                .walk(s -> s.skip(index+2).findFirst().map(StackWalker.StackFrame::getDeclaringClass).get());
+    }
+
+    @Override
+    public String getName(int index) {
+        return StackWalker.getInstance()
+                .walk(s -> s.skip(index+2).findFirst().map(StackWalker.StackFrame::getClassName).get());
+    }
+
+    private static SecurityResolver getSecurityResolver() {
+        try {
+            return new SecurityResolver();
+        } catch(SecurityException se) {
+            return null;
+        }
+    }
+
+    private static final class SecurityResolver extends SecurityManager {
+
+        private static final int FIRST = 3;
+
+        public Class<?> type(int index) {
+            return super.getClassContext()[FIRST+index];
+        }
+
+        public String name(int index) {
+            return super.getClassContext()[FIRST+index].getName();
+        }
+
+        public List<Class<?>> list() {
+            return new ClassArray(super.getClassContext(), FIRST);
+        }
+
+        public Stream<Class<?>> stream() {
+            Class<?>[] array = super.getClassContext();
+            return Arrays.stream(array, FIRST, array.length);
+        }
+
+        public List<String> names() {
+            return new NameArray(super.getClassContext(), FIRST);
+        }
+
+    }
+
+    private static final class ClassArray extends AbstractList<Class<?>> {
+
+        private final Class<?>[] array;
+        private final int offset;
+        private final int length;
+
+        @SuppressWarnings("PMD.ArrayIsStoredDirectly")
+        public ClassArray(Class<?>[] array, int offset, int length) {
+            this.array = array;
+            this.offset = offset;
+            this.length = length;
+        }
+
+        public ClassArray(Class<?>[] array, int offset) {
+            this(array, offset, array.length-offset);
+        }
+
+        @Override
+        public Class<?> get(int index) {
+            return array[offset+index];
+        }
+
+        @Override
+        public int size() {
+            return length;
+        }
+
+    }
+
+    private static final class NameArray extends AbstractList<String> {
+
+        private final Class<?>[] array;
+        private final int offset;
+        private final int length;
+
+        @SuppressWarnings("PMD.ArrayIsStoredDirectly")
+        public NameArray(Class<?>[] array, int offset, int length) {
+            this.array = array;
+            this.offset = offset;
+            this.length = length;
+        }
+
+        public NameArray(Class<?>[] array, int offset) {
+            this(array, offset, array.length-offset);
+        }
+
+        @Override
+        public String get(int index) {
+            return array[offset+index].getName();
+        }
+
+        @Override
+        public int size() {
+            return length;
+        }
+
+    }
+
+}

+ 216 - 0
assira.jdk11/src/test/java/net/ranides/assira/trace/FStackWalker11Test.java

@@ -0,0 +1,216 @@
+package net.ranides.assira.trace;
+
+import net.ranides.assira.text.Wildcard;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class FStackWalker11Test {
+
+    @Test
+    public void testCallerType() {
+        assertTrue( SI0.runCallerType0() );
+    }
+
+    @Test
+    public void testCalleeType() {
+        assertTrue( SI0.runCalleeType0() );
+    }
+
+    @Test
+    public void testCallerName() {
+        assertTrue( SI0.runCallerName0() );
+    }
+
+    @Test
+    public void testCalleeName() {
+        assertTrue( SI0.runCalleeName0() );
+    }
+
+    @Test
+    public void testGetTypes0() {
+        assertTrue( SI0.runGetTypes0() );
+    }
+
+    @Test
+    public void testGetNames() {
+        assertTrue( SI0.runGetNames0() );
+    }
+
+    @Test
+    public void testFrame() {
+        assertTrue( SI0.runFrame0() );
+    }
+
+    private static final class SI0 {
+
+        private SI0() { /* utility class */ }
+
+        public static boolean runCallerType0() {
+            SI1.runCallerType1();
+            return true;
+        }
+
+        public static boolean runCalleeType0() {
+            SI1.runCalleeType1();
+            return true;
+        }
+
+        public static boolean runCallerName0() {
+            SI1.runCallerName1();
+            return true;
+        }
+
+        public static boolean runCalleeName0() {
+            SI1.runCalleeName1();
+            return true;
+        }
+
+        public static boolean runGetTypes0() {
+            SI1.runGetTypes1();
+            return true;
+        }
+
+        public static boolean runGetNames0() {
+            SI1.runGetNames1();
+            return true;
+        }
+
+        public static boolean runFrame0() {
+            SI1.runFrame1();
+            return true;
+        }
+
+    }
+
+    private static final class SI1 {
+
+        private SI1() { /* utility class */ }
+
+        public static void runCallerType1() {
+            Class<?> caller = SI0.class;
+
+            Class callerAuto = TraceUtils.getCallerType();
+            assertEquals(caller, callerAuto);
+        }
+
+        public static void runCalleeType1() {
+            Class<?> callee = SI1.class;
+
+            Class calleeAuto = TraceUtils.getCalleeType();
+            assertEquals(callee, calleeAuto);
+        }
+
+        public static void runCallerName1() {
+            String caller = SI0.class.getName();
+
+            String callerAuto = TraceUtils.getCallerName();
+            assertEquals(caller, callerAuto);
+        }
+
+        public static void runCalleeName1() {
+            String callee = SI1.class.getName();
+
+            String calleeAuto = TraceUtils.getCalleeName();
+            assertEquals(callee, calleeAuto);
+        }
+
+        public static void runGetTypes1() {
+            Class<?> callee = SI1.class;
+            Class<?> caller = SI0.class;
+
+            List<Class<?>> listAuto = TraceUtils.getTypes();
+
+            if(false) { //NOPMD
+                dump(listAuto);
+            }
+
+//            assertEquals(listAuto, listSM);
+//
+//            assertTrue(listSM.size() > 5);
+//
+//            assertEquals(callee, listSM.get(0));
+////            assertEquals(callee, listSR.get(0));
+//
+//            assertEquals(caller, listSM.get(1));
+////            assertEquals(caller, listSR.get(1));
+//
+//            assertThrows(UnsupportedOperationException.class, ()->{
+//                FStackWalker11.test_getTypes(FStackWalker11.RESOLVER_THREAD);
+//            });
+//            assertThrows(UnsupportedOperationException.class, ()->{
+//                FStackWalker11.test_getTypes(FStackWalker11.RESOLVER_EXCEPT);
+//            });
+        }
+
+        public static void runGetNames1() {
+            String callee = SI1.class.getName();
+            String caller = SI0.class.getName();
+
+            List<String> listAuto = TraceUtils.getNames();
+
+            if(false) { //NOPMD
+                System.out.printf("%n%nauto%n");
+                dump(listAuto);
+            }
+
+//            assertTrue(
+//                    listAuto.equals(listSM) ||
+//                            listAuto.equals(listTS) ||
+//                            listAuto.equals(listES)
+//            );
+//
+//            assertEquals(listTS, listES);
+//
+//            assertTrue(listSM.size() > 5);
+//            assertTrue(listSM.size() <= listTS.size());
+//
+//            assertEquals(callee, listSM.get(0));
+//            assertEquals(callee, listTS.get(0));
+//            assertEquals(callee, listES.get(0));
+//
+//            assertEquals(caller, listSM.get(1));
+//            assertEquals(caller, listTS.get(1));
+//            assertEquals(caller, listES.get(1));
+        }
+
+        public static void runFrame1() {
+            List<StackTraceElement> frames = TraceUtils.getFrames();
+            List<String> names = TraceUtils.getNames();
+
+            if(false) { // NOPMD
+                System.out.printf("frames = %d%n", frames.size());
+                System.out.printf("names = %d%n", names.size());
+                dump(frames);
+                dump(names);
+            }
+
+            Wildcard callee = Wildcard.compile("net.ranides.assira.trace.FStackWalker11Test$SI1.runFrame1(FStackWalker11Test.java:*)");
+            Wildcard caller = Wildcard.compile("net.ranides.assira.trace.FStackWalker11Test$SI0.runFrame0(FStackWalker11Test.java:*)");
+            Wildcard frame2 = Wildcard.compile("net.ranides.assira.trace.FStackWalker11Test.testFrame(FStackWalker11Test.java:*)");
+
+            assertTrue(callee.test(TraceUtils.getCalleeFrame().toString()));
+            assertTrue(caller.test(TraceUtils.getCallerFrame().toString()));
+
+            assertTrue(callee.test(frames.get(0).toString()));
+            assertTrue(caller.test(frames.get(1).toString()));
+            assertTrue(frame2.test(frames.get(2).toString()));
+
+            assertEquals(frames.size(), names.size());
+        }
+
+    }
+
+    @SuppressWarnings("PMD")
+    private static void dump(List<?> list) {
+        int i = 0;
+        for(Object c : list) {
+            System.err.printf("%d. %s%n", i++, c);
+        }
+        System.out.printf("%n");
+    }
+    
+}

+ 43 - 0
assira.jdk8/pom.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>assira.project</artifactId>
+        <groupId>net.ranides</groupId>
+        <version>2.3.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>assira.jdk8</artifactId>
+
+    <properties>
+        <assira.junit.debug>false</assira.junit.debug>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira.junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 467 - 0
assira.jdk8/src/main/java/net/ranides/assira/trace/FStackWalker8.java

@@ -0,0 +1,467 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.trace;
+
+import net.ranides.assira.generic.ValueUtils;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class FStackWalker8 implements TraceUtils.IStackWalker {
+
+    // Please note that class is implemented in very verbose way:
+    // we don't use any functional interfaces, adapters, JDK Stream API etc.
+    //
+    // Every syntactic elegance will slow down us. It matters, because functions
+    // are designed to be *extremaly* fast (~1 us per call) and every overhead
+    // is noticeable.
+    //
+    // We use "package scope" because we want to test our resolvers in junit
+
+    private static final String NSE = "StackInspector: operation not supported. Please use Sun JDK or enable SecurityManager.";
+
+    static final SunResolver RESOLVER_SUN = getSunResolver();
+
+    static final SecurityResolver RESOLVER_SECURITY = getSecurityResolver();
+
+    static final ThreadResolver RESOLVER_THREAD = new ThreadResolver();
+
+    static final ExceptionResolver RESOLVER_EXCEPT = new ExceptionResolver();
+
+    /**
+     * if you want full list, SecurityManager is faster than SunReflection
+     */
+    static final Resolver AUTO_LIST_RESOLVER = ValueUtils.or(
+            RESOLVER_SECURITY,
+            RESOLVER_SUN,
+            RESOLVER_EXCEPT
+    );
+
+    /**
+     * if you want first element, SunReflection is faster than SecurityManager
+     */
+    static final Resolver AUTO_CALLER_RESOLVER = ValueUtils.or(
+            RESOLVER_SUN,
+            RESOLVER_SECURITY,
+            RESOLVER_EXCEPT
+    );
+
+    @Override
+    public List<StackTraceElement> getFrames() {
+        return new FrameList();
+    }
+
+    @Override
+    public List<Class<?>> getTypes() {
+        return AUTO_LIST_RESOLVER.list();
+    }
+
+    @Override
+    public List<String> getNames() {
+        return AUTO_LIST_RESOLVER.names();
+    }
+
+    @Override
+    public Optional<StackTraceElement> getFrame(Predicate<StackTraceElement> filter) {
+        return new FrameList().stream().filter(filter).findFirst();
+    }
+
+    @Override
+    public Optional<Class<?>> getType(Predicate<Class<?>> filter) {
+        return AUTO_LIST_RESOLVER.list().stream().filter(filter).findFirst();
+    }
+
+    @Override
+    public Optional<String> getName(Predicate<String> filter) {
+        return AUTO_LIST_RESOLVER.names().stream().filter(filter).findFirst();
+    }
+
+    @Override
+    public StackTraceElement getFrame(int index) {
+        return new FrameList().get(index);
+    }
+
+    @Override
+    public Class<?> getType(int index) {
+        return AUTO_CALLER_RESOLVER.type(index);
+    }
+
+    @Override
+    public String getName(int index) {
+        return AUTO_CALLER_RESOLVER.name(index);
+    }
+
+    @SuppressWarnings("PMD")
+    static List<Class<?>> test_getTypes(Resolver resolver) {
+        return test1_getTypes(resolver);
+    }
+
+    private static List<Class<?>> test1_getTypes(Resolver resolver) {
+        return resolver.list();
+    }
+
+    @SuppressWarnings("PMD")
+    static List<String> test_getNames(Resolver resolver) {
+        return test1_getNames(resolver);
+    }
+
+    private static List<String> test1_getNames(Resolver resolver) {
+        return resolver.names();
+    }
+
+    @SuppressWarnings("PMD")
+    static Class<?> test_getCalleeType(Resolver resolver) {
+        return test_getCalleeType1(resolver);
+    }
+
+    private static Class<?> test_getCalleeType1(Resolver resolver) {
+        return resolver.type(0);
+    }
+
+    @SuppressWarnings("PMD")
+    static String test_getCalleeName(Resolver resolver) {
+        return test_getCalleeName1(resolver);
+    }
+
+    private static String test_getCalleeName1(Resolver resolver) {
+        return resolver.name(0);
+    }
+
+    @SuppressWarnings("PMD")
+    static Class<?> test_getCallerType(Resolver resolver) {
+        return test_getCallerType1(resolver);
+    }
+
+    private static Class<?> test_getCallerType1(Resolver resolver) {
+        return resolver.type(1);
+    }
+
+    @SuppressWarnings("PMD")
+    static String test_getCallerName(Resolver resolver) {
+        return test_getCallerName1(resolver);
+    }
+
+    private static String test_getCallerName1(Resolver resolver) {
+        return resolver.name(1);
+    }
+
+    interface Resolver {
+
+        Class<?> type(int index);
+
+        String name(int index);
+
+        List<Class<?>> list();
+
+        List<String> names();
+    }
+
+    private static SunResolver getSunResolver() {
+        try {
+            return new SunResolver();
+        } catch(Exception | Error cause) {
+            return null;
+        }
+    }
+
+    private static SecurityResolver getSecurityResolver() {
+        try {
+            return new SecurityResolver();
+        } catch(SecurityException se) {
+            return null;
+        }
+    }
+
+    private static final class SecurityResolver extends SecurityManager implements Resolver {
+
+        private static final int FIRST = 3;
+
+        @Override
+        public Class<?> type(int index) {
+            return super.getClassContext()[FIRST+index];
+        }
+
+        @Override
+        public String name(int index) {
+            return super.getClassContext()[FIRST+index].getName();
+        }
+
+        @Override
+        public List<Class<?>> list() {
+            return new ClassArray(super.getClassContext(), FIRST);
+        }
+
+        @Override
+        public List<String> names() {
+            return new NameArray(super.getClassContext(), FIRST);
+        }
+
+    }
+
+    private static final class SunResolver implements Resolver {
+
+        private static final int FIRST = 3+3;
+
+        public SunResolver() {
+            $caller(0);
+        }
+
+        @Override
+        public Class<?> type(int index) {
+            return $caller(FIRST+index);
+        }
+
+        @Override
+        public String name(int index) {
+            return $caller(FIRST+index).getName();
+        }
+
+        @Override
+        public List<Class<?>> list() {
+            List<Class<?>> list = new ArrayList<>(64);
+            int i=FIRST;
+            Class<?> c;
+            while(null != (c = $caller(i++))) {
+                list.add(c);
+            }
+            return list;
+        }
+
+        @Override
+        public List<String> names() {
+            List<String> list = new ArrayList<>(64);
+            int i=FIRST;
+            Class<?> c;
+            while(null != (c = $caller(i++))) {
+                list.add(c.getName());
+            }
+            return list;
+        }
+
+    }
+
+    private static Class<?> $caller(int index) {
+        return sun.reflect.Reflection.getCallerClass(index);
+    }
+
+    private static final class ThreadResolver implements Resolver {
+
+        private static final int FIRST = 4;
+
+        @Override
+        public List<String> names() {
+            return new FrameArray(Thread.currentThread().getStackTrace(), FIRST);
+        }
+
+        @Override
+        public Class<?> type(int index) {
+            throw new UnsupportedOperationException(NSE);
+        }
+
+        @Override
+        public String name(int index) {
+            return Thread.currentThread().getStackTrace()[FIRST+index].getClassName();
+        }
+
+        @Override
+        public List<Class<?>> list() {
+            throw new UnsupportedOperationException(NSE);
+        }
+
+    }
+
+    private static final class ExceptionResolver implements Resolver {
+
+        private static final int FIRST = 3;
+
+        @Override
+        public Class<?> type(int index) {
+            throw new UnsupportedOperationException(NSE);
+        }
+
+        @Override
+        public String name(int index) {
+            return ReflectFrame.get(new Exception(), FIRST+index).getClassName(); //NOPMD
+        }
+
+        @Override
+        public List<String> names() {
+            return new FrameArray(new Exception().getStackTrace(), FIRST); //NOPMD
+        }
+
+        @Override
+        public List<Class<?>> list() {
+            throw new UnsupportedOperationException(NSE);
+        }
+
+    }
+
+    private static final class ClassArray extends AbstractList<Class<?>> {
+
+        private final Class<?>[] array;
+        private final int offset;
+        private final int length;
+
+        @SuppressWarnings("PMD.ArrayIsStoredDirectly")
+        public ClassArray(Class<?>[] array, int offset, int length) {
+            this.array = array;
+            this.offset = offset;
+            this.length = length;
+        }
+
+        public ClassArray(Class<?>[] array, int offset) {
+            this(array, offset, array.length-offset);
+        }
+
+        @Override
+        public Class<?> get(int index) {
+            return array[offset+index];
+        }
+
+        @Override
+        public int size() {
+            return length;
+        }
+
+    }
+
+    private static final class NameArray extends AbstractList<String> {
+
+        private final Class<?>[] array;
+        private final int offset;
+        private final int length;
+
+        @SuppressWarnings("PMD.ArrayIsStoredDirectly")
+        public NameArray(Class<?>[] array, int offset, int length) {
+            this.array = array;
+            this.offset = offset;
+            this.length = length;
+        }
+
+        public NameArray(Class<?>[] array, int offset) {
+            this(array, offset, array.length-offset);
+        }
+
+        @Override
+        public String get(int index) {
+            return array[offset+index].getName();
+        }
+
+        @Override
+        public int size() {
+            return length;
+        }
+
+    }
+
+    private static final class FrameArray extends AbstractList<String> {
+
+        private final StackTraceElement[] array;
+        private final int offset;
+        private final int length;
+
+        @SuppressWarnings("PMD.ArrayIsStoredDirectly")
+        public FrameArray(StackTraceElement[] array, int offset, int length) {
+            this.array = array;
+            this.offset = offset;
+            this.length = length;
+        }
+
+        public FrameArray(StackTraceElement[] array, int offset) {
+            this(array, offset, array.length-offset);
+        }
+
+        @Override
+        public String get(int index) {
+            return array[offset+index].getClassName();
+        }
+
+        @Override
+        public int size() {
+            return length;
+        }
+
+    }
+
+    private static final class FrameList extends AbstractList<StackTraceElement> {
+
+        private static final int FIRST = 3;
+
+        private final Throwable cause;
+
+        private final int size;
+
+        private StackTraceElement[] array;
+
+        public FrameList() {
+            this.cause = new Throwable(); // NOPMD
+            this.size = ReflectFrame.depth(cause)-FIRST;
+            this.array = null;
+        }
+
+        @Override
+        public StackTraceElement get(int index) {
+            if(null == array) {
+                array = new StackTraceElement[ReflectFrame.depth(cause)];
+            }
+            if(null == array[index]) {
+                array[index] = ReflectFrame.get(cause, FIRST+index);
+            }
+            return array[index];
+        }
+
+        @Override
+        public int size() {
+            return size;
+        }
+
+    }
+
+    private static final class ReflectFrame { // NOPMD - lazy init idiom
+
+        public static final java.lang.reflect.Method GET;
+
+        public static final java.lang.reflect.Method DEPTH;
+
+        static {
+            try {
+                GET = Throwable.class.getDeclaredMethod("getStackTraceElement", int.class);
+                GET.setAccessible(true);
+
+                DEPTH = Throwable.class.getDeclaredMethod("getStackTraceDepth");
+                DEPTH.setAccessible(true);
+            } catch(ReflectiveOperationException ex) {
+                throw new UnsupportedOperationException(NSE, ex);
+            }
+        }
+
+        public static int depth(Throwable that) {
+            try {
+                return (int)DEPTH.invoke(that);
+            } catch(ReflectiveOperationException ex) {
+                throw new UnsupportedOperationException(NSE, ex);
+            }
+        }
+
+        public static StackTraceElement get(Throwable that, int index) {
+            try {
+                return (StackTraceElement)GET.invoke(that, index);
+            } catch(ReflectiveOperationException ex) {
+                throw new UnsupportedOperationException(NSE, ex);
+            }
+        }
+
+    }
+
+}

+ 283 - 0
assira.jdk8/src/test/java/net/ranides/assira/trace/FStackWalker8Test.java

@@ -0,0 +1,283 @@
+package net.ranides.assira.trace;
+
+import net.ranides.assira.text.Wildcard;
+import org.junit.Test;
+
+import java.util.List;
+
+import static net.ranides.assira.junit.NewAssert.assertThrows;
+import static org.junit.Assert.*;
+
+public class FStackWalker8Test {
+
+    @Test
+    public void testCallerType() {
+        assertTrue( SI0.runCallerType0() );
+    }
+
+    @Test
+    public void testCalleeType() {
+        assertTrue( SI0.runCalleeType0() );
+    }
+
+    @Test
+    public void testCallerName() {
+        assertTrue( SI0.runCallerName0() );
+    }
+
+    @Test
+    public void testCalleeName() {
+        assertTrue( SI0.runCalleeName0() );
+    }
+
+    @Test
+    public void testGetTypes0() {
+        assertTrue( SI0.runGetTypes0() );
+    }
+
+    @Test
+    public void testGetNames() {
+        assertTrue( SI0.runGetNames0() );
+    }
+
+    @Test
+    public void testFrame() {
+        assertTrue( SI0.runFrame0() );
+    }
+
+    private static final class SI0 {
+
+        private SI0() { /* utility class */ }
+
+        public static boolean runCallerType0() {
+            SI1.runCallerType1();
+            return true;
+        }
+
+        public static boolean runCalleeType0() {
+            SI1.runCalleeType1();
+            return true;
+        }
+
+        public static boolean runCallerName0() {
+            SI1.runCallerName1();
+            return true;
+        }
+
+        public static boolean runCalleeName0() {
+            SI1.runCalleeName1();
+            return true;
+        }
+
+        public static boolean runGetTypes0() {
+            SI1.runGetTypes1();
+            return true;
+        }
+
+        public static boolean runGetNames0() {
+            SI1.runGetNames1();
+            return true;
+        }
+
+        public static boolean runFrame0() {
+            SI1.runFrame1();
+            return true;
+        }
+
+    }
+
+    private static final class SI1 {
+
+        private SI1() { /* utility class */ }
+
+        public static void runCallerType1() {
+            Class<?> caller = SI0.class;
+
+            Class callerAuto = TraceUtils.getCallerType();
+            Class callerSM   = FStackWalker8.test_getCallerType(FStackWalker8.RESOLVER_SECURITY);
+            Class callerSR   = FStackWalker8.test_getCallerType(FStackWalker8.RESOLVER_SUN);
+
+            assertEquals(caller, callerAuto);
+            assertEquals(caller, callerSM);
+            assertEquals(caller, callerSR);
+
+            assertThrows(UnsupportedOperationException.class, ()->{
+                FStackWalker8.test_getCallerType(FStackWalker8.RESOLVER_THREAD);
+            });
+            assertThrows(UnsupportedOperationException.class, ()->{
+                FStackWalker8.test_getCallerType(FStackWalker8.RESOLVER_EXCEPT);
+            });
+        }
+
+        public static void runCalleeType1() {
+            Class<?> callee = SI1.class;
+
+            Class calleeAuto = TraceUtils.getCalleeType();
+            Class calleeSM   = FStackWalker8.test_getCalleeType(FStackWalker8.RESOLVER_SECURITY);
+            Class calleeSR   = FStackWalker8.test_getCalleeType(FStackWalker8.RESOLVER_SUN);
+
+            assertEquals(callee, calleeAuto);
+            assertEquals(callee, calleeSM);
+            assertEquals(callee, calleeSR);
+
+            assertThrows(UnsupportedOperationException.class, ()->{
+                FStackWalker8.test_getCalleeType(FStackWalker8.RESOLVER_THREAD);
+            });
+            assertThrows(UnsupportedOperationException.class, ()->{
+                FStackWalker8.test_getCalleeType(FStackWalker8.RESOLVER_EXCEPT);
+            });
+        }
+
+        public static void runCallerName1() {
+            String caller = SI0.class.getName();
+
+            String callerAuto = TraceUtils.getCallerName();
+            String callerSM   = FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_SECURITY);
+            String callerSR   = FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_SUN);
+            String callerTS   = FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_THREAD);
+            String callerES   = FStackWalker8.test_getCallerName(FStackWalker8.RESOLVER_EXCEPT);
+
+            assertEquals(caller, callerAuto);
+            assertEquals(caller, callerSM);
+            assertEquals(caller, callerSR);
+            assertEquals(caller, callerTS);
+            assertEquals(caller, callerES);
+        }
+
+        public static void runCalleeName1() {
+            String callee = SI1.class.getName();
+
+            String calleeAuto = TraceUtils.getCalleeName();
+            String calleeSM   = FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_SECURITY);
+            String calleeSR   = FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_SUN);
+            String calleeTS   = FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_THREAD);
+            String calleeES   = FStackWalker8.test_getCalleeName(FStackWalker8.RESOLVER_EXCEPT);
+
+            assertEquals(callee, calleeAuto);
+            assertEquals(callee, calleeSM);
+            assertEquals(callee, calleeSR);
+            assertEquals(callee, calleeTS);
+            assertEquals(callee, calleeES);
+        }
+
+        public static void runGetTypes1() {
+            Class<?> callee = SI1.class;
+            Class<?> caller = SI0.class;
+
+            List<Class<?>> listAuto = TraceUtils.getTypes();
+            List<Class<?>> listSM   = FStackWalker8.test_getTypes(FStackWalker8.RESOLVER_SECURITY);
+            List<Class<?>> listSR   = FStackWalker8.test_getTypes(FStackWalker8.RESOLVER_SUN);
+
+            if(false) { //NOPMD
+                dump(listAuto);
+                dump(listSM);
+                dump(listSR);
+            }
+
+            assertTrue(
+                    listAuto.equals(listSM) ||
+                            listAuto.equals(listSR)
+            );
+
+            assertEquals(listSM, listSR);
+
+            assertTrue(listSM.size() > 5);
+
+            assertEquals(callee, listSM.get(0));
+            assertEquals(callee, listSR.get(0));
+
+            assertEquals(caller, listSM.get(1));
+            assertEquals(caller, listSR.get(1));
+
+            assertThrows(UnsupportedOperationException.class, ()->{
+                FStackWalker8.test_getTypes(FStackWalker8.RESOLVER_THREAD);
+            });
+            assertThrows(UnsupportedOperationException.class, ()->{
+                FStackWalker8.test_getTypes(FStackWalker8.RESOLVER_EXCEPT);
+            });
+        }
+
+        public static void runGetNames1() {
+            String callee = SI1.class.getName();
+            String caller = SI0.class.getName();
+
+            List<String> listAuto = TraceUtils.getNames();
+            List<String> listSM  = FStackWalker8.test_getNames(FStackWalker8.RESOLVER_SECURITY);
+            List<String> listSR  = FStackWalker8.test_getNames(FStackWalker8.RESOLVER_SUN);
+            List<String> listTS  = FStackWalker8.test_getNames(FStackWalker8.RESOLVER_THREAD);
+            List<String> listES  = FStackWalker8.test_getNames(FStackWalker8.RESOLVER_EXCEPT);
+
+            if(false) { //NOPMD
+                System.out.printf("%n%nauto%n");
+                dump(listAuto);
+                System.out.printf("%n%nsm%n");
+                dump(listSM);
+                System.out.printf("%n%nsr%n");
+                dump(listSR);
+                System.out.printf("%n%nts%n");
+                dump(listTS);
+                System.out.printf("%n%nes%n");
+                dump(listES);
+            }
+
+            assertTrue(
+                    listAuto.equals(listSM) ||
+                            listAuto.equals(listSR) ||
+                            listAuto.equals(listTS) ||
+                            listAuto.equals(listES)
+            );
+
+            assertEquals(listSM, listSR);
+            assertEquals(listTS, listES);
+
+            assertTrue(listSM.size() > 5);
+            assertTrue(listSM.size() <= listTS.size());
+
+            assertEquals(callee, listSM.get(0));
+            assertEquals(callee, listSR.get(0));
+            assertEquals(callee, listTS.get(0));
+            assertEquals(callee, listES.get(0));
+
+            assertEquals(caller, listSM.get(1));
+            assertEquals(caller, listSR.get(1));
+            assertEquals(caller, listTS.get(1));
+            assertEquals(caller, listES.get(1));
+        }
+
+        public static void runFrame1() {
+            List<StackTraceElement> frames = TraceUtils.getFrames();
+            List<String> names = FStackWalker8.test_getNames(FStackWalker8.RESOLVER_THREAD);
+
+            if(false) { // NOPMD
+                System.out.printf("frames = %d%n", frames.size());
+                System.out.printf("names = %d%n", names.size());
+                dump(frames);
+                dump(names);
+            }
+
+            Wildcard callee = Wildcard.compile("net.ranides.assira.trace.FStackWalker8Test$SI1.runFrame1(FStackWalker8Test.java:*)");
+            Wildcard caller = Wildcard.compile("net.ranides.assira.trace.FStackWalker8Test$SI0.runFrame0(FStackWalker8Test.java:*)");
+            Wildcard frame2 = Wildcard.compile("net.ranides.assira.trace.FStackWalker8Test.testFrame(FStackWalker8Test.java:*)");
+
+            assertTrue(callee.test(TraceUtils.getCalleeFrame().toString()));
+            assertTrue(caller.test(TraceUtils.getCallerFrame().toString()));
+
+            assertTrue(callee.test(frames.get(0).toString()));
+            assertTrue(caller.test(frames.get(1).toString()));
+            assertTrue(frame2.test(frames.get(2).toString()));
+
+            assertEquals(frames.size(), names.size());
+        }
+
+    }
+
+    @SuppressWarnings("PMD")
+    private static void dump(List<?> list) {
+        int i = 0;
+        for(Object c : list) {
+            System.err.printf("%d. %s%n", i++, c);
+        }
+        System.out.printf("%n");
+    }
+
+}

+ 5 - 9
assira.lambda/pom.xml

@@ -13,6 +13,8 @@
 
     <properties>
         <assira.junit.debug>false</assira.junit.debug>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
     </properties>
 
     <build>
@@ -21,8 +23,6 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
                     <compilerArgs>
                         <argument>-Xlint:unchecked</argument>
                         <argument>-Xlint:removal</argument>
@@ -54,12 +54,12 @@
 
     <dependencies>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <groupId>net.ranides</groupId>
+            <artifactId>assira</artifactId>
         </dependency>
         <dependency>
             <groupId>net.ranides</groupId>
-            <artifactId>assira</artifactId>
+            <artifactId>assira.jdk11</artifactId>
         </dependency>
         <dependency>
             <groupId>net.ranides</groupId>
@@ -69,10 +69,6 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
     </dependencies>
 
 </project>

+ 8 - 6
assira/pom.xml

@@ -122,10 +122,18 @@
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.datatype</groupId>
             <artifactId>jackson-datatype-json-org</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
         <dependency>
             <groupId>se.fishtank</groupId>
             <artifactId>css-selectors</artifactId>
@@ -137,15 +145,9 @@
             <type>jar</type>
             <optional>true</optional>
         </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.dataformat</groupId>
-            <artifactId>jackson-dataformat-xml</artifactId>
-            <version>2.9.4</version>
-        </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
-            <version>1.18.8</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

+ 42 - 240
assira/src/main/java/net/ranides/assira/trace/TraceUtils.java

@@ -6,17 +6,9 @@
  */
 package net.ranides.assira.trace;
 
-import java.lang.StackWalker.StackFrame;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
-import java.util.function.Function;
 import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.stream.Stream;
-
-import net.ranides.assira.collection.lists.ListUtils;
-import net.ranides.assira.generic.ValueUtils;
 
 /**
  *
@@ -24,297 +16,107 @@ import net.ranides.assira.generic.ValueUtils;
  */
 public final class TraceUtils {
 
-    // @todo (assira #1) JDK11: migrate to StackWalker
-    static final Supplier<RuntimeException> THROW = () -> new RuntimeException("Internal: TraceUtils");
+    interface IStackWalker {
 
-    static final SecurityResolver RESOLVER_SECURITY = getSecurityResolver();
+        List<StackTraceElement> getFrames();
 
-    static final ThreadResolver RESOLVER_THREAD = new ThreadResolver();
+        List<Class<?>> getTypes();
 
-    static final ExceptionResolver RESOLVER_EXCEPT = new ExceptionResolver();
+        List<String> getNames();
 
+        Optional<StackTraceElement> getFrame(Predicate<StackTraceElement> filter);
 
-    static final Resolver AUTO_LIST_FRAMES = ValueUtils.or(
-            RESOLVER_THREAD,
-            RESOLVER_EXCEPT
-    );
+        Optional<Class<?>> getType(Predicate<Class<?>> filter);
 
-    static final Resolver AUTO_LIST_TYPES = ValueUtils.or(
-            RESOLVER_SECURITY,
-            RESOLVER_THREAD,
-            RESOLVER_EXCEPT
-    );
+        Optional<String> getName(Predicate<String> filter);
 
-    static final Resolver AUTO_LIST_NAMES = ValueUtils.or(
-            RESOLVER_SECURITY,
-            RESOLVER_THREAD,
-            RESOLVER_EXCEPT
-    );
+        StackTraceElement getFrame(int index);
 
-    static final Resolver AUTO_FRAME = ValueUtils.or(
-            RESOLVER_THREAD,
-            RESOLVER_EXCEPT
-    );
+        Class<?> getType(int index);
 
-    static final Resolver AUTO_TYPE = ValueUtils.or(
-            RESOLVER_SECURITY,
-            RESOLVER_THREAD,
-            RESOLVER_EXCEPT
-    );
+        String getName(int index);
 
-    static final Resolver AUTO_NAME = ValueUtils.or(
-            RESOLVER_SECURITY,
-            RESOLVER_THREAD,
-            RESOLVER_EXCEPT
+    }
+
+    private static final IStackWalker WALKER = init(
+        "net.ranides.assira.trace.FStackWalker11",
+        "net.ranides.assira.trace.FStackWalker8",
+        "net.ranides.assira.trace.FStackWalker6"
     );
 
+    private static IStackWalker init(String... names) {
+        for(String name : names) {
+            try {
+                return (IStackWalker)Class.forName(name).newInstance();
+            } catch (ReflectiveOperationException ex) {
+                // continue
+            }
+        }
+        throw new UnsatisfiedLinkError("There is no IStackWalker implementation. Add dependency: assira.jdk8 or assira.jdk11");
+    }
+
     private TraceUtils() {
         /* utility class */
     }
 
-    @Deprecated
     public static List<StackTraceElement> getFrames() {
-        return AUTO_LIST_FRAMES.frames();
+        return WALKER.getFrames();
     }
 
-    @Deprecated
     public static List<Class<?>> getTypes() {
-        return AUTO_LIST_TYPES.types();
+        return WALKER.getTypes();
     }
 
-    @Deprecated
     public static List<String> getNames() {
-        return AUTO_LIST_NAMES.names();
+        return WALKER.getNames();
     }
 
     public static Optional<StackTraceElement> getFrame(Predicate<StackTraceElement> filter) {
-        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                .walk(s -> s.map(StackFrame::toStackTraceElement).filter(filter).findFirst());
+        return WALKER.getFrame(filter);
     }
 
     public static Optional<Class<?>> getType(Predicate<Class<?>> filter) {
-        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                .walk(s -> s.filter(f -> filter.test(f.getDeclaringClass())).findFirst().map(StackFrame::getDeclaringClass));
+        return WALKER.getType(filter);
     }
 
     public static Optional<String> getName(Predicate<String> filter) {
-        return StackWalker.getInstance()
-                .walk(s -> s.filter(f -> filter.test(f.getClassName())).findFirst().map(StackFrame::getClassName));
+        return WALKER.getName(filter);
     }
 
-    @Deprecated
     public static StackTraceElement getFrame(int index) {
-        return AUTO_FRAME.frame(index);
+        return WALKER.getFrame(index);
     }
 
-    @Deprecated
     public static Class<?> getType(int index) {
-        return AUTO_TYPE.type(index);
+        return WALKER.getType(index);
     }
 
-    @Deprecated
     public static String getName(int index) {
-        return AUTO_NAME.name(index);
+        return WALKER.getName(index);
     }
 
     public static StackTraceElement getCalleeFrame() {
-        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                .walk(f -> f.skip(1).map(StackFrame::toStackTraceElement).findFirst().orElseThrow(THROW));
+        return getFrame(1);
     }
 
     public static Class<?> getCalleeType() {
-        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                .walk(f -> f.skip(1).map(StackFrame::getDeclaringClass).findFirst().orElseThrow(THROW));
+        return getType(1);
     }
 
     public static String getCalleeName() {
-        return StackWalker.getInstance()
-                .walk(f -> f.skip(1).map(StackFrame::getClassName).findFirst().orElseThrow(THROW));
+        return getName(1);
     }
 
     public static StackTraceElement getCallerFrame() {
-        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                .walk(f -> f.skip(2).map(StackFrame::toStackTraceElement).findFirst().orElseThrow(THROW));
+        return getFrame(2);
     }
 
     public static Class<?> getCallerType() {
-        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                .walk(f -> f.skip(2).map(StackFrame::getDeclaringClass).findFirst().orElseThrow(THROW));
+        return getType(2);
     }
 
     public static String getCallerName() {
-        return StackWalker.getInstance()
-                .walk(f -> f.skip(2).map(StackFrame::getClassName).findFirst().orElseThrow(THROW));
-    }
-
-    @SuppressWarnings("PMD")
-    static List<Class<?>> test_getTypes(Resolver resolver) {
-        return resolver.types();
-    }
-
-    @SuppressWarnings("PMD")
-    static List<String> test_getNames(Resolver resolver) {
-        return resolver.names();
-    }
-
-	@SuppressWarnings("PMD")
-    static Class<?> test_getCalleeType(Resolver resolver) {
-        return resolver.type(0);
-    }
-
-	@SuppressWarnings("PMD")
-    static String test_getCalleeName(Resolver resolver) {
-        return resolver.name(0);
-    }
-
-    @SuppressWarnings("PMD")
-    static Class<?> test_getCallerType(Resolver resolver) {
-        return resolver.type(1);
-    }
-
-	@SuppressWarnings("PMD")
-    static String test_getCallerName(Resolver resolver) {
-        return resolver.name(1);
-    }
-
-    interface Resolver {
-
-        List<StackTraceElement> frames();
-
-        StackTraceElement frame(int index);
-
-        List<Class<?>> types();
-
-        Class<?> type(int index);
-
-        List<String> names();
-
-        String name(int index);
-    }
-
-    private static SecurityResolver getSecurityResolver() {
-        try {
-            return new SecurityResolver();
-        } catch(SecurityException se) {
-            return null;
-        }
-    }
-
-    private static <T> List<T> tail(int index, List<T> list) {
-        return list.subList(index, list.size());
-    }
-
-    private static <T,R> List<R> tail(int index, Function<T,R> map, List<T> list) {
-        return ListUtils.map(list, map).subList(index, list.size());
-    }
-
-    private static final class SecurityResolver extends SecurityManager implements Resolver {
-
-        private static final int FIRST = 2;
-
-        @Override
-        public Class<?> type(int index) {
-            return super.getClassContext()[FIRST+index];
-        }
-
-        @Override
-        public String name(int index) {
-            return super.getClassContext()[FIRST+index].getName();
-        }
-
-        @Override
-        public List<Class<?>> types() {
-            return tail(FIRST, Arrays.asList(super.getClassContext()));
-        }
-
-        @Override
-        public List<String> names() {
-            return tail(FIRST, Class::getName, Arrays.asList(super.getClassContext()));
-        }
-
-        @Override
-        public List<StackTraceElement> frames() {
-            throw new UnsupportedOperationException("SecurityManager does not support StackTraceElement");
-        }
-
-        @Override
-        public StackTraceElement frame(int index) {
-            throw new UnsupportedOperationException("SecurityManager does not support StackTraceElement");
-        }
-
-    }
-
-    private static final class ThreadResolver implements Resolver {
-
-        private static final int FIRST = 3;
-
-        @Override
-        public List<StackTraceElement> frames() {
-            return tail(FIRST, Arrays.asList(Thread.currentThread().getStackTrace()));
-        }
-
-        @Override
-        public StackTraceElement frame(int index) {
-            return Thread.currentThread().getStackTrace()[FIRST+index];
-        }
-
-        @Override
-        public List<String> names() {
-            return tail(FIRST, StackTraceElement::getClassName, Arrays.asList(Thread.currentThread().getStackTrace()));
-        }
-
-        @Override
-        public String name(int index) {
-            return Thread.currentThread().getStackTrace()[FIRST+index].getClassName();
-        }
-
-        @Override
-        public Class<?> type(int index) {
-            throw new UnsupportedOperationException("ThreadResolver does not support Class<?>");
-        }
-
-        @Override
-        public List<Class<?>> types() {
-            throw new UnsupportedOperationException("ThreadResolver does not support Class<?>");
-        }
-
-
-    }
-
-    private static final class ExceptionResolver implements Resolver {
-
-        private static final int FIRST = 2;
-
-        @Override
-        public List<String> names() {
-            return tail(FIRST, StackTraceElement::getClassName, Arrays.asList(new Exception().getStackTrace()));
-        }
-
-        @Override
-        public String name(int index) {
-            return new Exception().getStackTrace()[FIRST+index].getClassName();
-        }
-
-        @Override
-        public List<StackTraceElement> frames() {
-            return tail(FIRST, Arrays.asList(new Exception().getStackTrace()));
-        }
-
-        @Override
-        public StackTraceElement frame(int index) {
-            return new Exception().getStackTrace()[FIRST+index];
-        }
-
-        @Override
-        public Class<?> type(int index) {
-            throw new UnsupportedOperationException("ExceptionResolver does not support Class<?>");
-        }
-
-        @Override
-        public List<Class<?>> types() {
-            throw new UnsupportedOperationException("ExceptionResolver does not support Class<?>");
-        }
-
+        return getName(2);
     }
 
 }

+ 1 - 1
assira/src/test/java/net/ranides/assira/io/uri/impl/CFileHandlerTest.java

@@ -88,7 +88,7 @@ public class CFileHandlerTest {
         ));
         assertEquals("Hello world", IOStrings.read(handle6.reader()));
 
-        assertEquals(19, handle1.scan().size());
+        assertEquals(21, handle1.scan().size());
         assertEquals(Arrays.asList("indir","text"), handle3.parent().parent().scan().map(f-> asName(f)).sort().list());
         assertEquals(Arrays.asList("info.txt"), handle2.scan().map(f-> asName(f)).sort().list());
         assertThrows(IOException.class, ()->{

+ 136 - 0
assira/src/test/java/net/ranides/assira/trace/FStackWalker6.java

@@ -0,0 +1,136 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.trace;
+
+import net.ranides.assira.collection.lists.ListUtils;
+import net.ranides.assira.generic.ValueUtils;
+
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * This is simplified version of FStackWalker11 class. It uses slow methods, but it is compatible with every JDK.
+ * See: {@code net.ranides.assira.trace.FStackWalker11}
+ */
+public final class FStackWalker6 implements TraceUtils.IStackWalker {
+
+    static final SecurityResolver RESOLVER_SECURITY = getSecurityResolver();
+
+    static final ExceptionResolver RESOLVER_EXCEPT = new ExceptionResolver();
+
+    @Override
+    public List<StackTraceElement> getFrames() {
+        return RESOLVER_EXCEPT.frames();
+    }
+
+    @Override
+    public List<Class<?>> getTypes() {
+        return RESOLVER_SECURITY.types();
+    }
+
+    @Override
+    public List<String> getNames() {
+        return RESOLVER_EXCEPT.names();
+    }
+
+    @Override
+    public Optional<StackTraceElement> getFrame(Predicate<StackTraceElement> filter) {
+        return RESOLVER_EXCEPT.frames().stream().filter(filter).findFirst();
+    }
+
+    @Override
+    public Optional<Class<?>> getType(Predicate<Class<?>> filter) {
+        return RESOLVER_SECURITY.types().stream().filter(filter).findFirst();
+    }
+
+    @Override
+    public Optional<String> getName(Predicate<String> filter) {
+        return RESOLVER_EXCEPT.names().stream().filter(filter).findFirst();
+    }
+
+    @Override
+    public StackTraceElement getFrame(int index) {
+        return RESOLVER_EXCEPT.frame(index);
+    }
+
+    @Override
+    public Class<?> getType(int index) {
+        return RESOLVER_SECURITY.type(index);
+    }
+
+    @Override
+    public String getName(int index) {
+        return RESOLVER_EXCEPT.name(index);
+    }
+
+    private static SecurityResolver getSecurityResolver() {
+        try {
+            return new SecurityResolver();
+        } catch(SecurityException se) {
+            return null;
+        }
+    }
+
+    private static <T> List<T> tail(int index, List<T> list) {
+        return list.subList(index, list.size());
+    }
+
+    private static <T,R> List<R> tail(int index, Function<T,R> map, List<T> list) {
+        return ListUtils.map(list, map).subList(index, list.size());
+    }
+
+    private static final class SecurityResolver extends SecurityManager {
+
+        private static final int FIRST = 3;
+
+        public Class<?> type(int index) {
+            return super.getClassContext()[FIRST+index];
+        }
+
+        public String name(int index) {
+            return super.getClassContext()[FIRST+index].getName();
+        }
+
+        public List<Class<?>> types() {
+            return tail(FIRST, Arrays.asList(super.getClassContext()));
+        }
+
+        public List<String> names() {
+            return tail(FIRST, Class::getName, Arrays.asList(super.getClassContext()));
+        }
+
+    }
+
+    private static final class ExceptionResolver {
+
+        private static final int FIRST = 3;
+
+        public List<String> names() {
+            return tail(FIRST, StackTraceElement::getClassName, Arrays.asList(new Exception().getStackTrace()));
+        }
+
+        public String name(int index) {
+            return new Exception().getStackTrace()[FIRST+index].getClassName();
+        }
+
+        public List<StackTraceElement> frames() {
+            return tail(FIRST, Arrays.asList(new Exception().getStackTrace()));
+        }
+
+        public StackTraceElement frame(int index) {
+            return new Exception().getStackTrace()[FIRST+index];
+        }
+
+    }
+
+}

+ 3 - 148
assira/src/test/java/net/ranides/assira/trace/TraceUtilsTest.java

@@ -36,17 +36,7 @@ public class TraceUtilsTest {
     public void testCalleeName() {
         assertTrue( SI0.runCalleeName0() );
     }
-    
-    @Test
-    public void testGetTypes0() {
-        assertTrue( SI0.runGetTypes0() );
-    }
-    
-    @Test
-    public void testGetNames() {
-        assertTrue( SI0.runGetNames0() );
-    }
-    
+
     @Test
     public void testFrame() {
         assertTrue( SI0.runFrame0() );
@@ -75,17 +65,7 @@ public class TraceUtilsTest {
             SI1.runCalleeName1();
             return true;
         }
-        
-        public static boolean runGetTypes0() {
-            SI1.runGetTypes1();
-            return true;
-        }
-        
-        public static boolean runGetNames0() {
-            SI1.runGetNames1();
-            return true;
-        }
-        
+
         public static boolean runFrame0() {
             SI1.runFrame1();
             return true;
@@ -101,160 +81,37 @@ public class TraceUtilsTest {
             Class<?> caller = SI0.class;
 
             Class callerAuto = TraceUtils.getCallerType();
-            Class callerSM   = TraceUtils.test_getCallerType(TraceUtils.RESOLVER_SECURITY);
-//            Class callerSR   = TraceUtils.test_getCallerType(TraceUtils.RESOLVER_SR);
-
             assertEquals(caller, callerAuto);
-            assertEquals(caller, callerSM);
-//            assertEquals(caller, callerSR);
-            
-            assertThrows(UnsupportedOperationException.class, ()->{
-                TraceUtils.test_getCallerType(TraceUtils.RESOLVER_THREAD);
-            });
-            assertThrows(UnsupportedOperationException.class, ()->{
-                TraceUtils.test_getCallerType(TraceUtils.RESOLVER_EXCEPT);
-            });
         }
         
         public static void runCalleeType1() {
             Class<?> callee = SI1.class;
 
             Class calleeAuto = TraceUtils.getCalleeType();
-            Class calleeSM   = TraceUtils.test_getCalleeType(TraceUtils.RESOLVER_SECURITY);
-//            Class calleeSR   = TraceUtils.test_getCalleeType(TraceUtils.RESOLVER_SR);
-
             assertEquals(callee, calleeAuto);
-            assertEquals(callee, calleeSM);
-//            assertEquals(callee, calleeSR);
-            
-            assertThrows(UnsupportedOperationException.class, ()->{
-                TraceUtils.test_getCalleeType(TraceUtils.RESOLVER_THREAD);
-            });
-            assertThrows(UnsupportedOperationException.class, ()->{
-                TraceUtils.test_getCalleeType(TraceUtils.RESOLVER_EXCEPT);
-            });
         }
         
         public static void runCallerName1() {
             String caller = SI0.class.getName();
             
             String callerAuto = TraceUtils.getCallerName();
-            String callerSM   = TraceUtils.test_getCallerName(TraceUtils.RESOLVER_SECURITY);
-//            String callerSR   = TraceUtils.test_getCallerName(TraceUtils.RESOLVER_SR);
-            String callerTS   = TraceUtils.test_getCallerName(TraceUtils.RESOLVER_THREAD);
-            String callerES   = TraceUtils.test_getCallerName(TraceUtils.RESOLVER_EXCEPT);
-
             assertEquals(caller, callerAuto);
-            assertEquals(caller, callerSM);
-//            assertEquals(caller, callerSR);
-            assertEquals(caller, callerTS);
-            assertEquals(caller, callerES);
         }
         
         public static void runCalleeName1() {
             String callee = SI1.class.getName();
             
             String calleeAuto = TraceUtils.getCalleeName();
-            String calleeSM   = TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_SECURITY);
-//            String calleeSR   = TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_SR);
-            String calleeTS   = TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_THREAD);
-            String calleeES   = TraceUtils.test_getCalleeName(TraceUtils.RESOLVER_EXCEPT);
-
             assertEquals(callee, calleeAuto);
-            assertEquals(callee, calleeSM);
-//            assertEquals(callee, calleeSR);
-            assertEquals(callee, calleeTS);
-            assertEquals(callee, calleeES);
         }
-        
-        public static void runGetTypes1() {
-            Class<?> callee = SI1.class;
-            Class<?> caller = SI0.class;
-                    
-            List<Class<?>> listAuto = TraceUtils.getTypes();
-            List<Class<?>> listSM   = TraceUtils.test_getTypes(TraceUtils.RESOLVER_SECURITY);
-//            List<Class<?>> listSR   = TraceUtils.test_getTypes(TraceUtils.RESOLVER_SR);
-
-            if(false) { //NOPMD
-                dump(listAuto);
-                dump(listSM);
-//                dump(listSR);
-            }
 
-//            assertTrue(
-//                listAuto.equals(listSM) ||
-//                listAuto.equals(listSR)
-//            );
-//
-//            assertEquals(listSM, listSR);
-
-            assertTrue(listSM.size() > 5);
-
-            assertEquals(callee, listSM.get(0));
-//            assertEquals(callee, listSR.get(0));
-            
-            assertEquals(caller, listSM.get(1));
-//            assertEquals(caller, listSR.get(1));
-            
-            assertThrows(UnsupportedOperationException.class, ()->{
-                TraceUtils.test_getTypes(TraceUtils.RESOLVER_THREAD);
-            });
-            assertThrows(UnsupportedOperationException.class, ()->{
-                TraceUtils.test_getTypes(TraceUtils.RESOLVER_EXCEPT);
-            });
-        }
-        
-        public static void runGetNames1() {
-            String callee = SI1.class.getName();
-            String caller = SI0.class.getName();
-            
-            List<String> listAuto = TraceUtils.getNames();
-            List<String> listSM  = TraceUtils.test_getNames(TraceUtils.RESOLVER_SECURITY);
-//            List<String> listSR  = TraceUtils.test_getNames(TraceUtils.RESOLVER_SR);
-            List<String> listTS  = TraceUtils.test_getNames(TraceUtils.RESOLVER_THREAD);
-            List<String> listES  = TraceUtils.test_getNames(TraceUtils.RESOLVER_EXCEPT);
-
-            if(false) { //NOPMD
-                dump(listAuto);
-                dump(listSM);
-//                dump(listSR);
-                dump(listTS);
-                dump(listES);
-            }
-
-            assertTrue(
-                listAuto.equals(listSM) ||
-                /*listAuto.equals(listSR) ||*/
-                listAuto.equals(listTS) ||
-                listAuto.equals(listES) 
-            );
-
-//            assertEquals(listSM, listSR);
-            assertEquals(listTS, listES);
-
-            assertTrue(listSM.size() > 5);
-            assertTrue(listSM.size() <= listTS.size());
-
-            assertEquals(callee, listSM.get(0));
-//            assertEquals(callee, listSR.get(0));
-            assertEquals(callee, listTS.get(0));
-            assertEquals(callee, listES.get(0));
-
-            assertEquals(caller, listSM.get(1));
-//            assertEquals(caller, listSR.get(1));
-            assertEquals(caller, listTS.get(1));
-            assertEquals(caller, listES.get(1));
-        }
         
         public static void runFrame1() {
             List<StackTraceElement> frames = TraceUtils.getFrames();
-            List<String> names = TraceUtils.test_getNames(TraceUtils.RESOLVER_THREAD);
-            
+
             if(false) { // NOPMD
                 System.out.printf("frames = %d%n", frames.size());
-                System.out.printf("names = %d%n", names.size());
                 dump(frames);
-                dump(names);
             }
             
             Wildcard callee = Wildcard.compile("net.ranides.assira.trace.TraceUtilsTest$SI1.runFrame1(TraceUtilsTest.java:*)");
@@ -267,8 +124,6 @@ public class TraceUtilsTest {
             assertTrue(callee.test(frames.get(0).toString()));
             assertTrue(caller.test(frames.get(1).toString()));
             assertTrue(frame2.test(frames.get(2).toString()));
-
-            assertEquals(frames.size(), names.size());
         }
 
     }

+ 55 - 7
pom.xml

@@ -11,8 +11,8 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <maven.compiler.source>11</maven.compiler.source>
-        <maven.compiler.target>11</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
         <netbeans.hint.license>WTFPL</netbeans.hint.license>
         <assira.junit.debug>false</assira.junit.debug>
 
@@ -26,20 +26,46 @@
     </properties>
 
     <modules>
-<!--        <module>assira.asm</module>-->
         <module>assira.junit</module>
         <module>assira.rules</module>
         <module>assira.rules.test</module>
         <module>assira.test</module>
         <module>assira.drafts</module>
-        <module>assira.benchmark</module>
         <module>assira</module>
         <module>assira.all</module>
         <module>assira.archetype</module>
         <module>assira.enterprise</module>
-        <module>assira.lambda</module>
     </modules>
 
+    <profiles>
+        <profile>
+            <id>asm</id>
+            <modules>
+                <module>assira.asm</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>jdk8</id>
+            <activation>
+                <jdk>1.8</jdk>
+            </activation>
+            <modules>
+                <module>assira.jdk8</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>11</jdk>
+            </activation>
+            <modules>
+                <module>assira.jdk11</module>
+                <module>assira.lambda</module>
+                <module>assira.benchmark</module>
+            </modules>
+        </profile>
+    </profiles>
+
     <distributionManagement>
         <repository>
             <id>maven.ranides.net</id>
@@ -195,6 +221,18 @@
                 <artifactId>assira.asm</artifactId>
                 <version>7.1</version>
             </dependency>
+            <dependency>
+                <groupId>net.ranides</groupId>
+                <artifactId>assira.jdk8</artifactId>
+                <version>${project.version}</version>
+                <scope>runtime</scope>
+            </dependency>
+            <dependency>
+                <groupId>net.ranides</groupId>
+                <artifactId>assira.jdk11</artifactId>
+                <version>${project.version}</version>
+                <scope>runtime</scope>
+            </dependency>
             <dependency>
                 <groupId>net.ranides</groupId>
                 <artifactId>assira.junit</artifactId>
@@ -238,12 +276,22 @@
             <dependency>
                 <groupId>com.fasterxml.jackson.core</groupId>
                 <artifactId>jackson-core</artifactId>
-                <version>2.9.5</version>
+                <version>2.9.9</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-databind</artifactId>
+                <version>2.9.9.3</version>
             </dependency>
             <dependency>
                 <groupId>com.fasterxml.jackson.datatype</groupId>
                 <artifactId>jackson-datatype-json-org</artifactId>
-                <version>2.9.5</version>
+                <version>2.9.9</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.datatype</groupId>
+                <artifactId>jackson-datatype-jsr310</artifactId>
+                <version>2.9.9</version>
             </dependency>
             <dependency>
                 <groupId>se.fishtank</groupId>