changeset 18:782051f66932

JDK9 support. ANC, report, issue coverage improvements.
author afedorch
date Tue, 11 Jul 2017 16:16:12 -0700
parents c7a7c279c3a6
children c3aed4b2d93d
files build/build.properties build/build.xml src/classes/com/sun/tdk/jcov/Agent.java src/classes/com/sun/tdk/jcov/DiffCoverage.java src/classes/com/sun/tdk/jcov/Filter.java src/classes/com/sun/tdk/jcov/Grabber.java src/classes/com/sun/tdk/jcov/Instr.java src/classes/com/sun/tdk/jcov/IssueCoverage.java src/classes/com/sun/tdk/jcov/JREInstr.java src/classes/com/sun/tdk/jcov/RepGen.java src/classes/com/sun/tdk/jcov/insert/AbstractUniversalInstrumenter.java src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java src/classes/com/sun/tdk/jcov/instrument/ClassMorph2.java src/classes/com/sun/tdk/jcov/instrument/ConcealedPackagesAttribute.java src/classes/com/sun/tdk/jcov/instrument/DeferringMethodClassAdapter.java src/classes/com/sun/tdk/jcov/instrument/EntryCodeMethodAdapter.java src/classes/com/sun/tdk/jcov/instrument/FieldAnnotationVisitor.java src/classes/com/sun/tdk/jcov/instrument/ForkingMethodAdapter.java src/classes/com/sun/tdk/jcov/instrument/HashesAttribute.java src/classes/com/sun/tdk/jcov/instrument/InstrumentationOptions.java src/classes/com/sun/tdk/jcov/instrument/InstrumentationParams.java src/classes/com/sun/tdk/jcov/instrument/InstrumentedAttributeClassAdapter.java src/classes/com/sun/tdk/jcov/instrument/InvokeClassAdapter.java src/classes/com/sun/tdk/jcov/instrument/InvokeMethodAdapter.java src/classes/com/sun/tdk/jcov/instrument/MethodAnnotationAdapter.java src/classes/com/sun/tdk/jcov/instrument/ModuleAttribute.java src/classes/com/sun/tdk/jcov/instrument/OffsetRecordingMethodAdapter.java src/classes/com/sun/tdk/jcov/instrument/OverriddenClassWriter.java src/classes/com/sun/tdk/jcov/instrument/SavePointsMethodAdapter.java src/classes/com/sun/tdk/jcov/instrument/StaticInvokeMethodAdapter.java src/classes/com/sun/tdk/jcov/processing/CombinerDataProcessor.java src/classes/com/sun/tdk/jcov/report/ClassCoverage.java src/classes/com/sun/tdk/jcov/report/DefaultReportGeneratorSPI.java src/classes/com/sun/tdk/jcov/report/MethodCoverage.java src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java src/classes/com/sun/tdk/jcov/report/javap/JavapClass.java src/classes/com/sun/tdk/jcov/tools/JCovTool.java src/classes/com/sun/tdk/jcov/util/Utils.java
diffstat 38 files changed, 1146 insertions(+), 511 deletions(-) [+]
line wrap: on
line diff
--- a/build/build.properties	Thu Mar 16 14:03:52 2017 +0300
+++ b/build/build.properties	Tue Jul 11 16:16:12 2017 -0700
@@ -21,8 +21,8 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 
-# path to asm5 library
-asmjar5 = asm5.jar
+# path to asm6 library
+asmjar = asm6.jar
 # path to javatest library (empty value allowed if you do not need jtobserver.jar)
 javatestjar = javatest.jar
 
--- a/build/build.xml	Thu Mar 16 14:03:52 2017 +0300
+++ b/build/build.xml	Tue Jul 11 16:16:12 2017 -0700
@@ -32,7 +32,7 @@
 
     <!-- Build area -->
     <property name="build.dir" location="${result.dir}/jcov_${build.version}"/>
-    <property name="jcov.classpath" value="${asmjar5}:${java.home}/lib/tools.jar"/>
+    <property name="jcov.classpath" value="${asmjar}:${java.home}/lib/tools.jar"/>
 
     <!-- Temp dir is for files which do not appear in release directory -->
     <property name="tmp.dir" location="${result.dir}/temp"/>
@@ -96,7 +96,7 @@
 
     <target name="prepare" depends="clean" description="checks dependencies">
 
-        <available file="${asmjar5}" property="asm.present"/>
+        <available file="${asmjar}" property="asm.present"/>
         <fail unless="asm.present" message="Please, specify asm library"/>
 
         <condition property="javatest.present">
@@ -159,13 +159,13 @@
     <target name="compile"  depends="prepare, build-date"
             description="compile main tools">
 
-        <javac encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
+        <javac includeantruntime="false" encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
                srcdir="${jcov.src.update}"
                destdir="${jcov.classes}"
                classpath="${jcov.classpath}">
         </javac>
 
-        <javac encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
+        <javac includeantruntime="true" encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
                srcdir="${src.dir}"
                destdir="${jcov.classes}"
                classpath="${jcov.classpath}">
@@ -182,7 +182,7 @@
     </patternset>
 
     <target name="build-jcov" depends="compile" description="build jcov jar">
-        <unjar src="${asmjar5}" dest="${jcov.classes}"/>
+        <unjar src="${asmjar}" dest="${jcov.classes}"/>
 
         <mkdir dir="${jcov.classes}/META-INF"/>
         <mkdir dir="${jcov.classes}/META-INF/services"/>
@@ -236,7 +236,7 @@
                 </filterreader>
             </filterchain>
         </copy>
-        <javac encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
+        <javac includeantruntime="false" encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
                srcdir="${jcov.filesaver.src}"
                sourcepath=""
                classpath="${jcov.filesaver.classes}"
@@ -270,7 +270,7 @@
                 </filterreader>
             </filterchain>
         </copy>
-        <javac encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
+        <javac includeantruntime="false" encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
                srcdir="${jcov.networksaver.src}"
                sourcepath=""
                classpath="${jcov.networksaver.classes}"
@@ -287,7 +287,7 @@
 
     <target name="build-jt.observer" depends="prepare" if ="javatest.present" description="build jtobserver jar">
         <mkdir dir="${jcov.jtobserver.classes}"/>
-        <javac encoding="iso-8859-1" debug="true" target="1.6" source="1.6"
+        <javac includeantruntime="false" encoding="iso-8859-1" debug="true" target="1.5" source="1.5"
                srcdir="${src.dir}"
                sourcepath=""
                destdir="${jcov.jtobserver.classes}" classpath="${javatestjar}">
--- a/src/classes/com/sun/tdk/jcov/Agent.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/Agent.java	Tue Jul 11 16:16:12 2017 -0700
@@ -516,18 +516,18 @@
     private void updateModules(){
         try {
             Class layer = Class.forName("java.lang.module.Layer");
-            java.lang.reflect.Method bootMethod = layer.getDeclaredMethod("boot", null);
-            Object layerObj = bootMethod.invoke(layer, null);
+            java.lang.reflect.Method bootMethod = layer.getDeclaredMethod("boot");
+            Object layerObj = bootMethod.invoke(layer);
 
-            java.lang.reflect.Method allModulesD = layer.getDeclaredMethod("allModuleDescriptors", null);
+            java.lang.reflect.Method allModulesD = layer.getDeclaredMethod("allModuleDescriptors");
             allModulesD.setAccessible(true);
-            Set<Object> mDescriptors = (Set<Object>) allModulesD.invoke(layerObj, null);
+            Set<Object> mDescriptors = (Set<Object>) allModulesD.invoke(layerObj);
 
             Class moduleDescriptor = Class.forName("java.lang.module.ModuleDescriptor");
             java.lang.reflect.Method nameMethod = moduleDescriptor.getDeclaredMethod("name");
 
             for (Object md : mDescriptors){
-                String moduleName = (String) nameMethod.invoke(md, null);
+                String moduleName = (String) nameMethod.invoke(md);
                 updateModule(moduleName, layer, layerObj);
             }
         }
@@ -539,11 +539,11 @@
         try{
             java.lang.reflect.Method findModule = layer.getDeclaredMethod("findModule", String.class);
             Object moduleOptional = findModule.invoke(layerObj, name);
-            java.lang.reflect.Method getMethod = moduleOptional.getClass().getDeclaredMethod("get", null);
-            Object module = getMethod.invoke(moduleOptional, null);
+            java.lang.reflect.Method getMethod = moduleOptional.getClass().getDeclaredMethod("get");
+            Object module = getMethod.invoke(moduleOptional);
 
-            java.lang.reflect.Method getModuleMethod = Class.class.getDeclaredMethod("getModule", null);
-            Object jcovModule = getModuleMethod.invoke(Class.forName("com.sun.tdk.jcov.runtime.CollectDetect"), null);
+            java.lang.reflect.Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object jcovModule = getModuleMethod.invoke(Class.forName("com.sun.tdk.jcov.runtime.CollectDetect"));
             java.lang.reflect.Method addReadsMethod = module.getClass().getDeclaredMethod("addReads", Class.forName("java.lang.reflect.Module"));
             addReadsMethod.invoke(module, jcovModule);
         }
--- a/src/classes/com/sun/tdk/jcov/DiffCoverage.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/DiffCoverage.java	Tue Jul 11 16:16:12 2017 -0700
@@ -60,8 +60,8 @@
      */
     public static class SourceLine {
 
-        private int line;
-        private String source;
+        public int line;
+        public String source;
         boolean checked;
         boolean codeByDefault = true;
 
--- a/src/classes/com/sun/tdk/jcov/Filter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/Filter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -142,6 +142,10 @@
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FM,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FM_LIST,
+                    InstrumentationOptions.DSC_MINCLUDE,
+                    InstrumentationOptions.DSC_MINCLUDE_LIST,
+                    InstrumentationOptions.DSC_MEXCLUDE,
+                    InstrumentationOptions.DSC_MEXCLUDE_LIST,
                     DSC_FILTER_PLUGIN,
                     DSC_SYNTHETIC
                 }, this);
--- a/src/classes/com/sun/tdk/jcov/Grabber.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/Grabber.java	Tue Jul 11 16:16:12 2017 -0700
@@ -27,9 +27,8 @@
 import com.sun.tdk.jcov.constants.MiscConstants;
 import com.sun.tdk.jcov.data.FileFormatException;
 import com.sun.tdk.jcov.data.Result;
-import com.sun.tdk.jcov.instrument.DataRoot;
+import com.sun.tdk.jcov.instrument.*;
 import com.sun.tdk.jcov.instrument.DataRoot.CompatibilityCheckResult;
-import com.sun.tdk.jcov.instrument.InstrumentationOptions;
 import com.sun.tdk.jcov.instrument.InstrumentationOptions.MERGE;
 import com.sun.tdk.jcov.runtime.Collect;
 import com.sun.tdk.jcov.runtime.FileSaver;
@@ -42,6 +41,8 @@
 import com.sun.tdk.jcov.util.RuntimeUtils;
 import com.sun.tdk.jcov.util.Utils;
 import com.sun.tdk.jcov.util.Utils.Pair;
+import org.objectweb.asm.Opcodes;
+
 import java.io.*;
 import java.net.*;
 import java.nio.charset.Charset;
@@ -825,6 +826,18 @@
                 if (templateName != null) {
                     //do not need it at all
                     dataRoot.update();
+                    if (dataRoot.getParams().isInstrumentAbstract() || dataRoot.getParams().isInstrumentNative()) {
+                        for (DataPackage dp : dataRoot.getPackages()) {
+                            for (DataClass dc : dp.getClasses()) {
+                                for (DataMethod dm : dc.getMethods()) {
+                                    if ((dm.isAbstract() || (dm.getAccess() & Opcodes.ACC_NATIVE) != 0)
+                                            && data.length > dm.getSlot() && dm.getCount() < data[dm.getSlot()]) {
+                                        dm.setCount(data[dm.getSlot()]);
+                                    }
+                                }
+                            }
+                        }
+                    }
                 }
                 FileSaver fs = FileSaver.getFileSaver(dataRoot, fileName, templateName, MERGE.OVERWRITE, false, true);
                 fs.saveResults(fileName);
--- a/src/classes/com/sun/tdk/jcov/Instr.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/Instr.java	Tue Jul 11 16:16:12 2017 -0700
@@ -37,6 +37,7 @@
 import com.sun.tdk.jcov.util.Utils;
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -59,6 +60,8 @@
     private String[] m_exclude = new String[]{""};
     private String[] callerInclude;
     private String[] callerExclude;
+    private String[] innerInclude;
+    private String[] innerExclude;
     private String[] save_beg = null;
     private String[] save_end = null;
     private boolean genabstract = false;
@@ -205,6 +208,18 @@
         }
     }
 
+    public void instrumentTests(String[] files, File outDir, String implantRT) throws IOException {
+
+        if (gennative || genabstract) {
+            morph.fillIntrMethodsIDs(morph.getRoot());
+        }
+
+        setDefaultInstrumenter();
+        for (String file : files) {
+            instrumenter.instrument(new File(file), outDir, implantRT, recurse);
+        }
+    }
+
     /**
      * Begin instrumentation in semi-automatic mode
      *
@@ -223,7 +238,9 @@
             InstrumentationParams params = new InstrumentationParams(innerinvocations, false, false, gennative, genfield, false, genabstract ? InstrumentationOptions.ABSTRACTMODE.DIRECT : InstrumentationOptions.ABSTRACTMODE.NONE, include, exclude, callerInclude, callerExclude, m_include, m_exclude, mode, save_beg, save_end)
                     .setInstrumentSynthetic(gensynthetic)
                     .setInstrumentAnonymous(genanonymous)
-                    .setInnerInvocations(innerinvocations);
+                    .setInnerInvocations(innerinvocations)
+                    .setInnerIncludes(innerInclude)
+                    .setInnerExcludes(innerExclude);
             if (subsequentInstr) {
                 morph = new ClassMorph(params, template);
             } else {
@@ -243,6 +260,21 @@
                         morph.saveData(template, null, MERGE.OVERWRITE); // template should be initialized
                     }
                 }
+
+                public void processClassFileInModules(Path filePath, File outDir){
+                    if (morph != null){
+                        if (filePath != null){
+                            String mpath = filePath.toAbsolutePath().toString();
+                            mpath = mpath.substring("/modules/".length());
+                            if (mpath.indexOf("/") != -1){
+                                String module_name = mpath.substring(0, mpath.indexOf("/"));
+                                morph.setCurrentModuleName(module_name);
+                            }
+                        }
+                        super.processClassFileInModules(filePath, outDir);
+                    }
+                }
+
             };
         }
     }
@@ -394,6 +426,14 @@
         this.callerExclude = callerExclude;
     }
 
+    public void setInnerInclude(String[] include) {
+        this.innerInclude = include;
+    }
+
+    public void setInnerExclude(String[] exclude) {
+        this.innerExclude = exclude;
+    }
+
     public void setFilter(String[] include, String exclude[]) {
         this.include = include;
         this.exclude = exclude;
@@ -582,6 +622,9 @@
         include = InstrumentationOptions.handleInclude(opts);
         exclude = InstrumentationOptions.handleExclude(opts);
 
+        m_include = InstrumentationOptions.handleMInclude(opts);
+        m_exclude = InstrumentationOptions.handleMExclude(opts);
+
         flushPath = opts.getValue(ClassMorph.DSC_FLUSH_CLASSES);
         if ("none".equals(flushPath)) {
             flushPath = null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/classes/com/sun/tdk/jcov/IssueCoverage.java	Tue Jul 11 16:16:12 2017 -0700
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tdk.jcov;
+
+import com.sun.source.tree.*;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+import com.sun.tdk.jcov.filter.MemberFilter;
+import com.sun.tdk.jcov.instrument.*;
+import com.sun.tdk.jcov.processing.DataProcessorSPI;
+import com.sun.tdk.jcov.processing.DefaultDataProcessorSPI;
+import com.sun.tdk.jcov.processing.StubSpi;
+import com.sun.tdk.jcov.report.*;
+import com.sun.tdk.jcov.tools.*;
+import com.sun.tdk.jcov.util.Utils;
+
+import javax.tools.*;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * @author Alexey Fedorchenko
+ */
+public class IssueCoverage extends JCovCMDTool {
+
+    final static String DATA_PROCESSOR_SPI = "dataprocessor.spi";
+
+    private String hg_path = "hg";
+    private String hg_repo_dir = "jdk";
+    private String output = "report";
+    private String hg_comment = "";
+    private DataProcessorSPI dataProcessorSPIs[];
+    private static final Logger logger;
+    private String resultFile;
+    private String replaceDiff = "";
+    private HashMap<String, DiffCoverage.SourceLine[]> sources;
+
+
+    static {
+        Utils.initLogger();
+        logger = Logger.getLogger(IssueCoverage.class.getName());
+    }
+
+
+    @Override
+    protected int run() throws Exception {
+
+        String[] command = new String[]{hg_path, "log", "-k", hg_comment};
+
+        ProcessBuilder pb =
+                new ProcessBuilder(command)
+                        .directory(new File(hg_repo_dir));
+
+        Process proc = pb.start();
+
+        InputStream inputStream = proc.getInputStream();
+        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+        String logline;
+        ArrayList<Integer> changesets = new ArrayList<Integer>();
+        while ((logline = br.readLine()) != null) {
+            if (logline.contains("changeset:")) {
+                try {
+                    changesets.add(Integer.parseInt(logline.split(":")[1].trim()));
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        if (changesets.size() == 0) {
+            logger.log(Level.SEVERE, "No changes found in the repository for " + hg_comment);
+            return ERROR_EXEC_EXIT_CODE;
+        }
+
+        String[] change_command = new String[changesets.size() + 2];
+        change_command[0] = hg_path;
+        change_command[1] = "diff";
+        for (int i = 0; i < changesets.size(); i++) {
+            change_command[i + 2] = "-c " + changesets.get(i);
+        }
+
+        ProcessBuilder pb1 =
+                new ProcessBuilder(change_command)
+                        .directory(new File(hg_repo_dir));
+
+        Process proc1 = pb1.start();
+        InputStream patchInputStream = proc1.getInputStream();
+
+        try {
+            BufferedReader in = new BufferedReader(new InputStreamReader(patchInputStream, "UTF-8"));
+            DiffCoverage.DiffHandler handler = new DiffCoverage.HGDiffHandler(in);
+            sources = new HashMap<String, DiffCoverage.SourceLine[]>();
+            String sourceName;
+            while ((sourceName = handler.getNextSource()) != null) {
+                LinkedList<DiffCoverage.SourceLine> lines = new LinkedList<DiffCoverage.SourceLine>();
+                DiffCoverage.SourceLine line;
+                while ((line = handler.getNextSourceLine()) != null) {
+                    lines.add(line);
+                }
+                if (lines.size() > 0) {
+                    logger.log(Level.INFO, "File {0} has {1} new lines", new Object[]{sourceName, lines.size()});
+
+                    sources.put(sourceName, lines.toArray(new DiffCoverage.SourceLine[lines.size()]));
+                } else {
+                    logger.log(Level.INFO, "File {0} doesn't have new lines", sourceName);
+                }
+            }
+
+        }
+        catch (Exception ex) {
+            logger.log(Level.SEVERE, "Error while parsing diff", ex);
+            return ERROR_EXEC_EXIT_CODE;
+        }
+
+        final HashMap<String, ArrayList<MethodWithParams>> changed = new HashMap<String, ArrayList<MethodWithParams>>();
+        processChangedClasses(changesets, changed);
+
+        DataRoot data = com.sun.tdk.jcov.io.Reader.readXML(resultFile, false, new MemberFilter() {
+            public boolean accept(DataClass clz) {
+
+                String className;
+                if (replaceDiff != null && replaceDiff.contains("#module")) {
+                    className = replaceDiff.replaceAll("\\#module", clz.getModuleName()) + clz.getFullname().substring(0, clz.getFullname().lastIndexOf('/') + 1) + clz.getSource();
+                } else {
+                    className = replaceDiff + clz.getFullname().substring(0, clz.getFullname().lastIndexOf('/') + 1) + clz.getSource();
+                }
+                return (changed.get(className) != null);
+            }
+
+            public boolean accept(DataClass clz, DataMethod m) {
+                return true;
+            }
+
+            public boolean accept(DataClass clz, DataField f) {
+                return true;
+            }
+        });
+
+
+        if (dataProcessorSPIs != null) {
+            for (DataProcessorSPI spi : dataProcessorSPIs) {
+                data = spi.getDataProcessor().process(data);
+            }
+        }
+
+        AncFilter notChanged = new AncFilter() {
+            @Override
+            public boolean accept(DataClass clz) {
+                return false;
+            }
+
+            @Override
+            public boolean accept(DataClass clz, DataMethod m) {
+
+                String className;
+                if (replaceDiff != null && replaceDiff.contains("#module")) {
+                    className = replaceDiff.replaceAll("\\#module", clz.getModuleName()) + clz.getFullname().substring(0, clz.getFullname().lastIndexOf('/') + 1) + clz.getSource();
+
+                } else {
+                    className = replaceDiff + clz.getFullname().substring(0, clz.getFullname().lastIndexOf('/') + 1) + clz.getSource();
+                }
+
+
+                if (changed.get(className) != null) {
+
+                    for (MethodWithParams method : changed.get(className)) {
+
+                        if (m.getName().equals(method.getMethodName()) ||
+                                (m.getName().contains("$") && m.getName().endsWith(method.getMethodName()))) {
+
+                            if (method.getMethodParams().size() == 0 || m.getFormattedSignature().split(",").length == method.getMethodParams().size()
+                                    && m.getFormattedSignature().matches(".*" + method.getParamsRegex())) {
+
+                                method.setFound(true);
+                                return false;
+                            }
+                        }
+                    }
+                }
+
+                return true;
+
+            }
+
+            @Override
+            public boolean accept(DataMethod m, DataBlock b) {
+                return false;
+            }
+
+            @Override
+            public String getAncReason() {
+                return "No changes";
+            }
+        };
+
+        RepGen rr = new RepGen();
+        ReportGenerator rg = rr.getDefaultReportGenerator();
+        try {
+            ReportGenerator.Options options = new ReportGenerator.Options(new File(hg_repo_dir + "/" + replaceDiff).getAbsolutePath(), null, null, false,
+                    false);
+
+            ProductCoverage coverage = new ProductCoverage(data, options.getSrcRootPaths(), options.getJavapClasses(), false, false, false, new AncFilter[]{notChanged});
+
+            for (String classFile : changed.keySet()) {
+                for (MethodWithParams method : changed.get(classFile)) {
+                    if (!method.isFound()) {
+                        logger.log(Level.WARNING, "Could not find changed method {0} from classfile {1}", new String[]{method.toString(), classFile});
+                    }
+                }
+            }
+
+            rg.init(output);
+            rg.generateReport(coverage, options);
+
+
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "Error in report generation:", e);
+        }
+
+        return 0;
+    }
+
+    private void processChangedClasses(ArrayList<Integer> changesets, HashMap<String, ArrayList<MethodWithParams>> changed) {
+        try {
+            ArrayList<String> files = new ArrayList<String>();
+
+            String[] command = new String[]{hg_path, "log", "-k", hg_comment, "--stat"};
+
+            ProcessBuilder pb =
+                    new ProcessBuilder(command)
+                            .directory(new File(hg_repo_dir));
+
+            Process proc = pb.start();
+
+            InputStream inputStream = proc.getInputStream();
+            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+            String classline;
+            while ((classline = br.readLine()) != null) {
+                if (classline.contains("|") && (classline.contains("+") || classline.contains("-"))) {
+                    try {
+                        files.add(classline.split(" ")[1]);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+
+            parseClassFiles(files, changesets.get(0), changed);
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "Error in parsing changed files:", e);
+        }
+    }
+
+    private void parseClassFiles(ArrayList<String> files, int changeset, HashMap<String, ArrayList<MethodWithParams>> changed) {
+        try {
+
+            for (String file : files) {
+
+                String[] command = new String[]{hg_path, "cat", file, "-r", String.valueOf(changeset)};
+
+                ProcessBuilder pb =
+                        new ProcessBuilder(command)
+                                .directory(new File(hg_repo_dir));
+
+                Process proc = pb.start();
+
+                InputStream inputStream = proc.getInputStream();
+
+                final Path destination = Paths.get(new File(hg_repo_dir).getAbsolutePath() + File.pathSeparator + "temp" + File.pathSeparator + ".java");
+                Files.copy(inputStream, destination);
+
+                DiffCoverage.SourceLine lines[] = sources.get(file);
+
+                parseClassFile(destination.toFile(), lines, file, changed);
+                destination.toFile().delete();
+            }
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "Error in parsing changed files:", e);
+        }
+    }
+
+    private void parseClassFile(File c, DiffCoverage.SourceLine lines[], String classFile, HashMap<String, ArrayList<MethodWithParams>> changed) {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        DiagnosticCollector<JavaFileObject> diagnosticsCollector = new DiagnosticCollector<JavaFileObject>();
+        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
+        Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(c);
+        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects);
+
+        JavacTask javacTask = (JavacTask) task;
+        SourcePositions sourcePositions = Trees.instance(javacTask).getSourcePositions();
+        Iterable<? extends CompilationUnitTree> parseResult = null;
+        try {
+            parseResult = javacTask.parse();
+        } catch (IOException e) {
+            logger.log(Level.SEVERE, "Error in parsing source file:", e);
+        }
+
+        if (parseResult != null) {
+            for (CompilationUnitTree compilationUnitTree : parseResult) {
+                compilationUnitTree.accept(new MethodParser(compilationUnitTree, sourcePositions, lines, classFile, changed), null);
+            }
+        }
+    }
+
+    private class MethodParser extends TreeScanner<Void, Void> {
+        private final CompilationUnitTree compilationUnitTree;
+        private final SourcePositions sourcePositions;
+        private final LineMap lineMap;
+        private final DiffCoverage.SourceLine lines[];
+        private HashMap<String, ArrayList<MethodWithParams>> changed;
+        private String classFile;
+        private List<ClassTree> classes;
+
+        private MethodParser(CompilationUnitTree compilationUnitTree, SourcePositions sourcePositions, DiffCoverage.SourceLine lines[], String classFile, HashMap<String, ArrayList<MethodWithParams>> changed) {
+            this.compilationUnitTree = compilationUnitTree;
+            this.sourcePositions = sourcePositions;
+            this.lineMap = compilationUnitTree.getLineMap();
+            this.lines = lines;
+            this.changed = changed;
+            this.classFile = classFile;
+            classes = new ArrayList<ClassTree>();
+        }
+
+        @Override
+        public Void visitClass(ClassTree paramClassTree, Void paramP) {
+            classes.add(paramClassTree);
+            return super.visitClass(paramClassTree, paramP);
+        }
+
+        private String findClassName(MethodTree method) {
+            String simpleName = "";
+            String className = "";
+            HashMap<String, Integer> annonym = new HashMap<String, Integer>();
+            for (ClassTree classTree : classes) {
+
+                simpleName = classTree.getSimpleName().toString();
+
+                if (simpleName.isEmpty()) {
+                    if (annonym.get(className) == null) {
+                        annonym.put(className, 1);
+                    } else {
+                        annonym.put(className, annonym.get(className) + 1);
+                    }
+                } else {
+                    className = String.valueOf(simpleName);
+                }
+                for (Tree tree : classTree.getMembers()) {
+                    if (method.equals(tree)) {
+                        if (simpleName.isEmpty()) {
+                            simpleName = className + "$" + annonym.get(className);
+                        }
+                        return simpleName;
+                    }
+                }
+            }
+            return simpleName;
+        }
+
+        @Override
+        public Void visitMethod(final MethodTree arg0, Void arg1) {
+            long startPosition = sourcePositions.getStartPosition(compilationUnitTree, arg0);
+            long startLine = lineMap.getLineNumber(startPosition);
+            long endPosition = sourcePositions.getEndPosition(compilationUnitTree, arg0);
+            long endLine = lineMap.getLineNumber(endPosition);
+
+            if (lines != null) {
+                for (DiffCoverage.SourceLine line : lines) {
+                    if (line.line >= startLine && line.line <= endLine) {
+
+                        if (changed.get(classFile) == null) {
+                            changed.put(classFile, new ArrayList<MethodWithParams>());
+                        }
+
+                        String simpleClassName = findClassName(arg0);
+
+                        String methodName = classFile.endsWith(simpleClassName + ".java") ? arg0.getName().toString() : "$" + simpleClassName + "." + arg0.getName();
+                        List<String> params = new ArrayList<String>();
+
+                        for (VariableTree vt : arg0.getParameters()) {
+                            params.add(vt.getType().toString());
+                        }
+                        changed.get(classFile).add(new MethodWithParams(methodName, params));
+
+                        return super.visitMethod(arg0, arg1);
+                    }
+                }
+            }
+
+            return super.visitMethod(arg0, arg1);
+        }
+    }
+
+
+    @Override
+    protected EnvHandler defineHandler() {
+        EnvHandler envHandler = new EnvHandler(new OptionDescr[]{
+                DSC_REPLACE_DIFF,
+                DSC_ISSUE_TO_FIND,
+                DSC_REPO_DIR,
+                DSC_OUTPUT,
+                DSC_HG_PATH
+        }, this);
+
+        SPIDescr spiDescr = new SPIDescr(DATA_PROCESSOR_SPI, DataProcessorSPI.class);
+        spiDescr.addPreset("none", new StubSpi());
+        spiDescr.setDefaultSPI(new DefaultDataProcessorSPI());
+        envHandler.registerSPI(spiDescr);
+        return envHandler;
+    }
+
+    @Override
+    protected int handleEnv(EnvHandler envHandler) throws EnvHandlingException {
+        String[] tail = envHandler.getTail();
+
+        if (tail == null) {
+            throw new EnvHandlingException("No input files. Please specify JCov data file and diff (mercurial) file.");
+        }
+
+        ArrayList<DataProcessorSPI> dataProcessors = envHandler.getSPIs(DataProcessorSPI.class);
+        if (dataProcessors != null) {
+            dataProcessorSPIs = dataProcessors.toArray(new DataProcessorSPI[dataProcessors.size()]);
+        }
+
+        replaceDiff = envHandler.getValue(DSC_REPLACE_DIFF);
+        hg_path = envHandler.getValue(DSC_HG_PATH);
+        hg_comment = envHandler.getValue(DSC_ISSUE_TO_FIND);
+        hg_repo_dir = envHandler.getValue(DSC_REPO_DIR);
+        output = envHandler.getValue(DSC_OUTPUT);
+
+        resultFile = tail[0];
+        Utils.checkFileNotNull(tail[0], "JCov datafile", Utils.CheckOptions.FILE_EXISTS, Utils.CheckOptions.FILE_ISFILE, Utils.CheckOptions.FILE_CANREAD);
+
+
+        return SUCCESS_EXIT_CODE;
+    }
+
+    @Override
+    protected String getDescr() {
+        return null;
+    }
+
+    @Override
+    protected String usageString() {
+        return null;
+    }
+
+    @Override
+    protected String exampleString() {
+        return null;
+    }
+
+    class MethodWithParams {
+
+        private String methodName;
+        private List<String> methodParams;
+        private boolean found = false;
+
+        MethodWithParams(String methodName, List<String> methodParams) {
+            this.methodName = methodName;
+            this.methodParams = methodParams;
+        }
+
+        public List<String> getMethodParams() {
+            return methodParams;
+        }
+
+        public void setMethodParams(List<String> methodParams) {
+            this.methodParams = methodParams;
+        }
+
+        public String getMethodName() {
+            return methodName;
+        }
+
+        public void setMethodName(String methodName) {
+            this.methodName = methodName;
+        }
+
+        public String getParamsRegex() {
+
+            if (methodParams.size() == 0) {
+                return "\\(\\)";
+            }
+
+            StringBuilder sb = new StringBuilder();
+            sb.append("\\(");
+
+            for (int i = 0; i < methodParams.size(); i++) {
+
+                String param = methodParams.get(i);
+                if (param.equals("K") || param.equals("V")) {
+                    param = "Object";
+                }
+                if (param.contains("<")) {
+                    param = param.substring(0, param.indexOf("<"));
+                }
+                param = Pattern.quote(param);
+
+                if (i < methodParams.size() - 1) {
+                    sb.append(".*").append(param).append(",");
+                } else {
+                    sb.append(".*").append(param).append("\\)");
+                }
+            }
+
+            return sb.toString();
+
+        }
+
+        public boolean isFound() {
+            return found;
+        }
+
+        public void setFound(boolean found) {
+            this.found = found;
+        }
+
+        public String toString() {
+            StringBuilder result = new StringBuilder();
+            result.append(methodName).append("( ");
+            for (String param : methodParams) {
+                result.append(param).append(" ");
+            }
+            result.append(")");
+
+            return result.toString();
+        }
+    }
+
+    static OptionDescr DSC_HG_PATH = new OptionDescr("hgPath", new String[]{"hgPath", "hg"}, "", OptionDescr.VAL_SINGLE, "Path to the hg", "hg");
+    static OptionDescr DSC_REPLACE_DIFF = new OptionDescr("replaceDiff", "Manage replacing", OptionDescr.VAL_SINGLE, "Set replacement pattern for diff filenames (e.g. to cut out \"src/classes\" you can specify -replaceDiff src/classes:)");
+    static OptionDescr DSC_ISSUE_TO_FIND = new OptionDescr("issueToFind", new String[]{"issueToFind","if"}, "", OptionDescr.VAL_SINGLE, "Set issue identifier to find in repository history");
+    static OptionDescr DSC_REPO_DIR = new OptionDescr("localRepo", new String[]{"localRepo", "lr"}, "", OptionDescr.VAL_SINGLE, "Path to the local repository");
+    static OptionDescr DSC_OUTPUT = new OptionDescr("output", new String[]{"output", "o"}, "", OptionDescr.VAL_SINGLE,
+                    "Output directory for generating HTML report.", "report");
+}
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/JREInstr.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/JREInstr.java	Tue Jul 11 16:16:12 2017 -0700
@@ -65,6 +65,8 @@
     private File javac;
     private String[] callerInclude;
     private String[] callerExclude;
+    private String[] innerInclude;
+    private String[] innerExclude;
     private static final Logger logger;
     private String host = null;
     private Integer port = null;
@@ -115,10 +117,15 @@
             }
             File jmodsTemp = new File(toInstrument.getParentFile(), "jmod_temp");
 
+            ArrayList<URL> urls = new ArrayList<URL>();
             for (File mod : toInstrument.listFiles()) {
                 File jmodDir = extractJMod(jdk, mod.getAbsoluteFile(), jmodsTemp);
-                Utils.addToClasspath(new String[]{new File(jmodDir, "classes").getAbsolutePath()});
+                urls.add(new File(jmodDir, "classes").toURI().toURL());
             }
+            urls.add(toInstrument.toURI().toURL());
+
+            cl = new StaticJREInstrClassLoader(urls.toArray(new URL[urls.size()]));
+            instr.setClassLoader(cl);
 
             try {
                 for (File mod : jmodsTemp.listFiles()) {
@@ -126,10 +133,9 @@
 
                         File modClasses = new File(mod, "classes");
                         if ("java.base".equals(mod.getName())) {
-                            updateExports(new File(modClasses, "module-info.class"), cl);
-                        } else {
-                            updateHashes(new File(modClasses, "module-info.class"), cl);
+                            addJCovRuntimeToJavaBase(new File(modClasses, "module-info.class"), cl);
                         }
+                        updateHashes(new File(modClasses, "module-info.class"), cl);
 
                         instr.instrumentFile(modClasses.getAbsolutePath(), null, null, mod.getName());
                         createJMod(mod, jdk, implant.getAbsolutePath());
@@ -241,30 +247,41 @@
             }
         }
 
-        if (addTests != null) {
-            if (srcs == null) {
-                srcs = new ArrayList<String>();
-            }
-            for (int i = 0; i < addTests.length; ++i) {
-                srcs.add(addTests[i].getAbsolutePath());
-            }
-        }
-
         if (srcs != null) {
             Utils.addToClasspath(srcs.toArray(new String[0]));
             instr.instrumentFiles(srcs.toArray(new String[0]), null, null);
         }
+
+        if (addTests != null) {
+            ArrayList<String> tests = new ArrayList<String>();
+            for (int i = 0; i < addTests.length; ++i) {
+                tests.add(addTests[i].getAbsolutePath());
+            }
+            instr.instrumentTests(tests.toArray(new String[0]), null, null);
+        }
+
         instr.finishWork();
         return SUCCESS_EXIT_CODE;
     }
 
 
-    private void updateExports(File file, ClassLoader cl) {
+    private void addJCovRuntimeToJavaBase(File file, ClassLoader cl) {
         try {
             InputStream in = new FileInputStream(file.getCanonicalPath());
             ClassReader cr = new ClassReader(in);
             ClassWriter cw = new OverriddenClassWriter(cr, ClassWriter.COMPUTE_FRAMES, cl);
-            cr.accept(cw, new Attribute[]{new ConcealedPackagesAttribute(), new ModuleAttribute()}, 0);
+
+            ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
+                @Override
+                public ModuleVisitor visitModule(String name, int access, String version) {
+                    ModuleVisitor mv = super.visitModule(name, access, version);
+                    mv.visitPackage("com/sun/tdk/jcov/runtime");
+                    mv.visitExport("com/sun/tdk/jcov/runtime", 0);
+                    return mv;
+                }
+            };
+
+            cr.accept(cv, 0);
 
             DataOutputStream dout = new DataOutputStream(new FileOutputStream(file.getCanonicalPath()));
             dout.write(cw.toByteArray());
@@ -272,7 +289,7 @@
             in.close();
             dout.close();
         } catch (Exception e) {
-            logger.log(Level.SEVERE, "can not update module exports", e);
+            logger.log(Level.SEVERE, "can not update java.base", e);
         }
     }
 
@@ -281,7 +298,7 @@
             InputStream in = new FileInputStream(file.getCanonicalPath());
             ClassReader cr = new ClassReader(in);
             ClassWriter cw = new OverriddenClassWriter(cr, ClassWriter.COMPUTE_FRAMES, cl);
-            cr.accept(cw, new Attribute[]{new ConcealedPackagesAttribute(), new HashesAttribute()}, 0);
+            cr.accept(cw, new Attribute[]{new HashesAttribute()}, 0);
 
             DataOutputStream doutn = new DataOutputStream(new FileOutputStream(file.getCanonicalPath()));
             doutn.write(cw.toByteArray());
@@ -319,7 +336,7 @@
     private File runJLink(File jmodDir, File jdk) {
         try {
 
-            String command = jdk.getAbsolutePath() + File.separator + "bin" + File.separator + "jlink --modulepath " + jmodDir.getCanonicalPath() + " --addmods ";
+            String command = jdk.getAbsolutePath() + File.separator + "bin" + File.separator + "jlink --module-path " + jmodDir.getCanonicalPath() + " --add-modules ";
 
             StringBuilder sb = new StringBuilder("");
             for (File subDir : jmodDir.listFiles()) {
@@ -348,8 +365,8 @@
         try {
             File modsDir = jmodDir.getParentFile();
             StringBuilder command = new StringBuilder();
-            command.append(jdk.getAbsolutePath() + File.separator + "bin" + File.separator + "jmod --create ");
-            command.append("--modulepath " + modsDir.getCanonicalPath() + " ");
+            command.append(jdk.getAbsolutePath() + File.separator + "bin" + File.separator + "jmod create ");
+            command.append("--module-path " + modsDir.getCanonicalPath() + " ");
 
             for (File subDir : jmodDir.listFiles()) {
                 if (subDir.getName().equals("classes")) {
@@ -439,6 +456,8 @@
                 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SYNTHETIC,
                 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ANONYM,
                 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNERINVOCATION,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNER_INCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNER_EXCLUDE,
                 Instr.DSC_SUBSEQUENT,
                 DSC_JAVAC_HACK,
                 DCS_ADD_JAR,
@@ -712,6 +731,9 @@
         callerInclude = envHandler.getValues(com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE);
         callerExclude = envHandler.getValues(com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE);
 
+        innerInclude = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleInnerInclude(envHandler);
+        innerExclude = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleInnerExclude(envHandler);
+
         if (!Utils.accept(pats, null, "/java/lang/Shutdown", null)) {
             // Shutdown was excluded with some filtering mechanism. No need to remove it from excludes as inclusion has more priority
             logger.log(Level.WARNING, "java.lang.Shutdown automatically included to instrumentation (it can't be excluded in jreinstr)");
@@ -738,11 +760,14 @@
         instr.setExclude(excludes);
 
         instr.setMInclude(m_includes);
-         instr.setMExclude(m_excludes);
+        instr.setMExclude(m_excludes);
 
         instr.setCallerInclude(callerInclude);
         instr.setCallerExclude(callerExclude);
 
+        instr.setInnerInclude(innerInclude);
+        instr.setInnerExclude(innerExclude);
+
         return ret;
     }
 
--- a/src/classes/com/sun/tdk/jcov/RepGen.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/RepGen.java	Tue Jul 11 16:16:12 2017 -0700
@@ -805,7 +805,7 @@
             ancMethod = ancMethod
                     || (clz.getSuperName().equals("java/lang/Enum") && (m.getName().equals("valueOf") || m.getName().equals("values")));
 
-            return !ancMethod;
+            return !ancMethod || m.getName().startsWith("lambda$");
 
         }
 
--- a/src/classes/com/sun/tdk/jcov/insert/AbstractUniversalInstrumenter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/insert/AbstractUniversalInstrumenter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -24,6 +24,7 @@
  */
 package com.sun.tdk.jcov.insert;
 
+import com.sun.tdk.jcov.instrument.OverriddenClassWriter;
 import com.sun.tdk.jcov.runtime.PropertyFinder;
 import com.sun.tdk.jcov.util.Utils;
 import java.io.BufferedInputStream;
@@ -34,6 +35,9 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.net.URI;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.logging.Level;
@@ -612,6 +616,8 @@
                     processArc(instrumentingPath, destinationPath, null);
                 }
             }
+        } else if (instrumentingPath.getName().equals("modules")) {
+            instrumentModulesFile(instrumentingPath, destinationPath);
         } else if (isClassFile(instrumentingPath.getName())) {
             if (destinationPath == null) {
                 destinationPath = instrumentingPath;
@@ -630,6 +636,84 @@
         }
     }
 
+    public void processClassFileInModules(Path file, File destinationPath){
+        String fname = file.toAbsolutePath().toString();
+        try {
+            final String distinationStr = destinationPath.toString();
+            classBuf = Files.readAllBytes(file);
+            int classLength = classBuf.length;
+            byte[] outBuf = null;
+            try {
+                if (!"module-info.class".equals(file.getFileName().toString())) {
+                    outBuf = instrument(classBuf, classLength);
+                }
+            } catch (IOException e) {
+                logger.log(Level.SEVERE, "  Error reading data from '" + fname + "' - skipped", e);
+            } catch (NullPointerException e) {
+                logger.log(Level.SEVERE, "  Error reading data from '" + fname + "' - skipped", e);
+            } catch (Exception e) {
+                logger.log(Level.SEVERE, "  Error instrumenting '" + fname + "' - skipped", e);
+            }
+            if (outBuf != null) {
+
+                classLength = outBuf.length;
+
+                File outFile = new File(distinationStr + File.separator + fname);
+                String parentName = outFile.getParent();
+                if (parentName != null) {
+                    File parent = new File(parentName);
+                    if (!parent.exists()) {
+                        parent.mkdirs();
+                    }
+                }
+                // write instrumented classfile
+                FileOutputStream fos = new FileOutputStream(outFile);
+                fos.write(outBuf, 0, classLength);
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    logger.log(Level.SEVERE, "  Error writing data to '" + outFile.getAbsolutePath() + "' - skipped", e);
+                }
+            }
+        }
+        catch(IOException e){
+            logger.log(Level.SEVERE, "  Error processing classFile by Path '" + fname + "' - skipped", e);
+        }
+    }
+
+    private void instrumentModulesFile(File modulePath, final File destinationPath){
+
+        try {
+            Utils.addToClasspath(modulePath.getParentFile().getParentFile());
+            FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+            final Path path = fs.getPath("/modules/");
+
+            Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    if(!attrs.isDirectory() && isClassFile(file.getFileName().toString())){
+                        OverriddenClassWriter.addClassInfo(Files.newInputStream(file));
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+
+            Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    if(!attrs.isDirectory() && isClassFile(file.getFileName().toString())){
+                        processClassFileInModules(file, destinationPath);
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "Modules instrumentaion failed", e);
+        }
+
+    }
+
     /**
      * <p> Treats given byte array as a class data and instruments the class.
      * Any Exception thrown from this metod will be treated as error during
--- a/src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java	Tue Jul 11 16:16:12 2017 -0700
@@ -77,6 +77,10 @@
         findAlreadyInstrumentedAndSetID();
     }
 
+    public DataRoot getRoot(){
+        return root;
+    }
+
     /**
      * Default constructor for Instr and TemplGen. Uses specified template as
      * output file.
@@ -283,8 +287,8 @@
                 fullname = fullname.substring(0, fullname.indexOf("$"));
             }
             Class cls = Class.forName(fullname.replaceAll("/","."));
-            java.lang.reflect.Method getModuleMethod = Class.class.getDeclaredMethod("getModule", null);
-            Object module = getModuleMethod.invoke(cls, null);
+            java.lang.reflect.Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object module = getModuleMethod.invoke(cls);
             result = module.toString();
 
         }catch(Throwable ignore){
@@ -570,6 +574,61 @@
 
     }
 
+    public static void fillIntrMethodsIDs(DataRoot root){
+        try {
+            for (DataPackage pack : root.getPackages()) {
+                for (DataClass clazz : pack.getClasses()) {
+                    for (DataMethod meth : clazz.getMethods()) {
+                        if (meth.access(meth.getAccess()).matches(".*abstract.*")
+                                || meth.access(meth.getAccess()).matches(".*native.*")) {
+                            int id = 0;
+                            if (meth instanceof DataMethodInvoked) {
+                                id = ((DataMethodInvoked) meth).getId();
+                            } else if (meth instanceof DataMethodEntryOnly) {
+                                id = ((DataMethodEntryOnly) meth).getId();
+                            } else {
+                                DataMethodWithBlocks mb = (DataMethodWithBlocks) meth;
+                                for (BasicBlock bb : mb.getBasicBlocks()) {
+                                    for (DataBlock db : bb.blocks()) {
+                                        id = db.getId();
+                                        break;
+                                    }
+                                    break;
+                                }
+                            }
+
+                            String className = pack.getName().equals("") ? clazz.getName()
+                                    : pack.getName().replace('.', '/') + "/" + clazz.getName();
+                            StaticInvokeMethodAdapter.addID(
+                                    className, meth.getName(), meth.getVmSignature(), id);
+
+                            if (meth.getAnnotations()!= null ) {
+                                for (String annotation : meth.getAnnotations()) {
+                                    if (annotation != null && annotation.contains("PolymorphicSignature")) {
+                                        StaticInvokeMethodAdapter.addID(
+                                                className, meth.getName(), "", id);
+                                        break;
+                                    }
+                                }
+                            }
+
+                        }
+                    }
+                    for (DataField fld : clazz.getFields()) {
+                        int id = fld.getId();
+                        String className = pack.getName().equals("") ? clazz.getName()
+                                : pack.getName().replace('.', '/') + "/" + clazz.getName();
+                        StaticInvokeMethodAdapter.addID(
+                                className, fld.getName(), fld.getVmSig(), id);
+                    }
+                }
+            }
+
+        } catch (Throwable t) {
+            throw new Error(t);
+        }
+    }
+
     public void saveData(InstrumentationOptions.MERGE merge) {
         FileSaver fileSaver = FileSaver.getFileSaver(root, outputFile, outputFile, merge, true, false);
         fileSaver.saveResults();
--- a/src/classes/com/sun/tdk/jcov/instrument/ClassMorph2.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/ClassMorph2.java	Tue Jul 11 16:16:12 2017 -0700
@@ -42,43 +42,7 @@
         try {
 
             DataRoot root = Reader.readXML(template, true, null);
-            for (DataPackage pack : root.getPackages()) {
-                for (DataClass clazz : pack.getClasses()) {
-                    for (DataMethod meth : clazz.getMethods()) {
-                        if (meth.access(meth.getAccess()).matches(".*abstract.*")
-                                || meth.access(meth.getAccess()).matches(".*native.*")) {
-                            int id = 0;
-                            if (meth instanceof DataMethodInvoked) {
-                                id = ((DataMethodInvoked) meth).getId();
-                            } else if (meth instanceof DataMethodEntryOnly) {
-                                id = ((DataMethodEntryOnly) meth).getId();
-                            } else {
-                                DataMethodWithBlocks mb = (DataMethodWithBlocks) meth;
-                                for (BasicBlock bb : mb.getBasicBlocks()) {
-                                    for (DataBlock db : bb.blocks()) {
-                                        id = db.getId();
-                                        break;
-                                    }
-                                    break;
-                                }
-                            }
-
-                            String className = pack.getName().equals("") ? clazz.getName()
-                                    : pack.getName().replace('.', '/') + "/" + clazz.getName();
-                            StaticInvokeMethodAdapter.addID(
-                                    className, meth.getName(), meth.getVmSignature(), id);
-
-                        }
-                    }
-                    for (DataField fld : clazz.getFields()) {
-                        int id = fld.getId();
-                        String className = pack.getName().equals("") ? clazz.getName()
-                                : pack.getName().replace('.', '/') + "/" + clazz.getName();
-                        StaticInvokeMethodAdapter.addID(
-                                className, fld.getName(), fld.getVmSig(), id);
-                    }
-                }
-            }
+            ClassMorph.fillIntrMethodsIDs(root);
 
         } catch (Throwable t) {
             throw new Error(t);
--- a/src/classes/com/sun/tdk/jcov/instrument/ConcealedPackagesAttribute.java	Thu Mar 16 14:03:52 2017 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.sun.tdk.jcov.instrument;
-
-import org.objectweb.asm.*;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- *
- * @author Alexey Fedorchenko
- */
-public class ConcealedPackagesAttribute extends Attribute {
-    private final Set<String> packages;
-
-    ConcealedPackagesAttribute(Set<String> packages) {
-        super("ConcealedPackages");
-        this.packages = packages;
-    }
-
-    public ConcealedPackagesAttribute() {
-        this(null);
-    }
-
-    @Override
-    protected Attribute read(ClassReader cr,
-                             int off,
-                             int len,
-                             char[] buf,
-                             int codeOff,
-                             Label[] labels)
-    {
-        // package count
-        int package_count = cr.readUnsignedShort(off);
-        off += 2;
-
-        // packages
-        Set<String> packages = new HashSet<String>();
-        for (int i=0; i<package_count; i++) {
-            String pkg = cr.readUTF8(off, buf).replace('/', '.');
-            packages.add(pkg);
-            off += 2;
-        }
-
-        return new ConcealedPackagesAttribute(packages);
-    }
-
-    @Override
-    protected ByteVector write(ClassWriter cw,
-                               byte[] code,
-                               int len,
-                               int maxStack,
-                               int maxLocals)
-    {
-        ByteVector attr = new ByteVector();
-
-        // package_count
-        attr.putShort(0);
-
-        // packages
-        /*for (String pak : packages){
-            String rp = pak.replace('.', '/');
-            attr.putShort(cw.newUTF8(""));
-        }*/
-
-        return attr;
-    }
-
-}
--- a/src/classes/com/sun/tdk/jcov/instrument/DeferringMethodClassAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/DeferringMethodClassAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -44,7 +44,7 @@
     private final InstrumentationParams params;
 
     public DeferringMethodClassAdapter(final ClassVisitor cv, DataClass k, InstrumentationParams params) {
-        super(ASM4, cv);
+        super(ASM6, cv);
         this.k = k;
         this.params = params;
     }
@@ -168,7 +168,7 @@
         MethodVisitor mv = visitMethodCoverage(access, name, desc, signature, exceptions);
 
         if ("<clinit>".equals(name) && !params.isDynamicCollect() && (k.getPackageName().startsWith("java/lang/"))) {
-            mv = new MethodVisitor(Opcodes.ASM4, mv) {
+            mv = new MethodVisitor(Opcodes.ASM6, mv) {
                 public void visitCode() {
                     mv.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/Collect", "init", "()V");
                     super.visitCode();
@@ -204,7 +204,7 @@
         if (params.isDataSaveFilterAccept(k.getFullname(), name, false)) {
             mv = new SavePointsMethodAdapter(mv, false);
         }
-        mv = new MethodVisitor(Opcodes.ASM4, mv) {
+        mv = new MethodVisitor(Opcodes.ASM6, mv) {
             @Override
             public void visitLocalVariable(String arg0, String arg1, String arg2, Label arg3, Label arg4, int arg5) {
                 //super.visitLocalVariable(arg0, arg1, arg2, arg3, arg4, arg5);
--- a/src/classes/com/sun/tdk/jcov/instrument/EntryCodeMethodAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/EntryCodeMethodAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -43,7 +43,7 @@
     EntryCodeMethodAdapter(final MethodVisitor mv,
             final DataMethodEntryOnly method,
             final InstrumentationParams params) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM6, mv);
         this.method = method;
         this.params = params;
     }
--- a/src/classes/com/sun/tdk/jcov/instrument/FieldAnnotationVisitor.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/FieldAnnotationVisitor.java	Tue Jul 11 16:16:12 2017 -0700
@@ -40,7 +40,7 @@
     final FieldVisitor fv;
 
     FieldAnnotationVisitor(final FieldVisitor fv, final DataField field) {
-        super(Opcodes.ASM4, fv);
+        super(Opcodes.ASM6, fv);
         this.fv = fv;
         this.field = field;
     }
--- a/src/classes/com/sun/tdk/jcov/instrument/ForkingMethodAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/ForkingMethodAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -44,7 +44,7 @@
         final AnnotationVisitor av2;
 
         DuplicatingAnnotationAdapter(final AnnotationVisitor av1, final AnnotationVisitor av2) {
-            super(Opcodes.ASM4);
+            super(Opcodes.ASM6);
             this.av1 = av1;
             this.av2 = av2;
         }
@@ -88,7 +88,7 @@
      * @param mv the code visitor to which this adapter must delegate calls.
      */
     public ForkingMethodAdapter(final MethodVisitor mv1, final MethodVisitor mv2) {
-        super(Opcodes.ASM4);
+        super(Opcodes.ASM6);
         this.mv1 = mv1;
         this.mv2 = mv2;
     }
--- a/src/classes/com/sun/tdk/jcov/instrument/HashesAttribute.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/HashesAttribute.java	Tue Jul 11 16:16:12 2017 -0700
@@ -36,11 +36,11 @@
  */
 public class HashesAttribute extends Attribute {
     private String algorithm;
-    private Map<String, String> nameToHash;
+    private Map<String, byte[]> nameToHash;
 
 
-    HashesAttribute(String algorithm, Map<String, String> nameToHash) {
-        super("Hashes");
+    HashesAttribute(String algorithm, Map<String, byte[]> nameToHash) {
+        super("ModuleHashes");
         this.algorithm = algorithm;
         this.nameToHash = nameToHash;
     }
@@ -63,12 +63,20 @@
         int hash_count = cr.readUnsignedShort(off);
         off += 2;
 
-        Map<String, String> map = new HashMap<String, String>();
+        Map<String, byte[]> map = new HashMap<String, byte[]>();
         for (int i=0; i<hash_count; i++) {
-            String dn = cr.readUTF8(off, buf);
-            String hash = cr.readUTF8(off, buf);
-            map.put(dn, hash);
+            String mn = cr.readModule(off, buf);
             off += 2;
+
+            int hash_length = cr.readUnsignedShort(off);
+            off += 2;
+            byte[] hash = new byte[hash_length];
+            for (int j = 0; j < hash_length; j++) {
+                hash[j] = (byte) (0xff & cr.readByte(off + j));
+            }
+            off += hash_length;
+
+            map.put(mn, hash);
         }
 
         return new HashesAttribute(algorithm, map);
@@ -85,14 +93,7 @@
 
         int index = cw.newUTF8(algorithm);
         attr.putShort(index);
-
-        Set<String> names = nameToHash.keySet();
-        attr.putShort(names.size());
-
-        for (String dn : names) {
-            attr.putShort(cw.newUTF8(""));
-            attr.putShort(cw.newUTF8(""));
-        }
+        attr.putShort(0);
 
         return attr;
     }
--- a/src/classes/com/sun/tdk/jcov/instrument/InstrumentationOptions.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InstrumentationOptions.java	Tue Jul 11 16:16:12 2017 -0700
@@ -144,10 +144,18 @@
             "Work similar savebegin, however save before last instruction in the method is executed (throw or return).\n"
             + "This method doesn't work if exception was thrown not directly in this method.");
     public final static OptionDescr DSC_INNERINVOCATION =
-            new OptionDescr("innerinvocation", "", new String[][]{
+            new OptionDescr("innerinvocation", "Inner invocations", new String[][]{
                 {"on", "count inner invocations in the product"},
                 {"off", "count only invocations outside the instrumented product"}
             }, "Allows to filter inner invocations in the instrumented product", "on");
+    public final static OptionDescr DSC_INNER_INCLUDE =
+            new OptionDescr("inner_include", new String[]{"ii"}, "", OptionDescr.VAL_MULTI,
+            "Specify included classes by regular expression for adding inner invocations instrumentaion\n" +
+            "(only for innerinvocation off)");
+    public final static OptionDescr DSC_INNER_EXCLUDE =
+            new OptionDescr("inner_exclude", new String[]{"ie"}, "", OptionDescr.VAL_MULTI,
+            "Specify excluded classes by regular expression, no inner invocations instrumentaion will be\n" +
+            "added to the specified classes (only for innerinvocation off)");
 
     public static enum ABSTRACTMODE {
 
@@ -247,6 +255,29 @@
         return includeSet.toArray(new String[includeSet.size()]);
     }
 
+    public static String[] handleInnerInclude(EnvHandler opts) throws EnvHandlingException {
+        Set<String> includeSet = new TreeSet<String>();
+        String[] s;
+        if (opts.isSet(InstrumentationOptions.DSC_INNER_INCLUDE)) {
+            s = opts.getValues(InstrumentationOptions.DSC_INNER_INCLUDE);
+            if (s != null) {
+                includeSet.addAll(Arrays.asList(s));
+            }
+        }
+
+        return includeSet.toArray(new String[includeSet.size()]);
+    }
+
+    public static String[] handleInnerExclude(EnvHandler opts) throws EnvHandlingException {
+        Set<String> excludeSet = new TreeSet<String>();
+        String[] s = opts.getValues(InstrumentationOptions.DSC_INNER_EXCLUDE);
+        if (s != null) {
+            excludeSet.addAll(Arrays.asList(s));
+        }
+
+        return excludeSet.toArray(new String[excludeSet.size()]);
+    }
+
     public static String[] handleExclude(EnvHandler opts) throws EnvHandlingException {
         Set<String> excludeSet = new TreeSet<String>();
         String[] s = opts.getValues(InstrumentationOptions.DSC_EXCLUDE);
--- a/src/classes/com/sun/tdk/jcov/instrument/InstrumentationParams.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InstrumentationParams.java	Tue Jul 11 16:16:12 2017 -0700
@@ -57,6 +57,8 @@
     private String[] excludes;
     private String[] callerIncludes;
     private String[] callerExcludes;
+    private String[] inner_includes;
+    private String[] inner_excludes;
     private InstrumentationOptions.InstrumentationMode mode;
     private String saveBegin;
     private String saveEnd;
@@ -64,6 +66,7 @@
     private String[] savesEnd;
     private Pattern[] alls;
     private Pattern[] all_modules;
+    private Pattern[] inner_alls;
     private boolean innerInvocations = true;
 
     public InstrumentationParams(boolean dynamicCollect, boolean instrumentNative, boolean instrumentFields, boolean detectInternal, ABSTRACTMODE instrumentAbstract, String[] includes, String[] excludes, String[] callerIncludes, String[] callerExcludes, InstrumentationMode mode) {
@@ -139,6 +142,7 @@
         this.callerExclude = InstrumentationOptions.concatRegexps(callerExcludes);
         this.alls = Utils.concatFilters(includes, excludes);
         this.all_modules = Utils.concatModuleFilters(m_includes, m_excludes);
+        this.inner_alls = Utils.concatFilters(inner_includes, inner_excludes);
     }
 
     public boolean isDetectInternal() {
@@ -192,6 +196,10 @@
         return Utils.accept(alls, null, "/" + classname, null);
     }
 
+    public boolean isInnerInstrumentationIncludes(String classname) {
+        return Utils.accept(inner_alls, null, "/" + classname, null);
+    }
+
     public boolean isModuleIncluded(String modulename) {
         return Utils.accept(all_modules, null, modulename, null);
     }
@@ -294,6 +302,18 @@
         this.alls = Utils.concatFilters(includes, excludes);
     }
 
+    public InstrumentationParams setInnerExcludes(String[] excludes) {
+        this.inner_excludes = excludes;
+        this.inner_alls = Utils.concatFilters(inner_includes, excludes);
+        return this;
+    }
+
+    public InstrumentationParams setInnerIncludes(String[] includes) {
+        this.inner_includes = includes;
+        this.inner_alls = Utils.concatFilters(includes, inner_excludes);
+        return this;
+    }
+
     public InstrumentationParams setInstrumentSynthetic(boolean synth) {
         instrumentSynthetic = synth;
         return this;
--- a/src/classes/com/sun/tdk/jcov/instrument/InstrumentedAttributeClassAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InstrumentedAttributeClassAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -45,7 +45,7 @@
     }
 
     public InstrumentedAttributeClassAdapter(final ClassVisitor cv) {
-        super(Opcodes.ASM4, cv);
+        super(Opcodes.ASM6, cv);
     }
 
     public void visitAttribute(Attribute attr) {
--- a/src/classes/com/sun/tdk/jcov/instrument/InvokeClassAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InvokeClassAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -38,7 +38,7 @@
     private final InstrumentationParams params;
 
     public InvokeClassAdapter(final ClassVisitor cv, final InstrumentationParams params) {
-        super(Opcodes.ASM4, cv);
+        super(Opcodes.ASM6, cv);
         this.params = params;
     }
 
--- a/src/classes/com/sun/tdk/jcov/instrument/InvokeMethodAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InvokeMethodAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -70,7 +70,7 @@
             Collections.synchronizedMap(new HashMap<String, Integer>());
 
     public InvokeMethodAdapter(MethodVisitor mv, String className, final InstrumentationParams params) {
-        super(ASM4, mv);
+        super(ASM6, mv);
         this.className = className;
         this.params = params;
     }
@@ -89,7 +89,7 @@
     }
 
     @Override
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
         if (params.isCallerFilterOn()
                 && params.isCallerFilterAccept(className)) {
 
@@ -99,7 +99,7 @@
             } else {
                 int id = (name + desc).hashCode();
                 super.visitLdcInsn(id);
-                super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V");
+                super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V", false);
             }
         }
 
@@ -108,9 +108,9 @@
                 && params.isIncluded(owner)
                 && params.isCallerFilterAccept(className)) {
             super.visitLdcInsn(getInvokeID(owner, name, desc));
-            super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "invokeHit", "(I)V");
+            super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "invokeHit", "(I)V", false);
         }
-        super.visitMethodInsn(opcode, owner, name, desc);
+        super.visitMethodInsn(opcode, owner, name, desc, itf);
     }
 
     private enum ReflPair {
--- a/src/classes/com/sun/tdk/jcov/instrument/MethodAnnotationAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/MethodAnnotationAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -45,7 +45,7 @@
 
     MethodAnnotationAdapter(final MethodVisitor mv,
             final DataMethod method) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM6, mv);
         this.meth = method;
     }
 }
--- a/src/classes/com/sun/tdk/jcov/instrument/ModuleAttribute.java	Thu Mar 16 14:03:52 2017 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.sun.tdk.jcov.instrument;
-
-import java.util.*;
-
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ByteVector;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-
-/**
- *
- * @author Alexey Fedorchenko
- */
-public class ModuleAttribute extends Attribute{
-    private Set<String> serviceDependences;
-    private Set<ModuleExport> exports;
-    private Map<String, Set<String>> services;
-
-    public ModuleAttribute() {
-        super("Module");
-    }
-
-    @Override
-    protected Attribute read(ClassReader cr,
-                             int off,
-                             int len,
-                             char[] buf,
-                             int codeOff,
-                             Label[] labels) {
-        ModuleAttribute attr = new ModuleAttribute();
-
-
-        // requires_count and requires[requires_count]
-        int requires_count = cr.readUnsignedShort(off);
-        off += 2;
-        for (int i = 0; i < requires_count; i++) {
-            cr.readUTF8(off, buf);
-            cr.readUnsignedShort(off + 2);
-            off += 4;
-        }
-
-        // exports_count and exports[exports_count]
-        int exports_count = cr.readUnsignedShort(off);
-        off += 2;
-        if (exports_count > 0) {
-            attr.exports = new HashSet<ModuleExport>();
-            for (int i = 0; i < exports_count; i++) {
-                String pkg = cr.readUTF8(off, buf).replace('/', '.');
-                int exports_to_count = cr.readUnsignedShort(off + 2);
-                off += 4;
-
-                if (exports_to_count > 0) {
-                    for (int j = 0; j < exports_to_count; j++) {
-                        String who = cr.readUTF8(off, buf);
-                        off += 2;
-                        attr.exports.add(new ModuleExport(pkg, who));
-                    }
-                } else {
-                    attr.exports.add(new ModuleExport(pkg));
-                }
-            }
-        }
-
-        // uses_count and uses_index[uses_count]
-        int uses_count = cr.readUnsignedShort(off);
-        off += 2;
-        if (uses_count > 0) {
-            attr.serviceDependences = new HashSet<String>();
-            for (int i = 0; i < uses_count; i++) {
-                String sn = cr.readClass(off, buf).replace('/', '.');
-                attr.serviceDependences.add(sn);
-                off += 2;
-            }
-        }
-
-        // provides_count and provides[provides_count]
-        int provides_count = cr.readUnsignedShort(off);
-        off += 2;
-        if (provides_count > 0) {
-            attr.services = new HashMap<String, Set<String>>();
-            for (int i = 0; i < provides_count; i++) {
-                String sn = cr.readClass(off, buf).replace('/', '.');
-                String cn = cr.readClass(off + 2, buf).replace('/', '.');
-
-                if (attr.services.get(sn) == null){
-                    attr.services.put(sn, new HashSet<String>());
-                }
-                attr.services.get(sn).add(cn);
-
-                off += 4;
-            }
-        }
-
-        return attr;
-    }
-
-    @Override
-    protected ByteVector write(ClassWriter cw,
-                               byte[] code,
-                               int len,
-                               int maxStack,
-                               int maxLocals) {
-        ByteVector attr = new ByteVector();
-
-        attr.putShort(0);
-
-        if (exports == null) {
-            attr.putShort(0);
-        } else {
-            exports.add(new ModuleExport("com.sun.tdk.jcov.runtime"));
-            // group by exported package
-            Map<String, Set<String>> map = new HashMap<String, Set<String>>();
-            for (ModuleExport export : exports) {
-                String pkg = export.pkg();
-                String permit = export.permit();
-                if (permit == null) {
-
-                    if (map.get(pkg) == null){
-                        map.put(pkg, new HashSet<String>());
-                    }
-
-                } else {
-                    if (map.get(pkg) == null){
-                        map.put(pkg, new HashSet<String>());
-                    }
-                    map.get(pkg).add(permit);
-                }
-            }
-            attr.putShort(map.size());
-
-            for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
-                String pkg = entry.getKey().replace('.', '/');
-                int index = cw.newUTF8(pkg);
-                attr.putShort(index);
-
-                Set<String> permits = entry.getValue();
-                attr.putShort(permits.size());
-                for (String permit : permits) {
-                    index = cw.newUTF8(permit);
-                    attr.putShort(index);
-                }
-            }
-        }
-
-        // uses_count and uses_index[uses_count]
-        if (serviceDependences == null) {
-            attr.putShort(0);
-        } else {
-            attr.putShort(serviceDependences.size());
-            for (String s : serviceDependences) {
-                String service = s.replace('.', '/');
-                int index = cw.newClass(service);
-                attr.putShort(index);
-            }
-        }
-
-        // provides_count and provides[provides_count]
-        if (services == null) {
-            attr.putShort(0);
-        } else {
-            int count = 0;
-            for (Set<String> value : services.values()){
-                count += value.size();
-            }
-            attr.putShort(count);
-            for (Map.Entry<String, Set<String>> entry : services.entrySet()) {
-                String service = entry.getKey().replace('.', '/');
-                int index = cw.newClass(service);
-                for (String provider : entry.getValue()) {
-                    attr.putShort(index);
-                    attr.putShort(cw.newClass(provider.replace('.', '/')));
-                }
-            }
-        }
-
-        return attr;
-    }
-
-    class ModuleExport {
-
-        private final String pkg;
-        private final String permit;
-
-        public ModuleExport(String pkg, String who) {
-            this.pkg = Objects.requireNonNull(pkg);
-            this.permit = who;
-        }
-
-        public ModuleExport(String pkg) {
-            this(pkg, null);
-        }
-
-        public String pkg() {
-            return pkg;
-        }
-
-        public String permit() {
-            return permit;
-        }
-
-        public int hashCode() {
-            return Objects.hash(pkg, permit);
-        }
-
-        public boolean equals(Object obj) {
-            if (!(obj instanceof ModuleExport))
-                return false;
-            ModuleExport other = (ModuleExport)obj;
-            return Objects.equals(this.pkg, other.pkg) &&
-                    Objects.equals(this.permit, other.permit);
-        }
-
-    }
-}
-
--- a/src/classes/com/sun/tdk/jcov/instrument/OffsetRecordingMethodAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/OffsetRecordingMethodAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -45,7 +45,7 @@
 
     public OffsetRecordingMethodAdapter(final MethodVisitor mv,
             final DataMethodWithBlocks method) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM6, mv);
         this.currentInstructionIndex = 0;
         this.bcis = new int[60];
         this.method = method;
@@ -99,15 +99,6 @@
         super.visitFieldInsn(opcode, owner, name, desc);
     }
 
-    public void visitMethodInsn(
-            final int opcode,
-            final String owner,
-            final String name,
-            final String desc) {
-        recordInstructionOffset();
-        super.visitMethodInsn(opcode, owner, name, desc);
-    }
-
     public void visitJumpInsn(final int opcode, final Label label) {
         recordInstructionOffset();
         super.visitJumpInsn(opcode, label);
@@ -163,4 +154,11 @@
         recordInstructionOffset();
         super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
     }
+
+    @Override
+    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
+        recordInstructionOffset();
+        super.visitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
 }
--- a/src/classes/com/sun/tdk/jcov/instrument/OverriddenClassWriter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/OverriddenClassWriter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -31,6 +31,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import org.objectweb.asm.ClassReader;
@@ -101,6 +102,21 @@
         class_interfaces.clear();
     }
 
+    public static void addClassInfo(InputStream in){
+        try {
+            ClassReader cr = new OffsetLabelingClassReader(in);
+            if (class_superclass.get(cr.getClassName()) == null) {
+                class_superclass.put(cr.getClassName(), cr.getSuperName());
+            }
+            if (class_interfaces.get(cr.getClassName()) == null) {
+                class_interfaces.put(cr.getClassName(), Arrays.asList(cr.getInterfaces()));
+            }
+        }
+        catch (IOException ioe){
+            System.err.println("Failed to read class. Reason: " + ioe.getMessage());
+        }
+    }
+
     /**
      * Analog of Class.isAssignableFrom(class2)
      *
--- a/src/classes/com/sun/tdk/jcov/instrument/SavePointsMethodAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/SavePointsMethodAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -41,7 +41,7 @@
     private final boolean isBegin;
 
     public SavePointsMethodAdapter(final MethodVisitor mv, boolean isBegin) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM6, mv);
         this.isBegin = isBegin;
     }
 
--- a/src/classes/com/sun/tdk/jcov/instrument/StaticInvokeMethodAdapter.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/StaticInvokeMethodAdapter.java	Tue Jul 11 16:16:12 2017 -0700
@@ -58,12 +58,18 @@
         if (id != null) {
             return id;
         }
+
+        sig = owner + "." + name;
+        id = map.get(sig);
+        if (id != null) {
+            return id;
+        }
         return -1;
     }
     public static final Map<String, Integer> map = new HashMap<String, Integer>();
 
     public StaticInvokeMethodAdapter(MethodVisitor mv, String className, String methName, int access, final InstrumentationParams params) {
-        super(Opcodes.ASM4, mv);
+        super(Opcodes.ASM6, mv);
         this.className = className;
         this.params = params;
         this.methName = methName;
@@ -86,16 +92,16 @@
     }
 
     @Override
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-        if ((opcode == INVOKEVIRTUAL || opcode == INVOKEINTERFACE) && params.isInstrumentAbstract()
-                && params.isIncluded(owner)) {
+    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
 
+        if ((params.isInstrumentAbstract() || params.isInstrumentNative()) &&
+                params.isIncluded(owner) || params.isCallerFilterAccept(owner)) {
             if (getInvokeID(owner, name, desc) != -1) {
                 int id = getInvokeID(owner, name, desc);
                 InsnList il = new InsnList();
                 il.add(new LdcInsnNode(id));
                 il.add(new MethodInsnNode(INVOKESTATIC,
-                        "com/sun/tdk/jcov/runtime/Collect", "hit", "(I)V"));
+                        "com/sun/tdk/jcov/runtime/Collect", "hit", "(I)V", false));
                 il.accept(this);
             }
         }
@@ -104,21 +110,20 @@
 
             int id = (name + desc).hashCode();
             super.visitLdcInsn(id);
-            super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V");
+            super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V", false);
 
         }
 
         if (params.isInnerInvacationsOff() && Utils.isAdvanceStaticInstrAllowed(className, name)) {
-            if (!owner.equals("java/lang/Object")) {
-
+            if (!owner.equals("java/lang/Object") && params.isInnerInstrumentationIncludes(className)) {
                 int id = -1;
                 super.visitLdcInsn(id);
-                super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V");
+                super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V", false);
 
             }
         }
 
-        super.visitMethodInsn(opcode, owner, name, desc);
+        super.visitMethodInsn(opcode, owner, name, desc, itf);
 
     }
 
--- a/src/classes/com/sun/tdk/jcov/processing/CombinerDataProcessor.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/processing/CombinerDataProcessor.java	Tue Jul 11 16:16:12 2017 -0700
@@ -104,6 +104,9 @@
                     String prefix = createPrefix(clzName, mainClassName);
                     for (DataMethod m : c.getMethods()) {
                         int newAccess = isPublic ? m.getAccess() : makePrivate(m.getAccess());
+                        if ((c.getAccess() & Opcodes.ACC_SYNTHETIC) != 0 && (m.getAccess() & Opcodes.ACC_SYNTHETIC) == 0){
+                            newAccess = m.getAccess() | Opcodes.ACC_SYNTHETIC;
+                        }
 
                         DataMethod nm = m.clone(newClass, newAccess, prefix + m.getName());
                         // for -type=method methods exist witout blocks and branches
--- a/src/classes/com/sun/tdk/jcov/report/ClassCoverage.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/ClassCoverage.java	Tue Jul 11 16:16:12 2017 -0700
@@ -125,6 +125,10 @@
             if (method.getName() != null && method.getName().matches("\\$\\d.*")) {
                 methodCoverage.setInAnonymClass(true);
             }
+            if ((method.getAccess() & Opcodes.ACC_SYNTHETIC) != 0 && method.getName().startsWith("lambda$")){
+                methodCoverage.setLambdaMethod(true);
+            }
+
             methods.add(methodCoverage);
             lineCoverage.processLineCoverage(methodCoverage.getLineCoverage());
         }
@@ -400,6 +404,7 @@
     public CoverageData getData(DataType column, int testNumber) {
         switch (column) {
             case CLASS:
+                boolean allMethodsInANC = true;
                 for (MethodCoverage method : methods) {
                     if (method.count > 0 && (testNumber < 0 || method.isCoveredByTest(testNumber))) {
                         if (isInAnc) {
@@ -407,8 +412,11 @@
                         }
                         return new CoverageData(1, 0, 1);
                     }
+                    if (method.count <= 0 && !method.isMethodInAnc()){
+                        allMethodsInANC = false;
+                    }
                 }
-                if (isInAnc) {
+                if (isInAnc || (allMethodsInANC && methods.size() > 0)) {
                     return new CoverageData(0, 1, 1);
                 }
                 return new CoverageData(0, 0, 1);
@@ -495,6 +503,14 @@
             if (f.exists()) {
                 return f.getAbsolutePath();
             }
+            else{
+                if (clz.getModuleName() != null && source_paths[i].contains("#module")){
+                    f = new File(source_paths[i].replaceAll("\\#module",clz.getModuleName()) + source_name);
+                    if (f.exists()){
+                        return f.getAbsolutePath();
+                    }
+                }
+            }
         }
         return clz.getSource(); // not found
     }
--- a/src/classes/com/sun/tdk/jcov/report/DefaultReportGeneratorSPI.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/DefaultReportGeneratorSPI.java	Tue Jul 11 16:16:12 2017 -0700
@@ -44,6 +44,7 @@
     protected boolean showBlocks = true;
     protected boolean showBranches = true;
     protected boolean showLines = true;
+    protected boolean showOverviewColorBars = false;
     protected boolean generateShortFormat;
     protected boolean showFields;
 
@@ -67,6 +68,7 @@
             html.setShowBlocks(showBlocks);
             html.setShowBranches(showBranches);
             html.setShowLines(showLines);
+            html.setShowOverviewColorBars(showOverviewColorBars);
             return html;
         }
 
@@ -80,7 +82,8 @@
                     DSC_NO_LINE,
                     DSC_NO_METHOD,
                     DSC_NO_FIELD,
-                    DSC_SHORT,});
+                    DSC_SHORT,
+                    DSC_OVERVIEW_COLORBARS});
     }
 
     public int handleEnv(EnvHandler opts) throws EnvHandlingException {
@@ -90,6 +93,7 @@
         showBranches = !opts.isSet(DSC_NO_BRANCH);
         showLines = !opts.isSet(DSC_NO_LINE);
         generateShortFormat = opts.isSet(DSC_SHORT);
+        showOverviewColorBars = opts.isSet(DSC_OVERVIEW_COLORBARS);
 
         return 0;
     }
@@ -141,4 +145,6 @@
             new OptionDescr("noblock", "Additional filtering", "Hide block coverage from report");
     protected final static OptionDescr DSC_NO_LINE =
             new OptionDescr("noline", "Additional filtering", "Hide line coverage from report");
+    protected final static OptionDescr DSC_OVERVIEW_COLORBARS =
+            new OptionDescr("addoverviewbars", "Additional reporting", "Adds colorful bars to the overview frames.");
 }
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/report/MethodCoverage.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/MethodCoverage.java	Tue Jul 11 16:16:12 2017 -0700
@@ -34,6 +34,7 @@
 import com.sun.tdk.jcov.instrument.DataBlock;
 import com.sun.tdk.jcov.instrument.DataMethod;
 import com.sun.tdk.jcov.util.Utils;
+import org.objectweb.asm.Opcodes;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
@@ -56,6 +57,7 @@
     private LineCoverage lineCoverage = new LineCoverage();
     private List<ItemCoverage> items = new ArrayList<ItemCoverage>();
     private boolean inAnonymClass = false;
+    private boolean lambdaMethod = false;
     private boolean anonymon = false;
     private DataType[] supportedColumns = {METHOD, BLOCK, BRANCH, LINE};
     private boolean isInAnc = false;
@@ -122,13 +124,20 @@
         }
     }
 
-    private static String isBlockInAnc(DataMethod m, DataBlock b , AncFilter[] filters){
+    private static String isBlockInAnc(DataMethod m, DataBlock b , AncFilter[] filters, List<String> ancBlockReasons){
         if (filters == null){
             return null;
         }
         for (AncFilter filter : filters){
             if (filter.accept(m , b)){
-                return filter.getAncReason();
+                String ancReason = filter.getAncReason();
+                if (ancBlockReasons.size() == 0) {
+                    ancBlockReasons.add("All blocks are filtered:");
+                }
+                if (!ancBlockReasons.contains(ancReason)) {
+                    ancBlockReasons.add(ancReason);
+                }
+                return ancReason;
             }
         }
         return null;
@@ -146,11 +155,20 @@
         return inAnonymClass;
     }
 
+    public void setLambdaMethod(boolean lambdaMethod) {
+        this.lambdaMethod = lambdaMethod;
+    }
+
+    public boolean isLambdaMethod() {
+        return lambdaMethod;
+    }
+
     /**
      * Finds coverage items in terms of legacy jcov (blocks and branches)
      */
      void detectItems(DataMethod m, List<ItemCoverage> list, boolean isInAnc, AncFilter[] ancFilters) {
         Map<DataBlock, ItemCoverage> added = new HashMap<DataBlock, ItemCoverage>();
+        List<String> ancBlockReasons = new ArrayList<String>();
 
         for (DataBlock db : m.getBlocks()) {
             if (db instanceof DataBlockTarget /* db.isNested()*/) {
@@ -164,7 +182,7 @@
                 item = ItemCoverage.createBranchCoverageItem(db.startBCI(), db.endBCI(), db.getCount(), db.getScale());
             }
 
-            String ancReason = isBlockInAnc(m, db, ancFilters);
+            String ancReason = isBlockInAnc(m, db, ancFilters, ancBlockReasons);
             if (isInAnc || ancReason != null){
                 item.setAncInfo(ancInfo != null ? ancInfo : ancReason);
             }
@@ -202,7 +220,7 @@
                 item = ItemCoverage.createBranchCoverageItem(db.startBCI(), db.endBCI(), db.getCount(), db.getScale());
             }
 
-            String ancReason = isBlockInAnc(m, db, ancFilters);
+            String ancReason = isBlockInAnc(m, db, ancFilters, ancBlockReasons);
             if (isInAnc || ancReason != null){
                 item.setAncInfo(ancInfo != null ? ancInfo : ancReason);
             }
@@ -234,7 +252,7 @@
             if (!i.isBlock()) {
                 ItemCoverage i2 = ItemCoverage.createBlockCoverageItem(i.startLine, i.endLine, i.count, db.getScale());
 
-                String ancReason = isBlockInAnc(m, db, ancFilters);
+                String ancReason = isBlockInAnc(m, db, ancFilters, ancBlockReasons);
                 if (isInAnc || ancReason != null){
                     i2.setAncInfo(ancInfo != null ? ancInfo : ancReason);
                 }
@@ -264,6 +282,14 @@
                 }
             }
         }
+
+        if (!isInAnc && ancBlockReasons.size() - 1 == list.size()) {
+            StringBuilder methodAncReason = new StringBuilder();
+            for (String ancBlock : ancBlockReasons) {
+                methodAncReason.append(" ").append(ancBlock);
+            }
+            setAncInfo(methodAncReason.toString());
+        }
     }
 
     public void setAncInfo(String ancInfo){
@@ -271,6 +297,10 @@
         this.ancInfo = ancInfo;
     }
 
+    public boolean isMethodInAnc(){
+        return isInAnc;
+    }
+
     public String getAncInfo(){
         return ancInfo;
     }
@@ -365,6 +395,10 @@
                     return new CoverageData(0, 0, 0);
                 }
 
+                if (name.startsWith("lambda$")){
+                    return new CoverageData(0, 0, 0);
+                }
+
                 if (testNumber > -1) {
                     int c = (count > 0 && isCoveredByTest(testNumber)) ? 1 : 0;
                     if (isInAnc) {
@@ -379,6 +413,9 @@
                 return new CoverageData(c, 0, 1);
             case BLOCK:
             case BRANCH:
+                if (inAnonymClass && !anonymon && (access & Opcodes.ACC_SYNTHETIC) != 0) {
+                    return new CoverageData(0, 0, 0);
+                }
                 CoverageData result = new CoverageData(0, 0, 0);
                 for (ItemCoverage item : items) {
                     if (testNumber < 0 || item.isCoveredByTest(testNumber)) {
--- a/src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java	Tue Jul 11 16:16:12 2017 -0700
@@ -78,6 +78,7 @@
     private boolean showBranches;
     private boolean showBlocks;
     private boolean showMethods;
+    private boolean showOverviewColorBars;
     private static final Logger logger;
     private InstrumentationOptions.InstrumentationMode mode;
 
@@ -124,8 +125,7 @@
         CopyResources.copy(directory);
         generateSourceFiles(directory);
         generateFrameset(directory);
-        generatePackageList(directory);
-        generateClassList(directory);
+
         HashMap<String, ArrayList<ModuleCoverageData>> modules = getModulesCoverage();
         if (modules == null || (modules.size() == 1 && XmlNames.NO_MODULE.equals(modules.keySet().iterator().next()))){
             modules = null;
@@ -134,6 +134,8 @@
         if (modules != null) {
             generateModulesList(directory, modules);
         }
+        generatePackageList(directory, modules);
+        generateClassList(directory);
 
     }
 
@@ -224,7 +226,12 @@
                 + "</title>");
         generateScriptsHeader(pw);
         pw.println("</head>");
-        pw.println("<FRAMESET cols=\"20%,80%\" title=\"Documentation frame\" onclick=\"top.loadFrames()\">");
+        if (showOverviewColorBars) {
+            pw.println("<FRAMESET cols=\"30%,70%\" title=\"Documentation frame\" onclick=\"top.loadFrames()\">");
+        }
+        else{
+            pw.println("<FRAMESET cols=\"20%,80%\" title=\"Documentation frame\" onclick=\"top.loadFrames()\">");
+        }
         pw.println("<FRAMESET rows=\"30%,70%\" title=\"Left frames\" onload=\"top.loadFrames()\">");
         pw
                 .println("<FRAME src=\"overview-frame.html\" name=\"packageListFrame\" title=\"All Packages\">");
@@ -245,7 +252,7 @@
         pw.close();
     }
 
-    private void generatePackageList(File dir) throws IOException {
+    private void generatePackageList(File dir, HashMap<String, ArrayList<ModuleCoverageData>> modules) throws IOException {
         File fsFile = new File(dir, "overview-frame.html");
         logger.log(Level.INFO, "generatePackageList:{0}", fsFile.getAbsolutePath());
         PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
@@ -269,6 +276,27 @@
         pw.println("</tr>");
         pw.println("</table>");
         pw.println("<p>");
+
+        if (modules != null) {
+            pw.println("<table>");
+            pw.println("<tr>");
+            pw.println("<td nowrap=\"nowrap\"><span class=\"title2\">All modules</span></td>");
+            pw.println("</tr>");
+            pw.println("<tr>");
+            pw.println("<td nowrap=\"nowrap\">");
+            List<String> modulesList = new ArrayList<String>(modules.keySet());
+            Collections.sort(modulesList);
+            for (String module : modulesList){
+                pw.println("<a href=\"" + module + "/module-summary.html"+ "\" target=\"classFrame\""
+                        + " onClick=\"parent.frames[1].location.href='"
+                        + "allclasses-frame.html" + "';\">"
+                        + module+ "</a><br>");
+
+            }
+            pw.println("</tr>");
+            pw.println("</table>");
+        }
+
         pw.println("<table>");
         pw.println("<tr>");
         pw.println("<td nowrap=\"nowrap\"><span class=\"title2\">All packages</span></td>");
@@ -280,10 +308,15 @@
             String pkgPath = pkg.getName().replace('.', '/');
             String url = pkgPath + "/package-frame.html";
             logger.log(Level.FINE, "generatePackageList:url:{0}", url);
+
+            String pkgCovData = "";
+            if (showOverviewColorBars) {
+                pkgCovData = generatePercentResult(pkg.getCoverageString(DataType.METHOD, coverage.isAncFiltersSet()), true);
+            }
             pw.println("<a href=\"" + url + "\" target=\"packageFrame\""
                     + " onClick=\"parent.frames[2].location.href='"
                     + pkgPath + "/package-summary.html" + "';\">"
-                    + pkg.getName() + "</a><br>");
+                    + pkgCovData + pkg.getName()+ "</a><br>");
         }
 
         pw.println("</td>");
@@ -366,9 +399,13 @@
                     urlDirectory = ".";
                 }
             }
+            String classCovBar = "";
+            if (showOverviewColorBars) {
+                classCovBar = generatePercentResult(theClass.getCoverageString(DataType.METHOD, coverage.isAncFiltersSet()), true);
+            }
             String classFilename = theClass.getName() + ".html";
             pw.println("<a href=\"" + urlDirectory + "/" + classFilename
-                    + "\" target=\"classFrame\">" + theClass.getName()
+                    + "\" target=\"classFrame\">" +classCovBar + theClass.getName()
                     + "</a><span class=\"text_italic\">&nbsp;" + prc + "</span><br>");
         }
 
@@ -705,7 +742,9 @@
         printColumnHeaders(pw, "");
         pw.println("</tr>");
 
-        for (String module : modules.keySet()) {
+        List<String> modulesList = new ArrayList<String>(modules.keySet());
+        Collections.sort(modulesList);
+        for (String module : modulesList) {
             pw.println("<tr class=\"report\">");
             if (!decorate) {
                 pw.println("<td class=\"reportText\"><a href=\""
@@ -1448,6 +1487,9 @@
                     continue;
                 }
             }
+            if (mcov instanceof MethodCoverage && ((MethodCoverage) mcov).isLambdaMethod()){
+                continue;
+            }
 
             pw.println(" <tr class=\"report\">");
             long c = mcov.getHitCount();
@@ -1659,6 +1701,11 @@
     }
 
     private String generatePercentResult(String percentValue) {
+        return generatePercentResult(percentValue, false);
+    }
+
+
+    private String generatePercentResult(String percentValue, boolean onlyColorBar) {
         String value = percentValue;
         String cov_total = "";
         double anc = 0;
@@ -1687,14 +1734,25 @@
             badNumber = true;
         }
         StringBuilder sb = new StringBuilder();
-        sb.append("<table cellpadding=\"0\" cellspacing=\"0\" align=\"center\">");
-        sb.append("<tr>");
-        // sb.append("<td><span class=\"text\">" + decorate(percentValue)
-        sb.append("<td><span class=\"text\"><b>").append(value.trim()).append("</b>%").append(cov_total.trim()).append("</span></td>");
+        if (onlyColorBar) {
+            sb.append("<table cellpadding=\"0\" cellspacing=\"0\" align=\"left\">");
+        }
+        else{
+            sb.append("<table cellpadding=\"0\" cellspacing=\"0\" align=\"center\">");
+            sb.append("<tr>");
+            sb.append("<td><span class=\"text\"><b>").append(value.trim()).append("</b>%").append(cov_total.trim()).append("</span></td>");
+        }
+
         if (!badNumber) {
-            sb.append("<tr>");
-            sb.append("<td>");
-            sb.append("<table class=\"percentGraph\" cellpadding=\"0\" cellspacing=\"0\">");
+            if (onlyColorBar) {
+                sb.append("<td>");
+                sb.append("<table class=\"percentGraph\" cellpadding=\"0\" cellspacing=\"0\" style=\"padding-right: 5px\">");
+            }
+            else{
+                sb.append("<tr>");
+                sb.append("<td>");
+                sb.append("<table class=\"percentGraph\" cellpadding=\"0\" cellspacing=\"0\">");
+            }
             sb.append("<tr>");
             if (anc > 0) {
                 sb.append("<td class=\"percentCovered\" width=\"").append(dvalue - anc).append("\"></td>");
@@ -1710,9 +1768,13 @@
             sb.append("</tr>");
             sb.append("</table>");
             sb.append("</td>");
+            if (!onlyColorBar) {
+                sb.append("</tr>");
+            }
+        }
+        if (!onlyColorBar) {
             sb.append("</tr>");
         }
-        sb.append("</tr>");
         sb.append("</table>");
         return sb.toString();
     }
@@ -1768,4 +1830,8 @@
     public void setShowLines(boolean showLines) {
         this.showLines = showLines;
     }
+
+    public void setShowOverviewColorBars(boolean showOverviewColorBars){
+        this.showOverviewColorBars = showOverviewColorBars;
+    }
 }
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/report/javap/JavapClass.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/javap/JavapClass.java	Tue Jul 11 16:16:12 2017 -0700
@@ -170,6 +170,9 @@
             className = className.substring(0, className.indexOf('<'));
         }
 
+        if (className.startsWith("class")){
+            className = className.substring(6, className.length());
+        }
     }
 
     private void parsePackageName(String textLine) {
--- a/src/classes/com/sun/tdk/jcov/tools/JCovTool.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/tools/JCovTool.java	Tue Jul 11 16:16:12 2017 -0700
@@ -106,7 +106,8 @@
         "com.sun.tdk.jcov.Filter",
         "com.sun.tdk.jcov.DiffCoverage",
         "com.sun.tdk.jcov.RepGen",
-        "com.sun.tdk.jcov.JCov"
+        "com.sun.tdk.jcov.JCov",
+        "com.sun.tdk.jcov.IssueCoverage"
     };
     public static final List<String> allToolsList = Collections.unmodifiableList(Arrays.asList(allTools));
 
@@ -130,6 +131,11 @@
                 c = Class.forName(str);
                 o = c.newInstance();
                 h = (JCovTool) o;
+            } catch (NoClassDefFoundError cndfe){
+                if ("com.sun.tdk.jcov.IssueCoverage".equals(str)){
+                    System.out.println("IssueCoverage command request jdk9 or javax.tools in classpath");
+                    continue;
+                }
             } catch (Exception ex) {
                 ex.printStackTrace();
                 System.exit(1);
--- a/src/classes/com/sun/tdk/jcov/util/Utils.java	Thu Mar 16 14:03:52 2017 +0300
+++ b/src/classes/com/sun/tdk/jcov/util/Utils.java	Tue Jul 11 16:16:12 2017 -0700
@@ -100,20 +100,19 @@
     public final static int VER14 = 140;
     public final static int VER15 = 150;
     public final static int VER16 = 160;
-    private static int javaVersion = VER11;
+    private static int javaVersion = -1;
 
-    /* determine JVM version */
-    static {
-        String ver = System.getProperty("java.version");
-        javaVersion = (ver.charAt(0) - '0') * 100
-                + (ver.charAt(2) - '0') * 10
-                + (ver.length() > 4 ? (ver.charAt(4) - '0') : 0);
-    }
 
     /**
      * @return JVM version
      */
     public static int getJavaVersion() {
+        if (javaVersion == -1){
+            String ver = System.getProperty("java.version");
+            javaVersion = (ver.charAt(0) - '0') * 100
+                    + (ver.charAt(2) - '0') * 10
+                    + (ver.length() > 4 ? (ver.charAt(4) - '0') : 0);
+        }
         return javaVersion;
     }
 
@@ -519,20 +518,22 @@
     }
 
     public static void addToClasspath(String[] path) {
-        URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
-        Class sysclass = URLClassLoader.class;
+        if (ClassLoader.getSystemClassLoader() instanceof URLClassLoader) {
+            URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+            Class sysclass = URLClassLoader.class;
 
-        try {
-            Method method = sysclass.getDeclaredMethod("addURL", new Class[]{URL.class});
-            method.setAccessible(true);
+            try {
+                Method method = sysclass.getDeclaredMethod("addURL", new Class[]{URL.class});
+                method.setAccessible(true);
 
-            URL[] urls = new URL[path.length];
-            for (int i = 0; i < path.length; i++) {
-                urls[i] = new File(path[i]).toURI().toURL();
-                method.invoke(sysloader, new Object[]{urls[i]});
+                URL[] urls = new URL[path.length];
+                for (int i = 0; i < path.length; i++) {
+                    urls[i] = new File(path[i]).toURI().toURL();
+                    method.invoke(sysloader, new Object[]{urls[i]});
+                }
+            } catch (Throwable t) {
+                t.printStackTrace();
             }
-        } catch (Throwable t) {
-            t.printStackTrace();
         }
     }