changeset 14:4027bcf80b8d

Supporting JDK (9ea, jigsaw), modules reports (static+dynamic process), modules filters, accept not coverage filters.
author afedorch
date Mon, 26 Oct 2015 14:31:30 +0300
parents f73d660552bb
children cc7cda3d6842
files build/release.properties src/classes/com/sun/tdk/jcov/Agent.java src/classes/com/sun/tdk/jcov/Filter.java src/classes/com/sun/tdk/jcov/GrabberManager.java src/classes/com/sun/tdk/jcov/Instr.java src/classes/com/sun/tdk/jcov/JCov.java src/classes/com/sun/tdk/jcov/JREInstr.java src/classes/com/sun/tdk/jcov/RepGen.java src/classes/com/sun/tdk/jcov/TmplGen.java src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java src/classes/com/sun/tdk/jcov/instrument/ConcealedPackagesAttribute.java src/classes/com/sun/tdk/jcov/instrument/DataRoot.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/ModuleAttribute.java src/classes/com/sun/tdk/jcov/instrument/OverriddenClassWriter.java src/classes/com/sun/tdk/jcov/instrument/XmlContext.java src/classes/com/sun/tdk/jcov/instrument/XmlNames.java src/classes/com/sun/tdk/jcov/io/ClassSignatureFilter.java src/classes/com/sun/tdk/jcov/report/AbstractCoverage.java src/classes/com/sun/tdk/jcov/report/AncFilter.java src/classes/com/sun/tdk/jcov/report/ClassCoverage.java src/classes/com/sun/tdk/jcov/report/CoverageData.java src/classes/com/sun/tdk/jcov/report/FieldCoverage.java src/classes/com/sun/tdk/jcov/report/ItemCoverage.java src/classes/com/sun/tdk/jcov/report/LineCoverage.java src/classes/com/sun/tdk/jcov/report/MethodCoverage.java src/classes/com/sun/tdk/jcov/report/PackageCoverage.java src/classes/com/sun/tdk/jcov/report/ProductCoverage.java src/classes/com/sun/tdk/jcov/report/ReportGenerator.java src/classes/com/sun/tdk/jcov/report/SubpackageCoverage.java src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java src/classes/com/sun/tdk/jcov/report/html/resources/style.css src/classes/com/sun/tdk/jcov/report/text/TextReportGenerator.java src/classes/com/sun/tdk/jcov/runtime/Collect.java src/classes/com/sun/tdk/jcov/runtime/JCovSESocketSaver.java src/classes/com/sun/tdk/jcov/runtime/PropertyFinder.java src/classes/com/sun/tdk/jcov/util/Utils.java
diffstat 39 files changed, 1875 insertions(+), 382 deletions(-) [+]
line wrap: on
line diff
--- a/build/release.properties	Mon Apr 06 13:07:41 2015 +0300
+++ b/build/release.properties	Mon Oct 26 14:31:30 2015 +0300
@@ -1,26 +1,26 @@
-# 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.
-
-build.version = 2.0
-build.milestone = os.beta
-build.number = 1
\ No newline at end of file
+# 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.
+
+build.version = 3.0
+build.milestone = os.beta
+build.number = 2
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/Agent.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/Agent.java	Mon Oct 26 14:31:30 2015 +0300
@@ -70,6 +70,8 @@
     private boolean instrumentSynthetic = true;
     private String[] include;
     private String[] exclude;
+    private String[] m_include;
+    private String[] m_exclude;
     private String[] callerInclude;
     private String[] callerExclude;
     private String[] fm;
@@ -174,6 +176,7 @@
                         logger.log(Level.INFO, "Ignore for now {0}", className);
                     } else {
                         logger.log(Level.INFO, "Try to transform {0}", className);
+
                         byte[] newBuff = classMorph.morph(classfileBuffer, loader, flushpath);
                         return newBuff;
                     }
@@ -430,14 +433,17 @@
      */
     public void premainV50(String agentArgs, Instrumentation inst) throws Exception {
         InstrumentationParams params =
-                new InstrumentationParams(classesReload, true, instrumentNative, instrumentField,
+                new InstrumentationParams(true, classesReload, true, instrumentNative, instrumentField,
                 detectInternal, instrumentAbstract ? InstrumentationOptions.ABSTRACTMODE.DIRECT : InstrumentationOptions.ABSTRACTMODE.NONE,
-                include, exclude, callerInclude, callerExclude, mode, saveBegin, saveEnd)
+                include, exclude, callerInclude, callerExclude, m_include, m_exclude, mode, saveBegin, saveEnd)
                 .setInstrumentAnonymous(instrumentAnonymous)
                 .setInstrumentSynthetic(instrumentSynthetic);
 
         params.enable();
         CollectDetect.enterInstrumentationCode();
+
+        updateModules();
+
         Tr transformer = new Tr("RetransformApp", flushPath);
         inst.addTransformer(transformer, true);
         if (params.isInstrumentNative()) {
@@ -504,6 +510,45 @@
         }
         CollectDetect.leaveInstrumentationCode();
         PropertyFinder.addAutoShutdownSave();
+
+    }
+
+    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 allModulesD = layer.getDeclaredMethod("allModuleDescriptors", null);
+            allModulesD.setAccessible(true);
+            Set<Object> mDescriptors = (Set<Object>) allModulesD.invoke(layerObj, null);
+
+            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);
+                updateModule(moduleName, layer, layerObj);
+            }
+        }
+        catch (Exception e){
+        }
+    }
+
+    private void updateModule(String name, Class layer, Object layerObj){
+        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 getModuleMethod = Class.class.getDeclaredMethod("getModule", null);
+            Object jcovModule = getModuleMethod.invoke(Class.forName("com.sun.tdk.jcov.runtime.CollectDetect"), null);
+            java.lang.reflect.Method addReadsMethod = module.getClass().getDeclaredMethod("addReads", Class.forName("java.lang.reflect.Module"));
+            addReadsMethod.invoke(module, jcovModule);
+        }
+        catch (Exception e){
+        }
     }
 
     private void loadFileSaverClasses() throws IOException{
@@ -611,8 +656,12 @@
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE_LIST,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ABSTRACT,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_NATIVE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FIELD,
@@ -652,6 +701,10 @@
 
         include = InstrumentationOptions.handleInclude(opts);
         exclude = InstrumentationOptions.handleExclude(opts);
+
+        m_include = InstrumentationOptions.handleMInclude(opts);
+        m_exclude = InstrumentationOptions.handleMExclude(opts);
+
         fm = InstrumentationOptions.handleFM(opts);
 
         callerInclude = opts.getValues(InstrumentationOptions.DSC_CALLER_INCLUDE);
--- a/src/classes/com/sun/tdk/jcov/Filter.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/Filter.java	Mon Oct 26 14:31:30 2015 +0300
@@ -171,7 +171,10 @@
         String[] include = InstrumentationOptions.handleInclude(opts);
         String[] fm = InstrumentationOptions.handleFM(opts);
 
-        readFilter = new ClassSignatureFilter(include, exclude, fm);
+        String[] m_exclude = InstrumentationOptions.handleMExclude(opts);
+        String[] m_include = InstrumentationOptions.handleMInclude(opts);
+
+        readFilter = new ClassSignatureFilter(include, exclude, m_include, m_exclude, fm);
 
         ArrayList<FilterSpi> filters = opts.getSPIs(FilterSpi.class);
         if (filters == null || filters.isEmpty()) {
--- a/src/classes/com/sun/tdk/jcov/GrabberManager.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/GrabberManager.java	Mon Oct 26 14:31:30 2015 +0300
@@ -54,7 +54,7 @@
 public class GrabberManager extends JCovCMDTool {
 
     private LinkedList<ServerCommand> commands;
-    private int waittime = 5;
+    private int waittime = 30;
     private int stoptimeout = 0;
 
     @Override
@@ -168,7 +168,7 @@
         }
 
         if (opts.isSet(DSC_WAITTIME)) {
-            waittime = Utils.checkedToInt(opts.getValue(DSC_WAITTIME), "time to wait value");
+            waittime = Utils.checkedToInt(opts.getValue(DSC_WAITTIME), "time to wait value in seconds");
         }
         if (opts.isSet(DSC_STOPTIMEOUT)) {
             stoptimeout = Utils.checkedToInt(opts.getValue(DSC_STOPTIMEOUT), "time to wait before stop");
@@ -203,7 +203,7 @@
             new OptionDescr("grabber.props", "", OptionDescr.VAL_SINGLE, "Read server properties from a file. Host should be specified explicitly.");
     final static OptionDescr DSC_WAITTIME =
             new OptionDescr("waittime", new String[]{"time", "t"}, "",
-            OptionDescr.VAL_SINGLE, "Max time in seconds to wait for Grabber startup. Note that Manager will do 4 attempts to connect the Grabber");
+            OptionDescr.VAL_SINGLE, "Max time in seconds to wait for Grabber startup.");
     final static ServerCommand COMM_KILL =
             new ServerCommand("kill", new String[]{"stop"}, "Manage running server",
             OptionDescr.VAL_NONE, "Stop running server saving data and waining for all connections close.", MiscConstants.GRABBER_KILL_COMMAND);
@@ -336,7 +336,7 @@
      */
     public String sendWaitCommand() throws IOException {
         String ret = null;
-        for (int i = 0; i < 4; ++i) {
+        for (int i = 0; i < waittime; ++i) {
             try {
                 ret = recieveCode(COMM_WAIT.getCommandCode());
                 String[] split = ret.split(";");
@@ -345,7 +345,7 @@
                 }
             } catch (IOException e) {
                 try {
-                    Thread.sleep(waittime * 1000);
+                    Thread.sleep(1000);
                 } catch (InterruptedException ex) {
                 }
             }
--- a/src/classes/com/sun/tdk/jcov/Instr.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/Instr.java	Mon Oct 26 14:31:30 2015 +0300
@@ -55,6 +55,8 @@
 
     private String[] include = new String[]{".*"};
     private String[] exclude = new String[]{""};
+    private String[] m_include = new String[]{".*"};
+    private String[] m_exclude = new String[]{""};
     private String[] callerInclude;
     private String[] callerExclude;
     private String[] save_beg = null;
@@ -117,7 +119,7 @@
      * @throws IOException
      * @see
      * #setInstrumenter(com.sun.tdk.jcov.insert.AbstractUniversalInstrumenter)
-     * @see #setDefaultInstrumenter(java.io.File)
+     * @see #setDefaultInstrumenter()
      */
     public void instrumentAll(File[] files, File outDir) throws IOException {
         instrumentAll(files, outDir, null);
@@ -135,7 +137,7 @@
      * @throws IOException
      * @see
      * #setInstrumenter(com.sun.tdk.jcov.insert.AbstractUniversalInstrumenter)
-     * @see #setDefaultInstrumenter(java.io.File)
+     * @see #setDefaultInstrumenter()
      * @see #finishWork()
      */
     public void instrumentFile(File file, File outDir, String includeRTJar) throws IOException {
@@ -155,13 +157,20 @@
      * @throws IOException
      * @see
      * #setInstrumenter(com.sun.tdk.jcov.insert.AbstractUniversalInstrumenter)
-     * @see #setDefaultInstrumenter(java.io.File)
+     * @see #setDefaultInstrumenter()
      * @see #finishWork()
      */
     public void instrumentFile(String file, File outDir, String includeRTJar) throws IOException {
         instrumentFile(new File(file), outDir, includeRTJar);
     }
 
+    public void instrumentFile(String file, File outDir, String includeRTJar, String moduleName) throws IOException {
+        if (morph != null){
+            morph.setCurrentModuleName(moduleName);
+            instrumentFile(new File(file), outDir, includeRTJar);
+        }
+    }
+
     /**
      * <p> This method instruments a bunch of files using default instrumenter.
      * This method doesn't write output template.xml - use
@@ -211,7 +220,7 @@
     private void setDefaultInstrumenter() {
 
         if (morph == null) {
-            InstrumentationParams params = new InstrumentationParams(gennative, genfield, genabstract, include, exclude, callerInclude, callerExclude, mode, save_beg, save_end)
+            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);
@@ -337,6 +346,14 @@
         this.exclude = exclude;
     }
 
+    public String[] getMExclude() {
+        return m_exclude;
+    }
+
+    public void setMExclude(String[] m_exclude) {
+        this.m_exclude = m_exclude;
+    }
+
     public boolean isGenField() {
         return genfield;
     }
@@ -361,6 +378,14 @@
         this.include = include;
     }
 
+    public String[] getMInclude() {
+        return m_include;
+    }
+
+    public void setMInclude(String[] m_include) {
+        this.m_include = m_include;
+    }
+
     public void setCallerInclude(String[] callerInclude) {
         this.callerInclude = callerInclude;
     }
@@ -450,28 +475,30 @@
     @Override
     protected EnvHandler defineHandler() {
         return new EnvHandler(new OptionDescr[]{
-                    DSC_OUTPUT,
-                    DSC_VERBOSE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TYPE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SAVE_BEGIN,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SAVE_AT_END,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TEMPLATE,
-                    DSC_SUBSEQUENT,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ABSTRACT,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_NATIVE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FIELD,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SYNTHETIC,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ANONYM,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNERINVOCATION,
-                    ClassMorph.DSC_FLUSH_CLASSES,
-                    DSC_INCLUDE_RT,
-                    DSC_RECURSE,}, this);
+                DSC_OUTPUT,
+                DSC_VERBOSE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TYPE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SAVE_BEGIN,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SAVE_AT_END,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TEMPLATE,
+                DSC_SUBSEQUENT,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ABSTRACT,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_NATIVE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FIELD,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SYNTHETIC,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ANONYM,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNERINVOCATION,
+                ClassMorph.DSC_FLUSH_CLASSES,
+                DSC_INCLUDE_RT,
+                DSC_RECURSE,}, this);
     }
 
     private int handleEnv_(EnvHandler opts) throws EnvHandlingException {
@@ -576,9 +603,9 @@
     }
     final static OptionDescr DSC_OUTPUT =
             new OptionDescr("instr.output", new String[]{"output", "o"}, "Output directory for instrumented classes",
-            OptionDescr.VAL_SINGLE,
-            "Specifies output directory, default directory is current. Instr command could process different dirs and different jars: \n "
-            + "all classes from input dirs and all jars will be placed in output directory.");
+                    OptionDescr.VAL_SINGLE,
+                    "Specifies output directory, default directory is current. Instr command could process different dirs and different jars: \n "
+                            + "all classes from input dirs and all jars will be placed in output directory.");
     final static OptionDescr DSC_VERBOSE =
             new OptionDescr("verbose", "Verbose mode", "Enable verbose mode.");
     final static OptionDescr DSC_INCLUDE_RT =
--- a/src/classes/com/sun/tdk/jcov/JCov.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/JCov.java	Mon Oct 26 14:31:30 2015 +0300
@@ -84,7 +84,7 @@
             return 1;
         }
 
-        File parentProductDir = productDir.getParentFile();
+        File parentProductDir = productDir.getCanonicalFile().getParentFile();
 
         //zip product
         try {
--- a/src/classes/com/sun/tdk/jcov/JREInstr.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/JREInstr.java	Mon Oct 26 14:31:30 2015 +0300
@@ -24,11 +24,14 @@
  */
 package com.sun.tdk.jcov;
 
+import com.sun.tdk.jcov.instrument.*;
 import com.sun.tdk.jcov.runtime.JCovSESocketSaver;
 import com.sun.tdk.jcov.tools.EnvHandler;
 import com.sun.tdk.jcov.tools.JCovCMDTool;
 import com.sun.tdk.jcov.tools.OptionDescr;
 import com.sun.tdk.jcov.util.Utils;
+import org.objectweb.asm.*;
+import org.objectweb.asm.Attribute;
 
 import java.io.*;
 import java.net.URL;
@@ -104,15 +107,70 @@
         StaticJREInstrClassLoader cl = new StaticJREInstrClassLoader(new URL[]{toInstrument.toURI().toURL()});
         instr.setClassLoader(cl);
 
-        if (toInstrument.getAbsolutePath().endsWith("bootmodules.jimage")){
+        if (toInstrument.getName().equals("jmods")) {
+            logger.log(Level.INFO, "working with jmods");
+            File jdk = new File(toInstrument.getParentFile(), "jdk");
+            if (!jdk.exists()) {
+                jdk = toInstrument.getParentFile();
+            }
+            File jmodsTemp = new File(toInstrument.getParentFile(), "jmod_temp");
 
+            for (File mod : toInstrument.listFiles()) {
+                File jmodDir = extractJMod(jdk, mod.getAbsoluteFile(), jmodsTemp);
+                Utils.addToClasspath(new String[]{new File(jmodDir, "classes").getAbsolutePath()});
+            }
+
+            try {
+                for (File mod : jmodsTemp.listFiles()) {
+                    if (mod != null && mod.isDirectory()) {
+
+                        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);
+                        }
+
+                        instr.instrumentFile(modClasses.getAbsolutePath(), null, null, mod.getName());
+                        createJMod(mod, jdk, implant.getAbsolutePath());
+                    }
+                }
+
+                File newJdkDir = runJLink(jmodsTemp, jdk);
+                if (newJdkDir != null) {
+                    String jimage_path = File.separator + "lib" + File.separator + "modules" + File.separator + "bootmodules.jimage";
+                    File orig_jimage = new File(jdk.getCanonicalPath() + jimage_path);
+                    File instr_jimage = new File(newJdkDir.getCanonicalPath() + jimage_path);
+
+                    Utils.copyFile(orig_jimage, new File(orig_jimage.getParent(), orig_jimage.getName() + ".bak"));
+
+                    if (!orig_jimage.delete()) {
+                        Utils.copyFile(instr_jimage, new File(orig_jimage.getParent(), orig_jimage.getName() + ".instr"));
+                        logger.log(Level.SEVERE, "please, delete original jimage manually: " + orig_jimage);
+                    } else {
+                        Utils.copyFile(instr_jimage, orig_jimage);
+                    }
+                    if (!Utils.deleteDirectory(newJdkDir)) {
+                        logger.log(Level.SEVERE, "please, delete " + newJdkDir + " new instumented jdk dir manually");
+                    }
+                    if (!Utils.deleteDirectory(jmodsTemp)) {
+                        logger.log(Level.SEVERE, "please, delete " + jmodsTemp + " temp jmod dir manually");
+                    }
+
+                } else {
+                    logger.log(Level.SEVERE, "failed to link modules. Please, run jlink for " + jmodsTemp + " temp jmod dir manually");
+                }
+            } catch (Exception e) {
+                logger.log(Level.SEVERE, "exception while creating mods, e = " + e);
+            }
+        } else if (toInstrument.getAbsolutePath().endsWith("bootmodules.jimage")) {
             ArrayList<File> jdkImages = new ArrayList<File>();
             jdkImages.add(toInstrument);
             if (addJimages != null) {
                 Collections.addAll(jdkImages, addJimages);
             }
 
-            for (File jimageInstr: jdkImages) {
+            for (File jimageInstr : jdkImages) {
                 String tempDirName = jimageInstr.getName().substring(0, jimageInstr.getName().indexOf(".jimage"));
 
                 expandJimage(jimageInstr, tempDirName);
@@ -120,22 +178,30 @@
                 File dirtoInstrument = new File(jimageInstr.getParent(), tempDirName);
                 //still need it
                 Utils.addToClasspath(new String[]{dirtoInstrument.getAbsolutePath()});
-                for (File file:dirtoInstrument.listFiles()){
-                    if (file.isDirectory()){
+                for (File file : dirtoInstrument.listFiles()) {
+                    if (file.isDirectory()) {
                         Utils.addToClasspath(new String[]{file.getAbsolutePath()});
                     }
                 }
 
                 if (jimageInstr.equals(toInstrument)) {
-                    instr.instrumentFile(dirtoInstrument.getAbsolutePath(), null, implant.getAbsolutePath());
-                }
-                else{
+                    for (File mod : dirtoInstrument.listFiles()) {
+                        if (mod != null && mod.isDirectory()) {
+
+                            if ("java.base".equals(mod.getName())) {
+                                instr.instrumentFile(mod.getAbsolutePath(), null, implant.getAbsolutePath(), mod.getName());
+                            } else {
+                                instr.instrumentFile(mod.getAbsolutePath(), null, null, mod.getName());
+                            }
+                        }
+                    }
+                } else {
                     instr.instrumentFile(dirtoInstrument.getAbsolutePath(), null, null);
                 }
                 createJimage(dirtoInstrument, jimageInstr.getAbsolutePath() + "i");
 
             }
-            for (File jimageInstr: jdkImages) {
+            for (File jimageInstr : jdkImages) {
 
                 String tempDirName = jimageInstr.getName().substring(0, jimageInstr.getName().indexOf(".jimage"));
                 File dirtoInstrument = new File(jimageInstr.getParent(), tempDirName);
@@ -145,18 +211,16 @@
 
                 Utils.copyFile(jimageInstr, new File(jimageInstr.getParent(), jimageInstr.getName() + ".bak"));
 
-                if(!jimageInstr.delete()){
-                    logger.log(Level.SEVERE, "please, delete original jimage manually: "+jimageInstr);
-                }
-                else{
-                    Utils.copyFile(new File(jimageInstr.getAbsolutePath()+"i"), jimageInstr);
-                    new File(jimageInstr.getAbsolutePath()+"i").delete();
+                if (!jimageInstr.delete()) {
+                    logger.log(Level.SEVERE, "please, delete original jimage manually: " + jimageInstr);
+                } else {
+                    Utils.copyFile(new File(jimageInstr.getAbsolutePath() + "i"), jimageInstr);
+                    new File(jimageInstr.getAbsolutePath() + "i").delete();
                 }
 
             }
 
-        }
-        else {
+        } else {
             instr.instrumentFile(toInstrument.getAbsolutePath(), null, implant.getAbsolutePath());
         }
 
@@ -186,14 +250,136 @@
     }
 
 
-    private boolean expandJimage(File jimage, String tempDirName){
+    private void updateExports(File file, ClassLoader cl) {
         try {
-            String command = jimage.getParentFile().getParentFile().getParent()+File.separator+"bin"+File.separator+"jimage extract --dir "+
-                    jimage.getParent()+File.separator+tempDirName+" "+jimage.getAbsolutePath();
+            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);
+
+            DataOutputStream dout = new DataOutputStream(new FileOutputStream(file.getCanonicalPath()));
+            dout.write(cw.toByteArray());
+            dout.flush();
+            in.close();
+            dout.close();
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "can not update module exports", e);
+        }
+    }
+
+    private void updateHashes(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 HashesAttribute()}, 0);
+
+            DataOutputStream doutn = new DataOutputStream(new FileOutputStream(file.getCanonicalPath()));
+            doutn.write(cw.toByteArray());
+            doutn.flush();
+            in.close();
+            doutn.close();
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "can not update module hashes", e);
+        }
+    }
+
+    private File extractJMod(File jdk, File from, File to) {
+        try {
+            String name = from.getName();
+            if (name.contains(".jmod")) {
+                name = name.substring(0, name.indexOf(".jmod"));
+            }
+            File modDir = new File(to, name);
+            modDir.mkdirs();
+
+            String command = jdk.getAbsolutePath() + File.separator + "bin" + File.separator + "jar xf " + from.getAbsolutePath();
+            Process process = Runtime.getRuntime().exec(command, null, modDir);
+            process.waitFor();
+            if (process.exitValue() != 0) {
+                logger.log(Level.SEVERE, "wrong command for unjar jmod: " + command);
+                return null;
+            }
+            return modDir;
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "exception in process(unjar jmod)", e);
+            return null;
+        }
+    }
+
+    private File runJLink(File jmodDir, File jdk) {
+        try {
+
+            String command = jdk.getAbsolutePath() + File.separator + "bin" + File.separator + "jlink --modulepath " + jmodDir.getCanonicalPath() + " --addmods ";
+
+            StringBuilder sb = new StringBuilder("");
+            for (File subDir : jmodDir.listFiles()) {
+                if (subDir.isDirectory()) {
+                    sb.append(subDir.getName()).append(",");
+                }
+            }
+            String mods = sb.toString().substring(0, sb.toString().length() - 1);
+            command += mods + " --output instr_jimage_dir";
+
+            Process process = Runtime.getRuntime().exec(command, null, jmodDir.getParentFile());
+            process.waitFor();
+            if (process.exitValue() != 0) {
+                logger.log(Level.SEVERE, "wrong command for jlink mods: " + command);
+                return null;
+            }
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "exception in process(jlink mods)", e);
+            return null;
+        }
+
+        return new File(jmodDir.getParentFile(), "instr_jimage_dir");
+    }
+
+    private void createJMod(File jmodDir, File jdk, String rt_path) {
+        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() + " ");
+
+            for (File subDir : jmodDir.listFiles()) {
+                if (subDir.getName().equals("classes")) {
+                    if ("java.base".equals(jmodDir.getName())) {
+                        command.append("--class-path " + rt_path + File.pathSeparator + jmodDir.getName() + File.separator + "classes ");
+                    } else {
+                        command.append("--class-path " + jmodDir.getName() + File.separator + "classes ");
+                    }
+                }
+                if (subDir.getName().equals("bin")) {
+                    command.append("--cmds " + jmodDir.getName() + File.separator + "bin ");
+                }
+                if (subDir.getName().equals("conf")) {
+                    command.append("--config " + jmodDir.getName() + File.separator + "conf ");
+                }
+                if (subDir.getName().equals("native")) {
+                    command.append("--libs " + jmodDir.getName() + File.separator + "native ");
+                }
+            }
+            command.append(" " + jmodDir.getName() + ".jmod");
+
+            Process process = Runtime.getRuntime().exec(command.toString(), null, modsDir);
+            process.waitFor();
+            if (process.exitValue() != 0) {
+                logger.log(Level.SEVERE, "wrong command for create jmod: " + command.toString());
+            }
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "exception in process(create jmod)", e);
+        }
+    }
+
+    private boolean expandJimage(File jimage, String tempDirName) {
+        try {
+            String command = jimage.getParentFile().getParentFile().getParent() + File.separator + "bin" + File.separator + "jimage extract --dir " +
+                    jimage.getParent() + File.separator + tempDirName + " " + jimage.getAbsolutePath();
             Process process = Runtime.getRuntime().exec(command);
             process.waitFor();
             if (process.exitValue() != 0) {
-                logger.log(Level.SEVERE, "wrong command for expand jimage: "+command);
+                logger.log(Level.SEVERE, "wrong command for expand jimage: " + command);
                 return false;
             }
         } catch (Exception e) {
@@ -203,14 +389,14 @@
         return true;
     }
 
-    private boolean createJimage(File dir, String new_jimage_path){
+    private boolean createJimage(File dir, String new_jimage_path) {
         try {
-            String command = dir.getParentFile().getParentFile().getParent()+File.separator+"bin"+File.separator+"jimage recreate --dir "+
-                    dir + " "+ new_jimage_path;
+            String command = dir.getParentFile().getParentFile().getParent() + File.separator + "bin" + File.separator + "jimage recreate --dir " +
+                    dir + " " + new_jimage_path;
             Process process = Runtime.getRuntime().exec(command);
             process.waitFor();
             if (process.exitValue() != 0) {
-                logger.log(Level.SEVERE, "wrong command for create jimage: "+command);
+                logger.log(Level.SEVERE, "wrong command for create jimage: " + command);
                 return false;
             }
         } catch (Exception e) {
@@ -224,30 +410,34 @@
     protected EnvHandler defineHandler() {
         Instr.DSC_INCLUDE_RT.usage = "To run instrumented JRE you should implant JCov runtime library both into rt.jar and into 'lib/endorsed' directory.\nWhen instrumenting whole JRE dir with jreinstr tool - these 2 actions will be done automatically.";
         return new EnvHandler(new OptionDescr[]{
-                    Instr.DSC_INCLUDE_RT,
-                    Instr.DSC_VERBOSE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TYPE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TEMPLATE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ABSTRACT,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_NATIVE,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FIELD,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SYNTHETIC,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ANONYM,
-                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNERINVOCATION,
-                    Instr.DSC_SUBSEQUENT,
-                    DSC_JAVAC_HACK,
-                    DCS_ADD_JAR,
-                    DCS_ADD_JIMAGE,
-                    DCS_ADD_TESTS,
-                    DSC_HOST,
-                    DSC_PORT
-                }, this);
+                Instr.DSC_INCLUDE_RT,
+                Instr.DSC_VERBOSE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TYPE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE_LIST,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE_LIST,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_TEMPLATE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ABSTRACT,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_NATIVE,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FIELD,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_SYNTHETIC,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ANONYM,
+                com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INNERINVOCATION,
+                Instr.DSC_SUBSEQUENT,
+                DSC_JAVAC_HACK,
+                DCS_ADD_JAR,
+                DCS_ADD_JIMAGE,
+                DCS_ADD_TESTS,
+                DSC_HOST,
+                DSC_PORT
+        }, this);
     }
 
     @Override
@@ -417,86 +607,86 @@
                 throw new EnvHandlingException("lib directory was not found in JRE directory");
             }
 
-            toInstrument = new File(lib, "modules");
-            if (!toInstrument.exists()) {
-                toInstrument = new File(lib, "rt.jar");
+            String template = envHandler.getValue(InstrumentationOptions.DSC_TEMPLATE);
+            if (template != null) {
+                instr.setTemplate(template);
+            }
+
+            File mods = new File(f.getParentFile(), "jmods");
+            if (mods.exists()) {
+                toInstrument = mods;
+                createPropertyFile(f);
+            }
+            else if (new File(f, "jmods").exists()){
+                toInstrument = new File(f, "jmods");
+                createPropertyFile(toInstrument.getParentFile());
+            }
+            else {
+
+                toInstrument = new File(lib, "modules");
                 if (!toInstrument.exists()) {
-                    throw new EnvHandlingException("rt.jar directory was not found in lib directory");
-                }
-                if (!toInstrument.isFile() || !toInstrument.canRead() || !toInstrument.canWrite()) {
-                    throw new EnvHandlingException("Can't read/write rt.jar (or not a file)");
-                }
-                File bak = new File(lib, "rt.jar.bak");
-                if (!bak.exists()) {
-                    try {
-                        Utils.copyFile(toInstrument, bak);
-                    } catch (FileNotFoundException ex) {
-                        throw new EnvHandlingException("Error while backuping rt.jar: file not found", ex);
-                    } catch (IOException ex) {
-                        throw new EnvHandlingException("Error while backuping rt.jar", ex);
+                    toInstrument = new File(lib, "rt.jar");
+                    if (!toInstrument.exists()) {
+                        throw new EnvHandlingException("rt.jar directory was not found in lib directory");
                     }
-                } else {
-                    if (!envHandler.isSet(Instr.DSC_SUBSEQUENT)) {
-                        throw new EnvHandlingException("Backup rt.jar.bak file exisit. It can mean that JRE is already instrumented - nothing to do. Restore initial rt.jar or delete bak file.");
+                    if (!toInstrument.isFile() || !toInstrument.canRead() || !toInstrument.canWrite()) {
+                        throw new EnvHandlingException("Can't read/write rt.jar (or not a file)");
                     }
-                }
-
-                File endorsed = new File(lib, "endorsed");
-                if (!endorsed.exists()) {
-                    endorsed.mkdir();
-                } else {
-                    if (!endorsed.isDirectory()) {
-                        throw new EnvHandlingException("JRE/lib/endorsed is not a directory");
-                    }
-                }
-                File implantcopy = new File(endorsed, implant.getName());
-                try {
-                    // copy rt to endorsed dir
-                    Utils.copyFile(implant, implantcopy);
-
-                    if (host != null || port != null) {
-                        Properties prop = new Properties();
+                    File bak = new File(lib, "rt.jar.bak");
+                    if (!bak.exists()) {
                         try {
-                            if (host != null) {
-                                prop.setProperty(JCovSESocketSaver.HOST_PROPERTIES_NAME, host);
-                            }
-                            if (port != null) {
-                                prop.setProperty(JCovSESocketSaver.PORT_PROPERTIES_NAME, Integer.toString(port));
-                            }
-                            prop.store(new FileOutputStream(endorsed.getAbsolutePath() + File.separator + JCovSESocketSaver.NETWORK_DEF_PROPERTIES_FILENAME), null);
-
+                            Utils.copyFile(toInstrument, bak);
+                        } catch (FileNotFoundException ex) {
+                            throw new EnvHandlingException("Error while backuping rt.jar: file not found", ex);
                         } catch (IOException ex) {
-                            logger.log(Level.WARNING, "Cannot create property file to save host and port: {0}", ex);
+                            throw new EnvHandlingException("Error while backuping rt.jar", ex);
+                        }
+                    } else {
+                        if (!envHandler.isSet(Instr.DSC_SUBSEQUENT)) {
+                            throw new EnvHandlingException("Backup rt.jar.bak file exisit. It can mean that JRE is already instrumented - nothing to do. Restore initial rt.jar or delete bak file.");
                         }
                     }
 
+                    File endorsed = new File(lib, "endorsed");
+                    if (!endorsed.exists()) {
+                        endorsed.mkdir();
+                    } else {
+                        if (!endorsed.isDirectory()) {
+                            throw new EnvHandlingException("JRE/lib/endorsed is not a directory");
+                        }
+                    }
+                    File implantcopy = new File(endorsed, implant.getName());
+                    try {
+                        // copy rt to endorsed dir
+                        Utils.copyFile(implant, implantcopy);
+                        createPropertyFile(endorsed);
 
-                } catch (FileNotFoundException ex) {
-                    throw new EnvHandlingException("Error while copying implant file to endorsed dir: file not found", ex);
-                } catch (IOException ex) {
-                    throw new EnvHandlingException("Error while copying implant file to endorsed dir", ex);
-                }
-            }
-            else{
-                toInstrument = new File(toInstrument, "bootmodules.jimage");
-                if (!toInstrument.exists()) {
-                    throw new EnvHandlingException("bootmodules.jimage was not found in modules directory");
-                }
-                if (!toInstrument.isFile() || !toInstrument.canRead() || !toInstrument.canWrite()) {
-                    throw new EnvHandlingException("Can't read/write bootmodules.jimage");
-                }
-                File bak = new File(toInstrument.getParent(), "bootmodules.jimage.bak");
-                if (!bak.exists()) {
-                    try {
-                        Utils.copyFile(toInstrument, bak);
                     } catch (FileNotFoundException ex) {
-                        throw new EnvHandlingException("Error while backuping bootmodules.jimage: file not found", ex);
+                        throw new EnvHandlingException("Error while copying implant file to endorsed dir: file not found", ex);
                     } catch (IOException ex) {
-                        throw new EnvHandlingException("Error while backuping bootmodules.jimage", ex);
+                        throw new EnvHandlingException("Error while copying implant file to endorsed dir", ex);
                     }
                 } else {
-                    if (!envHandler.isSet(Instr.DSC_SUBSEQUENT)) {
-                        throw new EnvHandlingException("Backup bootmodules.jimage.bak file exisit. It can mean that JRE is already instrumented - nothing to do. Restore initial bootmodules.jimage or delete bak file.");
+                    toInstrument = new File(toInstrument, "bootmodules.jimage");
+                    if (!toInstrument.exists()) {
+                        throw new EnvHandlingException("bootmodules.jimage was not found in modules directory");
+                    }
+                    if (!toInstrument.isFile() || !toInstrument.canRead() || !toInstrument.canWrite()) {
+                        throw new EnvHandlingException("Can't read/write bootmodules.jimage");
+                    }
+                    File bak = new File(toInstrument.getParent(), "bootmodules.jimage.bak");
+                    if (!bak.exists()) {
+                        try {
+                            Utils.copyFile(toInstrument, bak);
+                        } catch (FileNotFoundException ex) {
+                            throw new EnvHandlingException("Error while backuping bootmodules.jimage: file not found", ex);
+                        } catch (IOException ex) {
+                            throw new EnvHandlingException("Error while backuping bootmodules.jimage", ex);
+                        }
+                    } else {
+                        if (!envHandler.isSet(Instr.DSC_SUBSEQUENT)) {
+                            throw new EnvHandlingException("Backup bootmodules.jimage.bak file exisit. It can mean that JRE is already instrumented - nothing to do. Restore initial bootmodules.jimage or delete bak file.");
+                        }
                     }
                 }
             }
@@ -507,6 +697,9 @@
         String[] includes = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleInclude(envHandler);
         Utils.Pattern pats[] = Utils.concatFilters(includes, excludes);
 
+        String[] m_excludes = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleMExclude(envHandler);
+        String[] m_includes = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleMInclude(envHandler);
+
         callerInclude = envHandler.getValues(com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_INCLUDE);
         callerExclude = envHandler.getValues(com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_CALLER_EXCLUDE);
 
@@ -520,18 +713,48 @@
                 includes = new String[]{"/java/lang/Shutdown", "/*"};
             }
         }
+        if (!Utils.accept(pats, null, "/java/lang/invoke/LambdaForm", null)) {
+            logger.log(Level.WARNING, "java.lang.invoke.LambdaForm automatically included to instrumentation (it can't be excluded in jreinstr)");
+            if (includes.length > 0) { // if something else is already included - just including Shutdown
+                includes = Utils.copyOf(includes, includes.length + 1);
+                includes[includes.length - 1] = "/java/lang/invoke/LambdaForm";
+            } else {
+                includes = new String[]{"/java/lang/invoke/LambdaForm", "/*"};
+            }
+        }
 
         int ret = instr.handleEnv(envHandler);
         instr.setSave_end(new String[]{"java/lang/Shutdown.runHooks"});
         instr.setInclude(includes);
         instr.setExclude(excludes);
 
+        instr.setMInclude(m_includes);
+         instr.setMExclude(m_excludes);
+
         instr.setCallerInclude(callerInclude);
         instr.setCallerExclude(callerExclude);
 
         return ret;
     }
 
+    private void createPropertyFile(File dir){
+        if (host != null || port != null) {
+            Properties prop = new Properties();
+            try {
+                if (host != null) {
+                    prop.setProperty(JCovSESocketSaver.HOST_PROPERTIES_NAME, host);
+                }
+                if (port != null) {
+                    prop.setProperty(JCovSESocketSaver.PORT_PROPERTIES_NAME, Integer.toString(port));
+                }
+                prop.store(new FileOutputStream(dir.getAbsolutePath() + File.separator + JCovSESocketSaver.NETWORK_DEF_PROPERTIES_FILENAME), null);
+
+            } catch (IOException ex) {
+                logger.log(Level.WARNING, "Cannot create property file to save host and port: {0}", ex);
+            }
+        }
+    }
+
     @Override
     protected String getDescr() {
         return "instrumenter designed for instumenting rt.jar";
@@ -546,6 +769,7 @@
     protected String exampleString() {
         return "To instrument JRE: \"java -jar jcov.jar jreinstr -implantrt jcov_j2se_rt.jar JDK1.7.0/jre\"";
     }
+
     public static final OptionDescr DSC_JAVAC_HACK = new OptionDescr("javac", "hack javac", OptionDescr.VAL_SINGLE, "Hack javac to increase minimum VM memory used on initialization. Should be used on Solaris platform or should be done manually. ");
     public static final OptionDescr DCS_ADD_JAR = new OptionDescr("addjar", new String[]{"add"}, "instrument additional jars", OptionDescr.VAL_MULTI, "Instrument additional jars within JRE or JDK. Only jar files are allowed.");
     public static final OptionDescr DCS_ADD_JIMAGE = new OptionDescr("addjimage", new String[]{"addjimage"}, "instrument additional jimages", OptionDescr.VAL_MULTI, "Instrument additional jimages within JRE or JDK. Only jimage files are allowed.");
@@ -554,4 +778,4 @@
             new OptionDescr("host", new String[]{"host"}, "sets default host", OptionDescr.VAL_SINGLE, "set the default host for sending jcov data. needed only in network mode");
     final static OptionDescr DSC_PORT =
             new OptionDescr("port", new String[]{"port"}, "sets default port", OptionDescr.VAL_SINGLE, "set the default port for sending jcov data. needed only in network mode");
-}
+}
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/RepGen.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/RepGen.java	Mon Oct 26 14:31:30 2015 +0300
@@ -28,6 +28,7 @@
 import com.sun.tdk.jcov.instrument.DataField;
 import com.sun.tdk.jcov.instrument.DataClass;
 import com.sun.tdk.jcov.processing.DataProcessorSPI;
+import com.sun.tdk.jcov.report.AncFilter;
 import com.sun.tdk.jcov.util.Utils;
 import com.sun.tdk.jcov.data.FileFormatException;
 import com.sun.tdk.jcov.data.Result;
@@ -94,8 +95,11 @@
     private DataProcessorSPI dataProcessorSPIs[];
     private String[] include = new String[]{".*"};
     private String[] exclude = new String[]{""};
+    private String[] m_include = new String[]{".*"};
+    private String[] m_exclude = new String[]{""};
     private String[] fms = null;
     private String filter = null;
+    private String[] ancfilters = null;
     private boolean noAbstract = false;
     private boolean syntheticOn = false;
     private boolean isPublicAPI = false;
@@ -108,6 +112,10 @@
     private boolean withTestsInfo = false;
     //path to the jar, dir or .class for javap repgen
     private String classesPath;
+    private AncFilter[] ancfiltersClasses = null;
+    private String mainReportTitle = null;
+    private String overviewListTitle = null;
+    private String entitiesTitle = null;
 
     public RepGen() {
         readPlugins = true;
@@ -221,6 +229,20 @@
             logger.fine("OK");
         }
 
+        if (ancfilters != null){
+            ancfiltersClasses = new AncFilter[ancfilters.length];
+            for (int i = 0; i < ancfilters.length; i++) {
+                try {
+                    String ancfilter = ancfilters[i];
+                    Class ancFilteClass = Class.forName(ancfilter);
+                    ancfiltersClasses[i] = (AncFilter) ancFilteClass.newInstance();
+                } catch (Exception e) {
+                    throw new Error("Cannot create an instance of "
+                            + "AncFilter: ", e);
+                }
+            }
+        }
+
         if (dataProcessorSPIs != null) {
             for (DataProcessorSPI spi : dataProcessorSPIs) {
                 logger.log(Level.INFO, "-- Applying data processor {0}", spi.getClass());
@@ -241,12 +263,13 @@
             }
             logger.fine("OK");
         }
-        ReportGenerator.Options options = new ReportGenerator.Options(srcRootPath, sts, classes, withTestsInfo, false);
+        ReportGenerator.Options options = new ReportGenerator.Options(srcRootPath, sts, classes, withTestsInfo, false,
+                mainReportTitle, overviewListTitle, entitiesTitle);
         options.setInstrMode(file_image.getParams().getMode());
         options.setAnonymOn(anonym);
 
         try {
-            ProductCoverage coverage = new ProductCoverage(file_image, options.getSrcRootPaths(), options.getJavapClasses(), isPublicAPI, noAbstract, anonym);
+            ProductCoverage coverage = new ProductCoverage(file_image, options.getSrcRootPaths(), options.getJavapClasses(), isPublicAPI, noAbstract, anonym, ancfiltersClasses);
 
             logger.log(Level.INFO, "- Starting ReportGenerator {0}", rg.getClass().getName());
             rg.generateReport(coverage, options);
@@ -286,7 +309,7 @@
 
     protected DataRoot readDataRootFile(String filename, boolean readScales, String[] include, String[] exclude, String[] modif) throws FileFormatException {
         DataRoot file_image = null;
-        ClassSignatureFilter acceptor = new ClassSignatureFilter(include, exclude, modif);
+        ClassSignatureFilter acceptor = new ClassSignatureFilter(include, exclude, m_include, m_exclude, modif);
         file_image = Reader.readXML(filename, readScales, acceptor);
         return file_image;
     }
@@ -543,9 +566,14 @@
                 rg.init(outputDir);
                 String[] tl = testlist != null ? Utils.readLines(testlist) : merge.getResultTestList();
                 SmartTestService sts = new SmartTestService(tl);
-                ReportGenerator.Options options = new ReportGenerator.Options(srcRootPath, sts, null, true, true);
+                ReportGenerator.Options options = new ReportGenerator.Options(srcRootPath, sts, null, true, true,
+                        mainReportTitle, overviewListTitle, entitiesTitle);
                 try {
-                    ProductCoverage coverage = new ProductCoverage(merge.getResult(), options.getSrcRootPaths(), null, isPublicAPI, noAbstract);
+                    DataRoot mergedResult = merge.getResult();
+                    if (!syntheticOn) {
+                        mergedResult.applyFilter(new ANC_FILTER());
+                    }
+                    ProductCoverage coverage = new ProductCoverage(mergedResult, options.getSrcRootPaths(), null, isPublicAPI, noAbstract, ancfiltersClasses);
                     rg.generateReport(coverage, options);
 
                     if (srcZipped) {
@@ -606,6 +634,10 @@
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FM,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FM_LIST,
                     DSC_NO_ABSTRACT,
@@ -614,10 +646,14 @@
                     DSC_SRC_ROOT,
                     DSC_VERBOSE,
                     DSC_FILTER_PLUGIN,
+                    DSC_ANC_FILTER_PLUGINS,
                     DSC_TEST_LIST,
                     DSC_ANONYM,
                     DSC_JAVAP,
-                    DSC_TESTS_INFO,}, this);
+                    DSC_TESTS_INFO,
+                    DSC_REPORT_TITLE_MAIN,
+                    DSC_REPORT_TITLE_OVERVIEW,
+                    DSC_REPORT_TITLE_ENTITIES,}, this);
         SPIDescr spiDescr = new SPIDescr(CUSTOM_REPORT_GENERATOR_SPI, ReportGeneratorSPI.class);
         spiDescr.setDefaultSPI(new DefaultReportGeneratorSPI());
         envHandler.registerSPI(spiDescr);
@@ -643,6 +679,7 @@
         // no check for output
 
         filter = opts.getValue(DSC_FILTER_PLUGIN);
+        ancfilters = opts.getValues(DSC_ANC_FILTER_PLUGINS);
         noAbstract = opts.isSet(DSC_NO_ABSTRACT);
         isPublicAPI = opts.isSet(DSC_PUBLIC_API);
         anonym = opts.isSet(DSC_ANONYM);
@@ -652,6 +689,9 @@
         exclude = InstrumentationOptions.handleExclude(opts);
         fms = InstrumentationOptions.handleFM(opts);
 
+        m_include = InstrumentationOptions.handleMInclude(opts);
+        m_exclude = InstrumentationOptions.handleMExclude(opts);
+
         testlist = opts.getValue(DSC_TEST_LIST);
         Utils.checkFileCanBeNull(testlist, "testlist filename", Utils.CheckOptions.FILE_EXISTS, Utils.CheckOptions.FILE_CANREAD, Utils.CheckOptions.FILE_ISFILE);
 
@@ -662,6 +702,16 @@
             srcRootPath = opts.getValue(DSC_SRC_ROOT);
         }
 
+        if (opts.isSet(DSC_REPORT_TITLE_MAIN)){
+            mainReportTitle = opts.getValue(DSC_REPORT_TITLE_MAIN);
+        }
+        if (opts.isSet(DSC_REPORT_TITLE_OVERVIEW)){
+            overviewListTitle = opts.getValue(DSC_REPORT_TITLE_OVERVIEW);
+        }
+        if (opts.isSet(DSC_REPORT_TITLE_ENTITIES)){
+            entitiesTitle = opts.getValue(DSC_REPORT_TITLE_ENTITIES);
+        }
+
         ArrayList<ReportGeneratorSPI> reportGenerators = opts.getSPIs(ReportGeneratorSPI.class);
         if (reportGenerators != null) {
             reportGeneratorSPIs = reportGenerators.toArray(new ReportGeneratorSPI[reportGenerators.size()]);
@@ -745,6 +795,11 @@
     final static OptionDescr DSC_FILTER_PLUGIN =
             new OptionDescr("filter", "", OptionDescr.VAL_SINGLE,
             "Custom filtering plugin class");
+
+    final static OptionDescr DSC_ANC_FILTER_PLUGINS =
+            new OptionDescr("ancfilter", new String[]{"ancf"}, "Custom anc filtering plugin classes", OptionDescr.VAL_MULTI,
+                    "");
+
     /**
      *
      */
@@ -770,4 +825,11 @@
             new OptionDescr("javap", new String[]{"javap"}, "Path to the class files of the product to use javap", OptionDescr.VAL_SINGLE, "");
     public final static OptionDescr DSC_TESTS_INFO =
             new OptionDescr("testsinfo", "Additional information about for specified tests' list", "Show covererage for all tests in test list");
+
+    public final static OptionDescr DSC_REPORT_TITLE_MAIN =
+            new OptionDescr("mainReportTitle", new String[]{"mainReportTitle", "mrtitle"}, "The main report title", OptionDescr.VAL_SINGLE, "");
+    public final static OptionDescr DSC_REPORT_TITLE_OVERVIEW =
+            new OptionDescr("overviewReportTitle", new String[]{"overviewReportTitle", "ortitle"}, "The overview list report title", OptionDescr.VAL_SINGLE, "");
+    public final static OptionDescr DSC_REPORT_TITLE_ENTITIES =
+            new OptionDescr("entitiesReportTitle", new String[]{"entitiesReportTitle", "ertitle"}, "Entities report title (for modules, packages, subpackages)", OptionDescr.VAL_SINGLE, "");
 }
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/TmplGen.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/TmplGen.java	Mon Oct 26 14:31:30 2015 +0300
@@ -54,13 +54,15 @@
     private String template;
     private String[] include;
     private String[] exclude;
+    private String[] m_include;
+    private String[] m_exclude;
     private boolean instrumentAbstract = false;
     private boolean instrumentNative = true;
     private boolean instrumentField = false;
     private boolean instrumentAnonymous = true;
     private boolean instrumentSynthetic = true;
     private InstrumentationOptions.InstrumentationMode mode;
-    private HashMap<String, String> moduleInfo = null;
+    private String currentModule = null;
 
     /**
      * Legacy CMD line entry poiny (use 'java -jar jcov.jar TmplGen' from cmd
@@ -133,10 +135,11 @@
                         Utils.addToClasspath(new String[]{file.getAbsolutePath()});
                     }
                 }
-                instrumenter.instrument(new File(rootFile.getParentFile().getAbsolutePath()+File.separator+"temp_"+jimagename), null);
-                File jdata = new File(rootFile.getParentFile().getAbsolutePath()+File.separator+"temp_"+jimagename+File.separator+jimagename+".jdata");
-                if (jdata.exists()){
-                   fillModuleInfo(jdata);
+                for (File file:tempJimage.listFiles()){
+                    if (file.isDirectory()){
+                        currentModule = file.getName();
+                        instrumenter.instrument(file, null);
+                    }
                 }
             }
             else {
@@ -162,32 +165,6 @@
         return jimagename;
     }
 
-    private void fillModuleInfo(File jdata){
-        try {
-            HashMap<String, String> packages = new HashMap<String, String>();
-            Scanner sc = new Scanner(jdata);
-
-            while (sc.hasNextLine()) {
-                String line = sc.nextLine();
-                String[] lineInfo = line.split("\\t");
-                for (int i = 1; i < lineInfo.length; i++){
-                    packages.put(lineInfo[i], lineInfo[0]);
-                }
-            }
-            sc.close();
-
-            if (moduleInfo == null){
-                moduleInfo  = new HashMap<String, String>();
-            }
-
-            moduleInfo.putAll(packages);
-
-        }
-        catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-    }
-
     public void generateTemplate(String[] files) throws IOException {
         if (instrumenter == null) {
             setDefaultInstrumenter();
@@ -209,7 +186,7 @@
         if (instrumenter == null) {
             instrumenter = new AbstractUniversalInstrumenter(true, true) {
                 ClassMorph morph = new ClassMorph(
-                        new InstrumentationParams(instrumentNative, instrumentField, instrumentAbstract, include, exclude, mode)
+                        new InstrumentationParams(instrumentNative, instrumentField, instrumentAbstract, include, exclude, m_include, m_exclude, mode)
                         .setInstrumentAnonymous(instrumentAnonymous)
                         .setInstrumentSynthetic(instrumentSynthetic), template);
 
@@ -217,14 +194,12 @@
 //                    byte[] res = Arrays.copyOf(classData, classLen);
                     byte[] res = new byte[classLen];
                     System.arraycopy(classData, 0, res, 0, classLen);
+                    morph.setCurrentModuleName(currentModule);
                     morph.morph(res, null, flushPath); // jdk1.5 support
                     return res;
                 }
 
                 public void finishWork() {
-                    if (moduleInfo != null){
-                        morph.updateModuleInfo(moduleInfo);
-                    }
                     morph.saveData(template, InstrumentationOptions.MERGE.MERGE);
                 }
             };
@@ -242,6 +217,10 @@
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE_LIST,
+                    com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE_LIST,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_ABSTRACT,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_NATIVE,
                     com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FIELD,
@@ -321,6 +300,9 @@
         include = InstrumentationOptions.handleInclude(opts);
         exclude = InstrumentationOptions.handleExclude(opts);
 
+        m_exclude = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleMExclude(opts);
+        m_include = com.sun.tdk.jcov.instrument.InstrumentationOptions.handleMInclude(opts);
+
         com.sun.tdk.jcov.runtime.CollectDetect.enableInvokeCounts();
 
         return SUCCESS_EXIT_CODE;
@@ -334,6 +316,14 @@
         this.exclude = exclude;
     }
 
+    public String[] getMExclude() {
+        return m_exclude;
+    }
+
+    public void setMExclude(String[] m_exclude) {
+        this.m_exclude = exclude;
+    }
+
     public String getFlushPath() {
         return flushPath;
     }
@@ -350,6 +340,14 @@
         this.include = include;
     }
 
+    public String[] getMInclude() {
+        return m_include;
+    }
+
+    public void setMInclude(String[] m_include) {
+        this.m_include = m_include;
+    }
+
     public boolean isInstrumentAbstract() {
         return instrumentAbstract;
     }
--- a/src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/ClassMorph.java	Mon Oct 26 14:31:30 2015 +0300
@@ -53,7 +53,7 @@
 
     private DataRoot root;
     private final String outputFile;
-//    private List<String> instrumented = new ArrayList<String>();
+    //    private List<String> instrumented = new ArrayList<String>();
 //    private HashSet<String> instrumented = new HashSet<String>(); // Set should work better
     private HashMap<String, Long> instrumented = new HashMap<String, Long>(); // Set should work better
     private HashMap<String, byte[]> instrumentedValues = new HashMap<String, byte[]>(); // Set should work better
@@ -61,6 +61,7 @@
     private final InstrumentationParams params;
     private boolean rtClassesInstrumented = false;
     private static final Logger logger;
+    private String currentModuleName = null;
 
     static {
         Utils.initLogger();
@@ -204,6 +205,23 @@
             return res;
         }
 
+        String moduleName = null;
+        if (params.isDynamicCollect()) {
+            moduleName = updateClassModule(fullname);
+        }
+        else{
+            if (currentModuleName != null) {
+                moduleName = "module " + currentModuleName;
+            }
+        }
+        if (moduleName == null){
+            moduleName = "module "+XmlNames.NO_MODULE;
+        }
+
+        if (!params.isModuleIncluded(moduleName.substring(7, moduleName.length()))){
+            return null;
+        }
+
         // Checksum should be counted before changing content
         long checksum = params.isDynamicCollect() ? -1
                 : computeCheckSum(classfileBuffer);
@@ -224,10 +242,6 @@
         }
 
         ClassWriter cw = new OverriddenClassWriter(cr, opt, loader);
-        String moduleName = getModuleName(fullname);
-        if (moduleName == null){
-            moduleName = "module no_module";
-        }
         DataClass k = new DataClass(root.rootId(), fullname, moduleName.substring(7), checksum, false);
 //        ClassVisitor cv = shouldFlush ? new TraceClassVisitor
 //                (cw, DebugUtils.getPrintWriter(fullname, Options.getFlushPath())) :
@@ -258,19 +272,22 @@
         }
     }
 
-    private String getModuleName(String fullname){
+    public void setCurrentModuleName(String name){
+        currentModuleName = name;
+    }
+
+    private String updateClassModule(String fullname){
         String result = null;
         try{
-            if (fullname.contains("$$")){
-                fullname = fullname.substring(0, fullname.indexOf("$$"));
+            if (fullname.contains("$")){
+                fullname = fullname.substring(0, fullname.indexOf("$"));
             }
             Class cls = Class.forName(fullname.replaceAll("/","."));
-            java.lang.reflect.Method method = Class.class.getDeclaredMethod("getModule", null);
-            Object module = method.invoke(cls, null);
+            java.lang.reflect.Method getModuleMethod = Class.class.getDeclaredMethod("getModule", null);
+            Object module = getModuleMethod.invoke(cls, null);
             result = module.toString();
 
-        }catch(Throwable t){
-
+        }catch(Throwable ignore){
         }
         return result;
     }
@@ -578,9 +595,9 @@
     }
     public final static OptionDescr DSC_FLUSH_CLASSES =
             new OptionDescr("flush", null, "flush instrumented classes",
-            OptionDescr.VAL_SINGLE, null, "Specify path to directory, where to store instrumented classes.\n"
-            + "Directory should exist. Classes will be saved in respect to their package hierarchy.\n"
-            + "Default value is \"none\". Pushing it means you don't want to flush classes.", "none");
+                    OptionDescr.VAL_SINGLE, null, "Specify path to directory, where to store instrumented classes.\n"
+                    + "Directory should exist. Classes will be saved in respect to their package hierarchy.\n"
+                    + "Default value is \"none\". Pushing it means you don't want to flush classes.", "none");
 
     private boolean isPreVMLoadClass(String fullname) {
         // classes (actually only certain packages needed) which are loaded before
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/classes/com/sun/tdk/jcov/instrument/ConcealedPackagesAttribute.java	Mon Oct 26 14:31:30 2015 +0300
@@ -0,0 +1,92 @@
+/*
+ * 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/DataRoot.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/DataRoot.java	Mon Oct 26 14:31:30 2015 +0300
@@ -398,6 +398,17 @@
      * @param name
      * @return package
      */
+    public DataPackage findPackage(String name) {
+        return findPackage(name, XmlNames.NO_MODULE);
+    }
+
+    /**
+     * Find package by name and module name. Creates new DataPackage instance if the package
+     * doesn't exist
+     *
+     * @param name
+     * @return package
+     */
     public DataPackage findPackage(String name, String moduleName) {
         DataPackage pack = packages.get(name);
         if (pack == null) {
@@ -824,7 +835,7 @@
                 }
             } else {
                 DataPackage p = packages.get(pOther.getName());
-                if (p.getModuleName() == null || p.getModuleName().equals("no_module")) {
+                if (p.getModuleName() == null || p.getModuleName().equals(XmlNames.NO_MODULE)) {
                     p.setModuleName(pOther.getModuleName());
                 }
                 for (DataClass cl : pOther.getClasses()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/classes/com/sun/tdk/jcov/instrument/HashesAttribute.java	Mon Oct 26 14:31:30 2015 +0300
@@ -0,0 +1,99 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author Alexey Fedorchenko
+ */
+public class HashesAttribute extends Attribute {
+    private String algorithm;
+    private Map<String, String> nameToHash;
+
+
+    HashesAttribute(String algorithm, Map<String, String> nameToHash) {
+        super("Hashes");
+        this.algorithm = algorithm;
+        this.nameToHash = nameToHash;
+    }
+
+    public HashesAttribute() {
+        this(null, null);
+    }
+
+    @Override
+    protected Attribute read(ClassReader cr,
+                             int off,
+                             int len,
+                             char[] buf,
+                             int codeOff,
+                             Label[] labels)
+    {
+        String algorithm = cr.readUTF8(off, buf);
+        off += 2;
+
+        int hash_count = cr.readUnsignedShort(off);
+        off += 2;
+
+        Map<String, String> map = new HashMap<String, String>();
+        for (int i=0; i<hash_count; i++) {
+            String dn = cr.readUTF8(off, buf);
+            String hash = cr.readUTF8(off, buf);
+            map.put(dn, hash);
+            off += 2;
+        }
+
+        return new HashesAttribute(algorithm, map);
+    }
+
+    @Override
+    protected ByteVector write(ClassWriter cw,
+                               byte[] code,
+                               int len,
+                               int maxStack,
+                               int maxLocals)
+    {
+        ByteVector attr = new ByteVector();
+
+        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(""));
+        }
+
+        return attr;
+    }
+}
--- a/src/classes/com/sun/tdk/jcov/instrument/InstrumentationOptions.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InstrumentationOptions.java	Mon Oct 26 14:31:30 2015 +0300
@@ -52,12 +52,26 @@
             "Specifies file with xml based template of pre-instrumented classes. Each classfile presented\n"
             + " in this template should be statically instrumented. The instrumentation parameters should be\n"
             + "compatible for static and dynamic instrumentation.", XML_DEFAULT_TEMPLATE);
+    public final static OptionDescr DSC_MINCLUDE =
+            new OptionDescr("include_module", new String[]{"im"}, "Filtering conditions.",
+                    OptionDescr.VAL_MULTI, "Specify included classes by regular expression for modules.");
+    public final static OptionDescr DSC_MEXCLUDE =
+            new OptionDescr("exclude_module", new String[]{"em"}, "", OptionDescr.VAL_MULTI,
+                    "Specify excluded classes by regular expression for modules.");
     public final static OptionDescr DSC_INCLUDE =
             new OptionDescr("include", new String[]{"i"}, "Filtering conditions.",
             OptionDescr.VAL_MULTI, "Specify included classes by regular expression.");
     public final static OptionDescr DSC_EXCLUDE =
             new OptionDescr("exclude", new String[]{"e"}, "", OptionDescr.VAL_MULTI,
             "Specify excluded classes by regular expression.");
+    public final static OptionDescr DSC_MINCLUDE_LIST =
+            new OptionDescr("include_module_list", "", OptionDescr.VAL_SINGLE,
+            "Specify the path to the file containing module include list. The effect will be the same as\n"
+            + "using multiple -include_module options. File should contain one module name mask per line.");
+    public final static OptionDescr DSC_MEXCLUDE_LIST =
+            new OptionDescr("exclude_module_list", "", OptionDescr.VAL_SINGLE,
+            "Specify the path to the file containing module exclude list. The effect will be the same as\n"
+            + "using multiple -exclude_module options. File should contain one module name mask per line.");
     public final static OptionDescr DSC_INCLUDE_LIST =
             new OptionDescr("include_list", "", OptionDescr.VAL_SINGLE,
             "Specify the path to the file containing include list. The effect will be the same as\n"
@@ -209,6 +223,30 @@
         return includeSet.toArray(new String[includeSet.size()]);
     }
 
+    public static String[] handleMInclude(EnvHandler opts) throws EnvHandlingException {
+        Set<String> includeSet = new TreeSet<String>();
+        String[] s;
+        if (opts.isSet(InstrumentationOptions.DSC_MINCLUDE)) {
+            s = opts.getValues(InstrumentationOptions.DSC_MINCLUDE);
+            if (s != null) {
+                includeSet.addAll(Arrays.asList(s));
+            }
+        }
+
+        if (opts.isSet(InstrumentationOptions.DSC_MINCLUDE_LIST)) {
+            try {
+                s = Utils.readLines(opts.getValue(InstrumentationOptions.DSC_MINCLUDE_LIST));
+                if (s != null) {
+                    includeSet.addAll(Arrays.asList(s));
+                }
+            } catch (IOException ex) {
+                throw new EnvHandlingException("Error while reading module include list " + opts.getValue(InstrumentationOptions.DSC_INCLUDE_LIST), ex);
+            }
+        }
+
+        return includeSet.toArray(new String[includeSet.size()]);
+    }
+
     public static String[] handleExclude(EnvHandler opts) throws EnvHandlingException {
         Set<String> excludeSet = new TreeSet<String>();
         String[] s = opts.getValues(InstrumentationOptions.DSC_EXCLUDE);
@@ -229,6 +267,27 @@
         return excludeSet.toArray(new String[excludeSet.size()]);
     }
 
+    public static String[] handleMExclude(EnvHandler opts) throws EnvHandlingException {
+        Set<String> excludeSet = new TreeSet<String>();
+        String[] s = opts.getValues(InstrumentationOptions.DSC_MEXCLUDE);
+        if (s != null) {
+            excludeSet.addAll(Arrays.asList(s));
+        }
+
+        if (opts.isSet(InstrumentationOptions.DSC_MEXCLUDE_LIST)) {
+            try {
+                s = Utils.readLines(opts.getValue(InstrumentationOptions.DSC_MEXCLUDE_LIST));
+                if (s != null) {
+                    excludeSet.addAll(Arrays.asList(s));
+                }
+            } catch (IOException ex) {
+                throw new EnvHandlingException("Error while reading module exclude list " + opts.getValue(InstrumentationOptions.DSC_EXCLUDE_LIST), ex);
+            }
+        }
+
+        return excludeSet.toArray(new String[excludeSet.size()]);
+    }
+
     public static String[] handleFM(EnvHandler opts) throws EnvHandlingException {
         Set<String> fmSet = new TreeSet<String>();
         String[] s;
--- a/src/classes/com/sun/tdk/jcov/instrument/InstrumentationParams.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/InstrumentationParams.java	Mon Oct 26 14:31:30 2015 +0300
@@ -63,6 +63,7 @@
     private String[] savesBegin;
     private String[] savesEnd;
     private Pattern[] alls;
+    private Pattern[] all_modules;
     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) {
@@ -73,6 +74,10 @@
         this(false, instrumentNative, instrumentFields, false, instrumentAbstract ? ABSTRACTMODE.DIRECT : ABSTRACTMODE.NONE, includes, excludes, null, null, mode, null, null);
     }
 
+    public InstrumentationParams(boolean instrumentNative, boolean instrumentFields, boolean instrumentAbstract,  String[] includes, String[] excludes, String[] m_includes, String[] m_excludes, InstrumentationMode mode) {
+        this(false, false, false, instrumentNative, instrumentFields, false, instrumentAbstract ? ABSTRACTMODE.DIRECT : ABSTRACTMODE.NONE, includes, excludes, null, null, m_includes, m_excludes, mode, null, null);
+    }
+
     public InstrumentationParams(boolean instrumentNative, boolean instrumentFields, boolean instrumentAbstract, String[] includes, String[] excludes, InstrumentationMode mode, String[] saveBegin, String[] saveEnd) {
         this(false, instrumentNative, instrumentFields, false, instrumentAbstract ? ABSTRACTMODE.DIRECT : ABSTRACTMODE.NONE, includes, excludes, null, null, mode, saveBegin, saveEnd);
     }
@@ -90,6 +95,10 @@
     }
 
     public InstrumentationParams(boolean innerInvocations, boolean classesReload, boolean dynamicCollect, boolean instrumentNative, boolean instrumentFields, boolean detectInternal, ABSTRACTMODE instrumentAbstract, String[] includes, String[] excludes, String[] callerIncludes, String[] callerExcludes, InstrumentationMode mode, String[] saveBegin, String[] saveEnd) {
+        this(innerInvocations, classesReload, dynamicCollect, instrumentNative, instrumentFields, detectInternal, instrumentAbstract, includes, excludes, callerIncludes, callerExcludes, null, null, mode, saveBegin, saveEnd);
+    }
+
+    public InstrumentationParams(boolean innerInvocations, boolean classesReload, boolean dynamicCollect, boolean instrumentNative, boolean instrumentFields, boolean detectInternal, ABSTRACTMODE instrumentAbstract, String[] includes, String[] excludes, String[] callerIncludes, String[] callerExcludes, String[] m_includes, String[] m_excludes, InstrumentationMode mode, String[] saveBegin, String[] saveEnd) {
 
         this.innerInvocations = innerInvocations;
         this.detectInternal = detectInternal;
@@ -104,6 +113,12 @@
         if (excludes == null) {
             excludes = new String[]{""};
         }
+        if (m_includes == null) {
+            m_includes = new String[]{""};
+        }
+        if (m_excludes == null) {
+            m_excludes = new String[]{""};
+        }
         this.includes = includes;
         this.excludes = excludes;
         if (callerIncludes == null) {
@@ -123,6 +138,7 @@
         this.callerInclude = InstrumentationOptions.concatRegexps(callerIncludes);
         this.callerExclude = InstrumentationOptions.concatRegexps(callerExcludes);
         this.alls = Utils.concatFilters(includes, excludes);
+        this.all_modules = Utils.concatModuleFilters(m_includes, m_excludes);
     }
 
     public boolean isDetectInternal() {
@@ -176,6 +192,10 @@
         return Utils.accept(alls, null, "/" + classname, null);
     }
 
+    public boolean isModuleIncluded(String modulename) {
+        return Utils.accept(all_modules, null, modulename, null);
+    }
+
     public boolean isCallerFilterOn() {
         return /*dynamicCollect &&*/ !(callerInclude.equals(".*") && callerExclude.equals(""));
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/classes/com/sun/tdk/jcov/instrument/ModuleAttribute.java	Mon Oct 26 14:31:30 2015 +0300
@@ -0,0 +1,240 @@
+/*
+ * 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/OverriddenClassWriter.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/OverriddenClassWriter.java	Mon Oct 26 14:31:30 2015 +0300
@@ -239,8 +239,28 @@
         }
 
         InputStream in = getInputStreamForName(clName, ClassLoader.getSystemClassLoader(), false, ".class");
+        String superClassName = null;
+        String[] interfaceNames = null;
+        if (in == null){
+            try {
+                Class cClass = Class.forName(clName.replace("/", "."));
 
-        if (in == null) {
+                superClassName = "java/lang/Object";
+                if (cClass.getSuperclass() != null) {
+                    superClassName = cClass.getSuperclass().getName();
+                }
+                Class[] iclasses = cClass.getInterfaces();
+                if (iclasses != null) {
+                    interfaceNames = new String[iclasses.length];
+                    for (int i = 0; i < iclasses.length; i++) {
+                        interfaceNames[i] = iclasses[i].getName();
+                    }
+                }
+            } catch (ClassNotFoundException e) {
+            }
+        }
+
+        if (in == null && superClassName == null) {
 
             in = getInputStreamForName(clName, ClassLoader.getSystemClassLoader(), false, ".clazz");
 
@@ -265,12 +285,17 @@
 
         }
 
-        ClassReader cr = new OffsetLabelingClassReader(in);
-        classInfo = new ClassInfo(cr.getSuperName(), cr.getInterfaces());
-        try{
-            in.close();
+        if (superClassName == null) {
+            ClassReader cr = new OffsetLabelingClassReader(in);
+            classInfo = new ClassInfo(cr.getSuperName(), cr.getInterfaces());
+            try {
+                in.close();
+            } catch (Throwable ignore) {
+            }
         }
-        catch (Throwable ignore){}
+        else{
+            classInfo = new ClassInfo(superClassName, interfaceNames);
+        }
         return classInfo;
     }
 
--- a/src/classes/com/sun/tdk/jcov/instrument/XmlContext.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/XmlContext.java	Mon Oct 26 14:31:30 2015 +0300
@@ -162,6 +162,9 @@
     }
 
     private void writeEscaped(String str) {
+        if (str == null){
+            return;
+        }
         for (int i = 0, j = str.length(); i < j; i++) {
             int ch = str.charAt(i);
             switch (ch) {
--- a/src/classes/com/sun/tdk/jcov/instrument/XmlNames.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/instrument/XmlNames.java	Mon Oct 26 14:31:30 2015 +0300
@@ -103,6 +103,6 @@
     public static final String CRT_LINE = "line";
     public static final String CRT_COL = "col";
     public static final String INNER_CLASS = "inner";
-
     public static final String MODULE_NAME = "moduleName";
+    public static final String NO_MODULE = "no_module";
 }
--- a/src/classes/com/sun/tdk/jcov/io/ClassSignatureFilter.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/io/ClassSignatureFilter.java	Mon Oct 26 14:31:30 2015 +0300
@@ -50,6 +50,7 @@
     private String[] includes;
     private String[] excludes;
     private Pattern[] alls;
+    private Pattern[] all_modules;
 
     /**
      * Constructs new ClassSignatureAcceptor with the specified
@@ -60,14 +61,20 @@
      * @param modifs acceptable modifiers
      */
     public ClassSignatureFilter(String[] incl_masks, String[] excl_masks, String[] modifs) {
+        this(incl_masks, excl_masks, null , null, modifs);
+    }
+
+    public ClassSignatureFilter(String[] incl_masks, String[] excl_masks, String[] m_includes, String[] m_excludes, String[] modifs) {
         this.modifs = modifs;
         this.includes = incl_masks;
         this.excludes = excl_masks;
         this.alls = Utils.concatFilters(incl_masks, excl_masks);
+        this.all_modules = Utils.concatModuleFilters(m_includes, m_excludes);
     }
 
     public boolean accept(DataClass c) {
-        return Utils.accept(alls, modifs, "/" + c.getFullname(), c.getSignature());
+        return Utils.accept(all_modules, modifs, c.getModuleName(), null) &&
+               Utils.accept(alls, modifs, "/" + c.getFullname(), c.getSignature());
     }
 
     public boolean accept(DataClass clz, DataMethod m) {
--- a/src/classes/com/sun/tdk/jcov/report/AbstractCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/AbstractCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -104,8 +104,12 @@
      * @see CoverageData#getFormattedCoverage()
      */
     public final String getCoverageString(DataType type) {
+        return getCoverageString(type, false);
+    }
+
+    public final String getCoverageString(DataType type, boolean withAnc) {
         CoverageData data = getData(type);
-        return data.getFormattedCoverage();
+        return data.getFormattedCoverage(withAnc);
     }
 
     /**
@@ -123,6 +127,11 @@
         return data.getFormattedCoverage(f);
     }
 
+    public final String getCoverageString(DataType type, CoverageANCFormatter f, boolean withAnc) {
+        CoverageData data = getData(type);
+        return data.getFormattedCoverage(f, withAnc);
+    }
+
     public int compareTo(Object obj) {
         return NaturalComparator.INSTANCE.compare(this.getName(), ((AbstractCoverage) obj).getName());
     }
@@ -154,18 +163,40 @@
         public String format(CoverageData data);
     }
 
+    public static interface CoverageANCFormatter {
+
+        /**
+         * @param data CoverageData object to format
+         * @param withAnc Show acceptable not covered data
+         * @return formatted coverage data
+         */
+        public String format(CoverageData data, boolean withAnc);
+
+    }
+
     /**
      * Default CoverageFormatter that formats coverage in form of "percent%
      * (covered/total)" or " -" if total is null
      */
-    public static class PercentFormatter implements CoverageFormatter {
+    public static class PercentFormatter implements CoverageFormatter, CoverageANCFormatter {
 
-        public String format(CoverageData data) {
+        public String format(CoverageData data){
             if (data.total == 0) {
                 return " -";
             } else {
                 return String.format("%0$4.0f%% (%d/%d)", (float) data.covered / data.total * 100., data.covered, data.total);
             }
         }
+
+        public String format(CoverageData data, boolean withAnc){
+            if (data.total == 0) {
+                return " -";
+            } else {
+                if (!withAnc) {
+                    return String.format("%0$4.0f%% (%d/%d)", (float) data.covered / data.total * 100., data.covered, data.total);
+                }
+                return String.format("%0$4.0f%% (%d/%d/%d)", (float) (data.covered + data.anc) / (data.total) * 100., data.covered, data.anc, data.total);
+            }
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/classes/com/sun/tdk/jcov/report/AncFilter.java	Mon Oct 26 14:31:30 2015 +0300
@@ -0,0 +1,45 @@
+/*
+ * 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.report;
+
+
+import com.sun.tdk.jcov.instrument.DataBlock;
+import com.sun.tdk.jcov.instrument.DataClass;
+import com.sun.tdk.jcov.instrument.DataMethod;
+
+/**
+ * @author Alexey Fedorchenko
+ */
+public interface AncFilter {
+
+    public boolean accept(DataClass clz);
+
+    public boolean accept(DataClass clz, DataMethod m);
+
+    public boolean accept(DataMethod m, DataBlock b);
+
+    public String getAncReason();
+
+}
--- a/src/classes/com/sun/tdk/jcov/report/ClassCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/ClassCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -68,6 +68,8 @@
     private String name;
     private String packagename;
     private String modulename;
+    private boolean isInAnc = false;
+    protected String ancInfo;
 
     /**
      * <p> Creates new ClassCoverage instance. </p>
@@ -81,22 +83,44 @@
     }
 
     public ClassCoverage(DataClass clz, String srcRootPaths[], List<JavapClass> javapClasses, MemberFilter filter) {
-        this(clz, srcRootPaths, null, filter, false);
+        this(clz, srcRootPaths, null, filter, null, false);
     }
 
-    public ClassCoverage(DataClass clz, String srcRootPaths[], List<JavapClass> javapClasses, MemberFilter filter, boolean anonym) {
+    public ClassCoverage(DataClass clz, String srcRootPaths[], List<JavapClass> javapClasses, MemberFilter filter, AncFilter[] ancFilters, boolean anonym) {
         access = clz.getAccess();
         fullname = clz.getFullname();
         name = clz.getName();
         packagename = clz.getPackageName();
         modulename = clz.getModuleName();
 
+        if (ancFilters != null){
+            for (AncFilter ancFilter : ancFilters){
+                if (ancFilter.accept(clz)){
+                    isInAnc = true;
+                    setAncInfo(ancFilter.getAncReason());
+                    break;
+                }
+            }
+        }
+
         for (DataMethod method : clz.getMethods()) {
             if (filter != null && !filter.accept(clz, method)) {
                 continue;
             }
 
-            MethodCoverage methodCoverage = new MethodCoverage(method);
+            MethodCoverage methodCoverage = null;
+            if (ancFilters != null){
+                for (AncFilter ancFilter : ancFilters){
+                    if (isInAnc || ancFilter.accept(clz, method)){
+                        methodCoverage = new MethodCoverage(method, ancFilters, ancFilter.getAncReason());
+                        methodCoverage.setAncInfo(ancFilter.getAncReason());
+                        break;
+                    }
+                }
+            }
+            if (methodCoverage == null) {
+                methodCoverage = new MethodCoverage(method, ancFilters, null);
+            }
             methodCoverage.setAnonymOn(anonym);
             if (method.getName() != null && method.getName().matches("\\$\\d.*")) {
                 methodCoverage.setInAnonymClass(true);
@@ -337,6 +361,19 @@
         return lineCoverage.isLineCovered(lineNum);
     }
 
+    public boolean isLineInAnc(int lineNum){
+        return lineCoverage.isLineAnc(lineNum);
+    }
+
+    public void setAncInfo(String ancInfo){
+        isInAnc = (ancInfo != null && !ancInfo.isEmpty());
+        this.ancInfo = ancInfo;
+    }
+
+    public String getAncInfo(){
+        return ancInfo;
+    }
+
     /**
      * Returns true if the line with the given number contains java code
      *
@@ -365,30 +402,37 @@
             case CLASS:
                 for (MethodCoverage method : methods) {
                     if (method.count > 0 && (testNumber < 0 || method.isCoveredByTest(testNumber))) {
-                        return new CoverageData(1, 1);
+                        if (isInAnc) {
+                            return new CoverageData(1, 1, 1);
+                        }
+                        return new CoverageData(1, 0, 1);
                     }
                 }
-                return new CoverageData(0, 1);
+                if (isInAnc) {
+                    return new CoverageData(0, 1, 1);
+                }
+                return new CoverageData(0, 0, 1);
             case METHOD:
             case BLOCK:
             case BRANCH:
-                CoverageData covered = new CoverageData(0, 0);
+                CoverageData covered = new CoverageData(0, 0, 0);
                 for (MethodCoverage method : methods) {
                     if (testNumber < 0 || method.isCoveredByTest(testNumber)) {
                         covered.add(method.getData(column, testNumber));
                     } else {
-                        covered.add(new CoverageData(0, method.getData(column, testNumber).getTotal()));
+                        CoverageData mcov = method.getData(column, testNumber);
+                        covered.add(new CoverageData(0, mcov.getAnc() ,mcov.getTotal()));
                     }
                 }
                 return covered;
             case FIELD:
-                covered = new CoverageData(0, 0);
+                covered = new CoverageData(0, 0, 0);
                 for (FieldCoverage field : fields) {
                     covered.add(field.getData(column));
                 }
                 return covered;
             case LINE:
-                return new CoverageData(lineCoverage.getCovered(), lineCoverage.getTotal());
+                return new CoverageData(lineCoverage.getCovered(), lineCoverage.getAnc(), lineCoverage.getTotal());
             default:
                 return new CoverageData();
         }
--- a/src/classes/com/sun/tdk/jcov/report/CoverageData.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/CoverageData.java	Mon Oct 26 14:31:30 2015 +0300
@@ -36,6 +36,7 @@
 
     protected int covered;
     protected int total;
+    protected int anc;
     /**
      * default formatter to use in getFormattedCoverage
      *
@@ -43,13 +44,13 @@
      * @see AbstractCoverage.CoverageFormatter
      * @see AbstractCoverage.PercentFormatter
      */
-    public static final AbstractCoverage.CoverageFormatter defaultFormatter = new AbstractCoverage.PercentFormatter();
+    public static final AbstractCoverage.CoverageANCFormatter defaultFormatter = new AbstractCoverage.PercentFormatter();
 
     /**
      * Creates zero-filled coverage data object
      */
     public CoverageData() {
-        this.covered = this.total = 0;
+        this.covered = this.anc = this.total = 0;
     }
 
     /**
@@ -57,10 +58,26 @@
      *
      * @param covered member hit count
      * @param total total member count
+     * @param anc acceptable non coverage
      */
-    public CoverageData(int covered, int total) {
+    public CoverageData(int covered, int anc, int total) {
         this.covered = covered;
         this.total = total;
+        this.anc = anc;
+    }
+
+    /**
+     * @return acceptable non coverage count
+     */
+    public int getAnc() {
+        return anc;
+    }
+
+    /**
+     * @param anc acceptable non coverage count
+     */
+    public void setAnc(int anc) {
+        this.anc = anc;
     }
 
     /**
@@ -100,6 +117,7 @@
     public CoverageData add(CoverageData data) {
         covered += data.covered;
         total += data.total;
+        anc += data.anc;
         return this;
     }
 
@@ -113,7 +131,11 @@
      * @see AbstractCoverage.PercentFormatter
      */
     public String getFormattedCoverage() {
-        return defaultFormatter.format(this);
+        return getFormattedCoverage(false);
+    }
+
+    public String getFormattedCoverage(boolean withANC) {
+        return defaultFormatter.format(this, withANC);
     }
 
     /**
@@ -128,6 +150,10 @@
         return f.format(this);
     }
 
+    public String getFormattedCoverage(AbstractCoverage.CoverageANCFormatter f, boolean withANC) {
+        return f.format(this, withANC);
+    }
+
     /**
      * @return coverage string in form of "covered/total"
      */
@@ -136,6 +162,11 @@
         if (total == 0) {
             return "-";
         }
-        return String.format("%d/%d", covered, total);
+
+        if (anc == 0){
+            return String.format("%d/%d", covered, total);
+        }
+
+        return String.format("%d/%d/%d", covered, anc, total);
     }
 }
--- a/src/classes/com/sun/tdk/jcov/report/FieldCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/FieldCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -84,7 +84,7 @@
     public CoverageData getData(DataType column, int testNumber) {
         switch (column) {
             case FIELD:
-                return new CoverageData(count > 0 ? 1 : 0, 1);
+                return new CoverageData(count > 0 ? 1 : 0, 0, 1);
             default:
                 return new CoverageData();
         }
--- a/src/classes/com/sun/tdk/jcov/report/ItemCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/ItemCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -112,6 +112,8 @@
     protected long count;
     private int srcLine = -1;
     protected Scale scale;
+    protected boolean isInAnc = false;
+    protected String ancInfo;
 
     protected ItemCoverage(int startLine, int endLine, long count, Scale scale) {
         this.startLine = startLine;
@@ -120,6 +122,19 @@
         this.scale = scale;
     }
 
+    public boolean isInAnc() {
+        return isInAnc;
+    }
+
+    public void setAncInfo(String ancInfo){
+        isInAnc = true;
+        this.ancInfo = ancInfo;
+    }
+
+    public String getAncInfo(){
+        return ancInfo;
+    }
+
     protected void setSrcLine(int srcLine) {
         this.srcLine = srcLine;
     }
@@ -219,7 +234,11 @@
         public CoverageData getData(DataType column, int testNumber) {
             switch (column) {
                 case BLOCK:
-                    return new CoverageData(count == 0 ? 0 : 1, 1);
+                    int value = count == 0 ? 0 : 1;
+                    if (isInAnc){
+                        return new CoverageData(value, 1 - value, 1);
+                    }
+                    return new CoverageData(value, 0, 1);
                 default:
                     return new CoverageData();
             }
@@ -268,7 +287,11 @@
         public CoverageData getData(DataType column, int testNumber) {
             switch (column) {
                 case BRANCH:
-                    return new CoverageData(count == 0 ? 0 : 1, 1);
+                    int value = count == 0 ? 0 : 1;
+                    if (isInAnc){
+                        return new CoverageData(value, 1 - value, 1);
+                    }
+                    return new CoverageData(value, 0, 1);
                 default:
                     return new CoverageData();
             }
--- a/src/classes/com/sun/tdk/jcov/report/LineCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/LineCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -37,6 +37,7 @@
 public class LineCoverage extends CoverageData {
 
     final HashMap<Long, Boolean> lines_hits = new HashMap<Long, Boolean>();
+    final HashMap<Long, Boolean> lines_ancs = new HashMap<Long, Boolean>();
 
     public LineCoverage() {
     }
@@ -53,6 +54,12 @@
 
     }
 
+    public boolean isLineAnc(long lineNum) {
+        Boolean isAnc = lines_ancs.get(lineNum);
+        return isAnc != null && isAnc.booleanValue();
+
+    }
+
     /**
      * Return true if the line with the given number contains java code
      *
@@ -75,6 +82,7 @@
         for (LineEntry le : lineTable) {
             ++total;
             lines_hits.put((long) le.line, false);
+            lines_ancs.put((long) le.line, false);
         }
     }
 
@@ -94,6 +102,34 @@
         }
     }
 
+    public void markLineAnc(long line) {
+        Boolean isAnc = lines_ancs.get(line);
+        if (isAnc != null) {
+            boolean was = lines_ancs.put(line, true);
+            if (!was){
+                ++anc;
+            }
+        }
+    }
+
+    private void markLineAnc(long line, boolean isAnc) {
+        Boolean wasAnc = lines_ancs.get(line);
+        if (wasAnc != null) {
+            if (!wasAnc && isAnc) {
+                ++anc;
+            } else if (wasAnc && !isAnc) {
+                --anc;
+            }
+            lines_ancs.put(line, isAnc || wasAnc);
+        }
+        else{
+            if (isAnc && !isLineCovered(line)) {
+                ++anc;
+            }
+            lines_ancs.put(line, isAnc);
+        }
+    }
+
     private void hitLine(long line, boolean isHit) {
         Boolean wasHit = lines_hits.get(line);
         if (wasHit != null) {
@@ -121,6 +157,10 @@
         for (long line : lineCov.lines_hits.keySet()) {
             hitLine(line, lineCov.lines_hits.get(line));
         }
+
+        for (long line : lineCov.lines_ancs.keySet()) {
+            markLineAnc(line, lineCov.lines_ancs.get(line));
+        }
     }
 
     /**
--- a/src/classes/com/sun/tdk/jcov/report/MethodCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/MethodCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -57,14 +57,20 @@
     private boolean inAnonymClass = false;
     private boolean anonymon = false;
     private DataType[] supportedColumns = {METHOD, BLOCK, BRANCH, LINE};
+    private boolean isInAnc = false;
+    protected static String ancInfo;
 
     /**
      * <p> Creates new MethodCoverage instance without counting blocks </p>
      *
      * @param method DataMethod to read data from
      */
-    public MethodCoverage(DataMethod method) {
-        this(method, false);
+    public MethodCoverage(DataMethod method, AncFilter[] ancFilters, String ancReason) {
+        this(method, false, ancFilters, ancReason);
+    }
+
+    public MethodCoverage(DataMethod method, boolean countBlocks) {
+        this(method, countBlocks, null, null);
     }
 
     /**
@@ -73,18 +79,21 @@
      * @param method
      * @param countBlocks not used
      */
-    public MethodCoverage(DataMethod method, boolean countBlocks) {
+    public MethodCoverage(DataMethod method, boolean countBlocks,  AncFilter[] ancFilters, String ancReason) {
         modifiers = Arrays.deepToString(method.getAccessFlags());
         name = method.getName();
         scale = method.getScale();
         signature = method.getVmSignature();
         access = method.getAccess();
+        isInAnc = ancReason != null;
+        ancInfo = ancReason;
+
         if (signature == null) {
             signature = "";
         }
         count = method.getCount();
 
-        detectItems(method, items);
+        detectItems(method, items, isInAnc, ancFilters);
 
         List<LineEntry> lineTable = method.getLineTable();
         if (lineTable != null) {
@@ -98,6 +107,11 @@
                         if (item.count > 0) {
                             lineCoverage.hitLine(le.line);
                         }
+                        else {
+                            if (isInAnc || item.isInAnc()) {
+                                lineCoverage.markLineAnc(le.line);
+                            }
+                        }
                         if (item.getSourceLine() < 0) { // not set yet
                             item.setSrcLine(le.line);
                         }
@@ -107,6 +121,18 @@
         }
     }
 
+    private static String isBlockInAnc(DataMethod m, DataBlock b , AncFilter[] filters){
+        if (filters == null){
+            return null;
+        }
+        for (AncFilter filter : filters){
+            if (filter.accept(m , b)){
+                return filter.getAncReason();
+            }
+        }
+        return null;
+    }
+
     public void setAnonymOn(boolean anonym) {
         this.anonymon = anonym;
     }
@@ -122,7 +148,7 @@
     /**
      * Finds coverage items in terms of legacy jcov (blocks and branches)
      */
-    static void detectItems(DataMethod m, List<ItemCoverage> list) {
+    static void detectItems(DataMethod m, List<ItemCoverage> list, boolean isInAnc, AncFilter[] ancFilters) {
         Map<DataBlock, ItemCoverage> added = new HashMap<DataBlock, ItemCoverage>();
 
         for (DataBlock db : m.getBlocks()) {
@@ -136,6 +162,12 @@
             } else {
                 item = ItemCoverage.createBranchCoverageItem(db.startBCI(), db.endBCI(), db.getCount(), db.getScale());
             }
+
+            String ancReason = isBlockInAnc(m, db, ancFilters);
+            if (isInAnc || ancReason != null){
+                item.setAncInfo(ancInfo != null ? ancInfo : ancReason);
+            }
+
             boolean isNew = true;
             for (DataBlock d : added.keySet()) {
                 if (d.startBCI() == db.startBCI() && type(d) == type(db) && added.get(d).isBlock()) {
@@ -160,6 +192,12 @@
             } else {
                 item = ItemCoverage.createBranchCoverageItem(db.startBCI(), db.endBCI(), db.getCount(), db.getScale());
             }
+
+            String ancReason = isBlockInAnc(m, db, ancFilters);
+            if (isInAnc || ancReason != null){
+                item.setAncInfo(ancInfo != null ? ancInfo : ancReason);
+            }
+
             boolean isNew = true;
             for (DataBlock d : added.keySet()) {
                 if (d.startBCI() == db.startBCI() && type(d) == type(db) && added.get(d).isBlock()) {
@@ -178,6 +216,12 @@
             ItemCoverage i = added.get(db);
             if (!i.isBlock()) {
                 ItemCoverage i2 = ItemCoverage.createBlockCoverageItem(i.startLine, i.endLine, i.count, db.getScale());
+
+                String ancReason = isBlockInAnc(m, db, ancFilters);
+                if (isInAnc || ancReason != null){
+                    i2.setAncInfo(ancInfo != null ? ancInfo : ancReason);
+                }
+
                 boolean isNew = true;
                 for (DataBlock d : added.keySet()) {
                     if (d.startBCI() == db.startBCI() && added.get(d).isBlock()) {
@@ -194,6 +238,15 @@
         }
     }
 
+    public void setAncInfo(String ancInfo){
+        isInAnc = (ancInfo != null && !ancInfo.isEmpty());
+        this.ancInfo = ancInfo;
+    }
+
+    public String getAncInfo(){
+        return ancInfo;
+    }
+
     /**
      * Detects type of the DataBlock
      *
@@ -281,21 +334,35 @@
             case METHOD:
 
                 if (inAnonymClass && !anonymon) {
-                    return new CoverageData(0, 0);
+                    return new CoverageData(0, 0, 0);
                 }
 
                 if (testNumber > -1) {
-                    return new CoverageData((count > 0 && isCoveredByTest(testNumber)) ? 1 : 0, 1);
+                    int c = (count > 0 && isCoveredByTest(testNumber)) ? 1 : 0;
+                    if (isInAnc) {
+                        return new CoverageData(c, 1 - c, 1);
+                    }
+                    return new CoverageData(c, 0, 1);
                 }
-                return new CoverageData(count > 0 ? 1 : 0, 1);
+                int c = count > 0 ? 1 : 0;
+                if (isInAnc) {
+                    return new CoverageData(c, 1 - c, 1);
+                }
+                return new CoverageData(c, 0, 1);
             case BLOCK:
             case BRANCH:
-                CoverageData result = new CoverageData(0, 0);
+                CoverageData result = new CoverageData(0, 0, 0);
                 for (ItemCoverage item : items) {
                     if (testNumber < 0 || item.isCoveredByTest(testNumber)) {
                         result.add(item.getData(column));
                     } else {
-                        result.add(new CoverageData(0, item.getData(column).getTotal()));
+                        CoverageData icov = item.getData(column);
+                        if (isInAnc){
+                            result.add(new CoverageData(0, 1, icov.getTotal()));
+                        }
+                        else {
+                            result.add(new CoverageData(0, icov.getAnc(), icov.getTotal()));
+                        }
                     }
                 }
                 return result;
--- a/src/classes/com/sun/tdk/jcov/report/PackageCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/PackageCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -59,17 +59,17 @@
      * @param srcRoots Paths for sources
      * @param filter Allows to filter read data
      */
-    public PackageCoverage(DataRoot fileImage, String name, String srcRoots[], ProductCoverage.CoverageFilter filter) {
-        this(fileImage, name, srcRoots, null, filter);
+    public PackageCoverage(DataRoot fileImage, String name, String srcRoots[], ProductCoverage.CoverageFilter filter,  AncFilter[] ancfilters) {
+        this(fileImage, name, srcRoots, null, filter, ancfilters);
     }
 
-    public PackageCoverage(DataRoot fileImage, String name, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter) {
-        this(fileImage, name, srcRoots, null, filter, false);
+    public PackageCoverage(DataRoot fileImage, String name, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter, AncFilter[] ancfilters) {
+        this(fileImage, name, srcRoots, null, filter, ancfilters, false);
     }
 
-    public PackageCoverage(DataRoot fileImage, String name, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter, boolean anonym) {
+    public PackageCoverage(DataRoot fileImage, String name, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter, AncFilter[] ancfilters, boolean anonym) {
         this.name = name;
-        classCoverageList = _getClassCoverageList(fileImage, srcRoots, javapClasses, filter, anonym);
+        classCoverageList = _getClassCoverageList(fileImage, srcRoots, javapClasses, filter, ancfilters, anonym);
         if (classCoverageList != null) {
             java.util.Collections.sort(classCoverageList);
         }
@@ -82,11 +82,11 @@
         return classCoverageList;
     }
 
-    private List<ClassCoverage> _getClassCoverageList(DataRoot fileImage, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter, boolean anonym) {
+    private List<ClassCoverage> _getClassCoverageList(DataRoot fileImage, String srcRoots[], List<JavapClass> javapClasses, ProductCoverage.CoverageFilter filter, AncFilter[] ancfilters, boolean anonym) {
         List<ClassCoverage> result = new ArrayList<ClassCoverage>();
         DataPackage pkg = fileImage.findPackage(name, "");
         for (DataClass cls : pkg.getClasses()) {
-            ClassCoverage cc = new ClassCoverage(cls, srcRoots, javapClasses, filter, anonym);
+            ClassCoverage cc = new ClassCoverage(cls, srcRoots, javapClasses, filter, ancfilters, anonym);
             if (filter == null || filter.accept(cc)) {
                 result.add(cc);
             }
@@ -146,7 +146,7 @@
                     if (testNumber < 0 || classCoverage.isCoveredByTest(testNumber)) {
                         covered.add(classCoverage.getData(column, testNumber));
                     } else {
-                        covered.add(new CoverageData(0, classCoverage.getData(column, testNumber).getTotal()));
+                        covered.add(new CoverageData(0, 0, classCoverage.getData(column, testNumber).getTotal()));
                     }
                 }
                 return covered;
--- a/src/classes/com/sun/tdk/jcov/report/ProductCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/ProductCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -26,12 +26,9 @@
 
 import com.sun.tdk.jcov.data.FileFormatException;
 import com.sun.tdk.jcov.filter.MemberFilter;
-import com.sun.tdk.jcov.instrument.DataBlock;
-import com.sun.tdk.jcov.instrument.DataBlockTarget;
 import com.sun.tdk.jcov.instrument.DataClass;
 import com.sun.tdk.jcov.instrument.DataField;
 import com.sun.tdk.jcov.instrument.DataMethod;
-import com.sun.tdk.jcov.instrument.DataMethod.LineEntry;
 import com.sun.tdk.jcov.instrument.DataPackage;
 import com.sun.tdk.jcov.instrument.DataRoot;
 import com.sun.tdk.jcov.io.Reader;
@@ -39,7 +36,6 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import org.objectweb.asm.Opcodes;
 
 /**
  * <p> The product coverage container serves for accessing coverage information
@@ -84,6 +80,7 @@
         DataType.BLOCK, DataType.BRANCH, DataType.LINE};
     private ArrayList<ClassCoverage> classes;
     private String productName;
+    private AncFilter[] ancfilters = null;
 
     /**
      * <p> Creates a new instance of ProductCoverage which is the top level
@@ -262,8 +259,16 @@
         this(fileImage, srcRootPaths, javapClasses, new DefaultFilter(noAbstract, isPublicAPI), false, false);
     }
 
+    public ProductCoverage(DataRoot fileImage, String srcRootPaths[], List<JavapClass> javapClasses, boolean isPublicAPI, boolean noAbstract, AncFilter[] ancfilters) {
+        this(fileImage, srcRootPaths, javapClasses, new DefaultFilter(noAbstract, isPublicAPI), false, false, ancfilters);
+    }
+
     public ProductCoverage(DataRoot fileImage, String srcRootPaths[], List<JavapClass> javapClasses, boolean isPublicAPI, boolean noAbstract, boolean anonym) {
-        this(fileImage, srcRootPaths, javapClasses, new DefaultFilter(noAbstract, isPublicAPI), false, anonym);
+        this(fileImage, srcRootPaths, javapClasses, new DefaultFilter(noAbstract, isPublicAPI), false, anonym, null);
+    }
+
+    public ProductCoverage(DataRoot fileImage, String srcRootPaths[], List<JavapClass> javapClasses, boolean isPublicAPI, boolean noAbstract, boolean anonym, AncFilter[] ancfilters) {
+        this(fileImage, srcRootPaths, javapClasses, new DefaultFilter(noAbstract, isPublicAPI), false, anonym, ancfilters);
     }
 
     /**
@@ -288,6 +293,9 @@
         this(fileImage, srcRootPaths, null, filter, false, false);
     }
 
+    public ProductCoverage(DataRoot fileImage, String srcRootPaths[], List<JavapClass> javapClasses, CoverageFilter filter, boolean releaseAfter, boolean anonym){
+        this(fileImage, srcRootPaths, null, filter, false, false, null);
+    }
     /**
      * <p> Creates a new instance of ProductCoverage which is the top level
      * coverage object in the coverage objects tree. </p> <p> Note that empty
@@ -304,12 +312,13 @@
      * @see DataRoot
      * @see DataRoot#read(java.lang.String)
      */
-    public ProductCoverage(DataRoot fileImage, String srcRootPaths[], List<JavapClass> javapClasses, CoverageFilter filter, boolean releaseAfter, boolean anonym) {
+    public ProductCoverage(DataRoot fileImage, String srcRootPaths[], List<JavapClass> javapClasses, CoverageFilter filter, boolean releaseAfter, boolean anonym, AncFilter[] ancfilters) {
         packages = new ArrayList<PackageCoverage>();
         classes = new ArrayList<ClassCoverage>();
         if (filter == null) {
             filter = new DefaultFilter(false, false);
         }
+        this.ancfilters = ancfilters;
 
         List<DataPackage> packs = fileImage.getPackages();
         ArrayList<String> packageNames = new ArrayList<String>(packs.size());
@@ -319,7 +328,7 @@
         java.util.Collections.sort(packageNames);
 
         for (String pkg : packageNames) {
-            PackageCoverage pc = new PackageCoverage(fileImage, pkg, srcRootPaths, javapClasses, filter, anonym);
+            PackageCoverage pc = new PackageCoverage(fileImage, pkg, srcRootPaths, javapClasses, filter, ancfilters, anonym);
             List<ClassCoverage> pkgClasses = pc.getClasses();
             classes.addAll(pkgClasses);
             if (filter.accept(pc)) {
@@ -332,6 +341,14 @@
         }
     }
 
+    /**
+     * Determine if the ANC filters were set
+     * @return
+     */
+    public boolean isAncFiltersSet(){
+        return ancfilters != null;
+    }
+
     private static DataRoot readFileImage(String filename, boolean useScales)
             throws FileFormatException {
         return Reader.readXML(filename, useScales, null);
@@ -381,7 +398,7 @@
     }
 
     public CoverageData getData(DataType column, int testNumber) {
-        CoverageData covered = new CoverageData(0, 0);
+        CoverageData covered = new CoverageData(0, 0, 0);
         switch (column) {
             case PACKAGE:
                 for (PackageCoverage pCoverage : packages) {
@@ -398,7 +415,7 @@
                     if (testNumber < 0 || classCoverage.isCoveredByTest(testNumber)) {
                         covered.add(classCoverage.getData(column));
                     } else {
-                        covered.add(new CoverageData(0, classCoverage.getData(column).getTotal()));
+                        covered.add(new CoverageData(0, 0, classCoverage.getData(column).getTotal()));
                     }
                 }
                 return covered;
--- a/src/classes/com/sun/tdk/jcov/report/ReportGenerator.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/ReportGenerator.java	Mon Oct 26 14:31:30 2015 +0300
@@ -93,6 +93,10 @@
         private InstrumentationOptions.InstrumentationMode mode;
         private boolean anonym = false;
 
+        private String mainReportTitle = null;
+        private String overviewListTitle = null;
+        private String entitiesTitle = null;
+
         /**
          * Creates empty Options
          */
@@ -110,6 +114,19 @@
          * @param testListService STS object
          */
         public Options(String srcRootPath, SmartTestService testListService, List<JavapClass> classes, boolean withTestInfo, boolean mergeRepGenMode) {
+            this(srcRootPath, testListService, classes, withTestInfo, mergeRepGenMode,
+                    null, null, null);
+        }
+
+        /**
+         * Creates Options instance
+         *
+         * @param srcRootPath Path to the sources (divided by
+         * File.pathSeparator)
+         * @param testListService STS object
+         */
+        public Options(String srcRootPath, SmartTestService testListService, List<JavapClass> classes, boolean withTestInfo, boolean mergeRepGenMode,
+                       String mainTitle, String overviewTitle, String entitiesTitle) {
             this.withTestsInfo = withTestInfo;
             this.mergeRepGenMode = mergeRepGenMode;
             this.classes = classes;
@@ -120,6 +137,10 @@
             } else {
                 this.srcRootPaths = null;
             }
+            this.mainReportTitle = mainTitle;
+            this.overviewListTitle = overviewTitle;
+            this.entitiesTitle = entitiesTitle;
+
         }
 
         public List<JavapClass> getJavapClasses() {
@@ -205,5 +226,17 @@
         public boolean isAnonymOn() {
             return anonym;
         }
+
+        public String getMainReportTitle() {
+            return mainReportTitle;
+        }
+
+        public String getOverviewListTitle() {
+            return overviewListTitle;
+        }
+
+        public String getEntitiesTitle() {
+            return entitiesTitle;
+        }
     }
 }
\ No newline at end of file
--- a/src/classes/com/sun/tdk/jcov/report/SubpackageCoverage.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/SubpackageCoverage.java	Mon Oct 26 14:31:30 2015 +0300
@@ -37,16 +37,22 @@
 public class SubpackageCoverage extends AbstractCoverage {
 
     private int class_cov = 0;
+    private int class_anc = 0;
     private int class_tot = 0;
     private int meth_cov = 0;
+    private int meth_anc = 0;
     private int meth_tot = 0;
     private int field_cov = 0;
+    private int field_anc = 0;
     private int field_tot = 0;
     private int block_cov = 0;
+    private int block_anc = 0;
     private int block_tot = 0;
     private int branch_cov = 0;
+    private int branch_anc = 0;
     private int branch_tot = 0;
     private int line_cov = 0;
+    private int line_anc = 0;
     private int line_tot = 0;
 
     public SubpackageCoverage() {
@@ -60,21 +66,27 @@
     public void add(AbstractCoverage cov) {
         CoverageData d = cov.getData(CLASS);
         class_cov += d.getCovered();
+        class_anc += d.getAnc();
         class_tot += d.getTotal();
         d = cov.getData(METHOD);
         meth_cov += d.getCovered();
+        meth_anc += d.getAnc();
         meth_tot += d.getTotal();
         d = cov.getData(FIELD);
         field_cov += d.getCovered();
+        field_anc += d.getAnc();
         field_tot += d.getTotal();
         d = cov.getData(BLOCK);
         block_cov += d.getCovered();
+        block_anc += d.getAnc();
         block_tot += d.getTotal();
         d = cov.getData(BRANCH);
         branch_cov += d.getCovered();
+        branch_anc += d.getAnc();
         branch_tot += d.getTotal();
         d = cov.getData(LINE);
         line_cov += d.getCovered();
+        line_anc += d.getAnc();
         line_tot += d.getTotal();
     }
     private DataType[] supportedColumns = {CLASS, METHOD, FIELD,
@@ -93,17 +105,17 @@
     public CoverageData getData(DataType column, int testNumber) {
         switch (column) {
             case CLASS:
-                return new CoverageData(class_cov, class_tot);
+                return new CoverageData(class_cov, class_anc, class_tot);
             case METHOD:
-                return new CoverageData(meth_cov, meth_tot);
+                return new CoverageData(meth_cov, meth_anc, meth_tot);
             case FIELD:
-                return new CoverageData(field_cov, field_tot);
+                return new CoverageData(field_cov, field_anc, field_tot);
             case BLOCK:
-                return new CoverageData(block_cov, block_tot);
+                return new CoverageData(block_cov, block_anc, block_tot);
             case BRANCH:
-                return new CoverageData(branch_cov, branch_tot);
+                return new CoverageData(branch_cov, branch_anc, branch_tot);
             case LINE:
-                return new CoverageData(line_cov, line_tot);
+                return new CoverageData(line_cov, line_anc, line_tot);
             default:
                 return new CoverageData();
         }
--- a/src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/html/CoverageReport.java	Mon Oct 26 14:31:30 2015 +0300
@@ -25,6 +25,7 @@
 package com.sun.tdk.jcov.report.html;
 
 import com.sun.tdk.jcov.instrument.InstrumentationOptions;
+import com.sun.tdk.jcov.instrument.XmlNames;
 import com.sun.tdk.jcov.report.*;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -68,6 +69,9 @@
     private boolean isMergeRepGenMode = false;
     private boolean isAnonymOn = false;
     private String title = "Coverage report";
+    private String mainReportTitle;
+    private String overviewListTitle;
+    private String entitiesTitle;
     private String dir;
     private boolean showLines;
     private boolean showFields;
@@ -106,6 +110,9 @@
         }
         this.setInstrMode(options.getInstrMode());
         this.isAnonymOn = options.isAnonymOn();
+        mainReportTitle = options.getMainReportTitle() == null ? "Coverage report" : options.getMainReportTitle();
+        overviewListTitle = options.getOverviewListTitle() == null ? "Coverage report" : options.getOverviewListTitle();
+        entitiesTitle = options.getEntitiesTitle() == null ? "Coverage report" : options.getEntitiesTitle();
 
         setGenSrc4Zero(true);
         generate();
@@ -120,7 +127,7 @@
         generatePackageList(directory);
         generateClassList(directory);
         HashMap<String, CoverageData[]> modules = getModulesCoverage();
-        if (modules == null || (modules.size() == 1 && "no_module".equals(modules.keySet().iterator().next()))){
+        if (modules == null || (modules.size() == 1 && XmlNames.NO_MODULE.equals(modules.keySet().iterator().next()))){
             modules = null;
         }
         generateOverview(directory, modules);
@@ -240,7 +247,7 @@
                 .println("<link rel =\"stylesheet\" type=\"text/css\" href=\"style.css\" title=\"Style\">");
         pw.println("</head>");
         pw.println("<body>");
-        pw.println("<span class=\"title\">" + title + "</span><br>");
+        pw.println("<span class=\"title\">" + overviewListTitle + "</span><br>");
         // pw.println("<span class=\"title2\">" + coverage.getData(ColumnName.PRODUCT)
         //    + "</span>");
         pw.println("<table>");
@@ -325,7 +332,7 @@
         if (pkg != null) {
             pw.println("<a href=\"package-summary.html\" target=\"classFrame\">"
                     + pkg.getName() + "</a> "
-                    + "<span class=\"text_italic\">&nbsp;" + pkg.getCoverageString(DataType.METHOD)
+                    + "<span class=\"text_italic\">&nbsp;" + pkg.getCoverageString(DataType.METHOD, coverage.isAncFiltersSet())
                     + "</span><br>");
             pw.println("<p>");
         }
@@ -339,7 +346,7 @@
             logger.log(Level.INFO, "{0} generateClassList:theClass:{1}", new Object[]{++i, theClass.getName()});
             String prc = showFields
                     ? theClass.getData(DataType.METHOD).add(theClass.getData(DataType.FIELD)).toString()
-                    : theClass.getCoverageString(DataType.METHOD);
+                    : theClass.getCoverageString(DataType.METHOD, coverage.isAncFiltersSet());
 
             if (pkg == null) {
                 if (theClass.getFullClassName().lastIndexOf('.') > 0) {
@@ -395,7 +402,7 @@
                 + "sorttable.js\"></script>");
         pw.println("</head>");
         pw.println("<body>");
-        pw.println("<span class=\"title\"> <b>" + title + " "
+        pw.println("<span class=\"title\"> <b>" + entitiesTitle + " "
                 + /*coverage.getData(ColumnName.PRODUCT) + */ "</b> </span>");
         pw.println("<p>");
 
@@ -448,7 +455,7 @@
                         pw.println("<td class=\"reportValue\">"
                                 + pkg.getData(DataType.CLASS).getTotal() + "</td>");
                         pw.println("<td class=\"reportValue\">"
-                                + decorate(pkg.getCoverageString(DataType.CLASS)) + "</td>");
+                                + decorate(pkg.getCoverageString(DataType.CLASS, coverage.isAncFiltersSet())) + "</td>");
                         printColumnCoverages(pw, pkg, true, "");
                     /*pw.println("<td class=\"reportValue\">"
                      + generatePercentResult(pkg.getTotalCoverageString()) + "</td>");*/
@@ -518,7 +525,8 @@
                 + "sorttable.js\"></script>");
         pw.println("</head>");
         pw.println("<body>");
-        pw.println("<span class=\"title\">" + title + " "
+        String otitle = thePackage == null ? mainReportTitle : entitiesTitle;
+        pw.println("<span class=\"title\">" + otitle + " "
                 + /*coverage.getData(ColumnName.PRODUCT) + */ "</span>");
         pw.println("<p>");
         pw.println("<table class=\"report\" cellpadding=\"0\" cellspacing=\"0\">");
@@ -579,7 +587,7 @@
                     pw.println("<td class=\"reportValue_number\">"
                             + pkg.getData(DataType.CLASS).getTotal() + "</td>");
                     pw.println("<td class=\"reportValue\">"
-                            + decorate(pkg.getCoverageString(DataType.CLASS)) + "</td>");
+                            + decorate(pkg.getCoverageString(DataType.CLASS, coverage.isAncFiltersSet())) + "</td>");
                     printColumnCoverages(pw, pkg, true, "");
                     /*pw.println("<td class=\"reportValue\">"
                      + generatePercentResult(pkg.getTotalCoverageString()) + "</td>");*/
@@ -703,14 +711,15 @@
             pw.println("<td class=\"reportValue_number\">"
                     + modules.get(module)[0].getTotal() + "</td>");
             for (int i = 1; i< modules.get(module).length; i++) {
-                CoverageData cd = modules.get(module)[i];
-                if (!decorate) {
-                    pw.println("<td class=\"reportValue\">"
-                            + decorate(cd.getFormattedCoverage()) + "</td>");
-                }
-                else{
-                    pw.println("<td class=\"reportValue\">"
-                            +generatePercentResult(cd.getFormattedCoverage()) + "</td>");
+                if (show(columns.valueOf(i))) {
+                    CoverageData cd = modules.get(module)[i];
+                    if (!decorate) {
+                        pw.println("<td class=\"reportValue\">"
+                                + decorate(cd.getFormattedCoverage(coverage.isAncFiltersSet())) + "</td>");
+                    } else {
+                        pw.println("<td class=\"reportValue\">"
+                                + generatePercentResult(cd.getFormattedCoverage(coverage.isAncFiltersSet())) + "</td>");
+                    }
                 }
             }
             pw.println("</tr>");
@@ -719,10 +728,27 @@
         pw.println("<p>");
     }
 
-    enum columns {
 
-        method, field, block, branch, line
-    };
+    public enum columns {
+        method(1), field(0), block(2), branch(3), line(4);
+
+        private int number;
+
+        private static Map<Integer, columns> map = new HashMap<Integer, columns>();
+
+        static {
+            for (columns column : columns.values()) {
+                map.put(column.number, column);
+            }
+        }
+
+        public static columns valueOf(int number) {
+            return map.get(number);
+        }
+
+        private columns(final int number) { this.number = number; }
+
+    }
 
     /**
      * Returns true if a column needs to be shown
@@ -755,15 +781,15 @@
     String getColumnData(columns col, AbstractCoverage cc) {
         switch (col) {
             case method:
-                return cc.getCoverageString(DataType.METHOD);
+                return cc.getCoverageString(DataType.METHOD, coverage.isAncFiltersSet());
             case field:
-                return cc.getCoverageString(DataType.FIELD);
+                return cc.getCoverageString(DataType.FIELD, coverage.isAncFiltersSet());
             case block:
-                return cc.getCoverageString(DataType.BLOCK);
+                return cc.getCoverageString(DataType.BLOCK, coverage.isAncFiltersSet());
             case branch:
-                return cc.getCoverageString(DataType.BRANCH);
+                return cc.getCoverageString(DataType.BRANCH, coverage.isAncFiltersSet());
             case line:
-                return cc.getCoverageString(DataType.LINE);
+                return cc.getCoverageString(DataType.LINE, coverage.isAncFiltersSet());
         }
         return "";
     }
@@ -771,13 +797,13 @@
     String getFormattedColumnData(columns col, AbstractCoverage cc, int testNumber) {
         switch (col) {
             case method:
-                return cc.getData(DataType.METHOD, testNumber).getFormattedCoverage();
+                return cc.getData(DataType.METHOD, testNumber).getFormattedCoverage(coverage.isAncFiltersSet());
             case field:
-                return cc.getData(DataType.FIELD, testNumber).getFormattedCoverage();
+                return cc.getData(DataType.FIELD, testNumber).getFormattedCoverage(coverage.isAncFiltersSet());
             case block:
-                return cc.getData(DataType.BLOCK, testNumber).getFormattedCoverage();
+                return cc.getData(DataType.BLOCK, testNumber).getFormattedCoverage(coverage.isAncFiltersSet());
             case branch:
-                return cc.getData(DataType.BRANCH, testNumber).getFormattedCoverage();
+                return cc.getData(DataType.BRANCH, testNumber).getFormattedCoverage(coverage.isAncFiltersSet());
             case line:
                 return "";
         }
@@ -987,7 +1013,7 @@
             }
         }
 
-        generateMemberTable(pw, "method", methodList, isGenerate, theClass.isJavapSource());
+        generateMemberTable(pw, theClass, "method", methodList, isGenerate, theClass.isJavapSource());
 
         List<FieldCoverage> fieldList = theClass.getFields();
         //Collections.sort((List) fieldList);
@@ -998,7 +1024,7 @@
                 methodsForLine.put(new Integer(startLine), fcov);
                 logger.log(Level.FINE, "{0}-{1}", new Object[]{fcov.getName(), startLine});
             }
-            generateMemberTable(pw, "field", fieldList, isGenerate, theClass.isJavapSource());
+            generateMemberTable(pw, theClass, "field", fieldList, isGenerate, theClass.isJavapSource());
         }
 
         if (isGenerate) {
@@ -1058,10 +1084,36 @@
             MemberCoverage mcov = methodsForLine.get(numLine);
             List<ItemCoverage> items = itemsForLine.get(numLine);
             String lineCov = null;
+            String ancInfo = "";
             if (!theClass.isCode(numLine)) {
                 lineCov = "numLine";
             } else {
-                lineCov = theClass.isLineCovered(numLine) ? "numLineCover" : "numLineUnCover";
+                String unCover = theClass.isLineInAnc(numLine) ? "numLineAnc" : "numLineUnCover";
+                lineCov = theClass.isLineCovered(numLine) ? "numLineCover" : unCover;
+                if (theClass.isLineInAnc(numLine) && !theClass.isLineCovered(numLine)) {
+                    if (theClass.getAncInfo() != null){
+                        ancInfo = "title = \"" + theClass.getAncInfo() + "\" ";
+                    }
+                    else if (mcov instanceof MethodCoverage && ((MethodCoverage) mcov).getAncInfo() != null){
+                        ancInfo = "title = \"" + ((MethodCoverage) mcov).getAncInfo() + "\" ";
+                    }
+                    else {
+                        if (items == null) {
+                            int upLine = numLine;
+                            List<ItemCoverage> upItems;
+                            while ((upItems = itemsForLine.get(upLine)) == null) {
+                                upLine--;
+                            }
+                            for (ItemCoverage i : upItems) {
+                                if (i.isInAnc()) {
+                                    ancInfo = "title = \"" + i.getAncInfo() + "\" ";
+                                    break;
+                                }
+                            }
+
+                        }
+                    }
+                }
             }
             String link = "";
 
@@ -1071,6 +1123,7 @@
 
             if (items != null) {
                 int allcovered = 0;
+                int allanc = 0;
                 Map<DataType, Integer> covered = new HashMap();
                 Map<DataType, Integer> total = new HashMap();
                 for (DataType kind : ItemCoverage.getAllPossibleTypes()) {
@@ -1084,6 +1137,9 @@
                         covered.put(kind, covered.get(kind) + 1);
                         allcovered++;
                     }
+                    if (icov.isInAnc()){
+                        allanc++;
+                    }
                 }
 
                 String shortInfo = "";
@@ -1094,8 +1150,46 @@
                 }
                 boolean isGreen = items.size() == allcovered;
 
-                String nbHitsCov = isGreen ? "nbHitsCovered" : "nbHitsUncovered";
-                pw.println(" <td class=\"" + lineCov + "\">&nbsp;" + numLine + link
+                String nbHitsCov = isGreen ? "nbHitsCovered" : items.size() == allanc ? "nbHitsAnc" : "nbHitsUncovered";
+                ancInfo = "";
+
+                if (!theClass.isLineCovered(numLine)){
+                    if (items.size() == allanc) {
+                        lineCov = "numLineAnc";
+                        if (theClass.getAncInfo() != null){
+                            ancInfo = "title = \"" + theClass.getAncInfo() + "\" ";
+                        }
+                        else if (mcov instanceof MethodCoverage && ((MethodCoverage) mcov).getAncInfo() != null){
+                            ancInfo = "title = \"" + ((MethodCoverage) mcov).getAncInfo() + "\" ";
+                        }
+                        else{
+                            ancInfo = "title = \"" + items.get(0).getAncInfo() + "\" ";
+                        }
+                    }
+                }
+                else{
+                    ancInfo = "";
+
+                    for (ItemCoverage i : items) {
+                        if (!i.isCovered()) {
+                            if (theClass.getAncInfo() != null){
+                                ancInfo = "title = \"" + theClass.getAncInfo() + "\" ";
+                                break;
+                            }
+                            else if (mcov instanceof MethodCoverage && ((MethodCoverage) mcov).getAncInfo() != null){
+                                ancInfo = "title = \"" + ((MethodCoverage) mcov).getAncInfo() + "\" ";
+                                break;
+                            }
+                            else if (i.isInAnc() && i.getAncInfo() != null){
+                                ancInfo = "title = \"" + i.getAncInfo() + "\" ";
+                                break;
+                            }
+                        }
+                    }
+
+                }
+
+                pw.println(" <td "+ancInfo+"class=\"" + lineCov + "\">&nbsp;" + numLine + link
                         + "</td>");
 
                 if (isMergeRepGenMode) {
@@ -1124,13 +1218,17 @@
                     Iterator<Test> iterator = testService.iterator();
                     while (iterator.hasNext()) {
                         Test test = iterator.next();
-                        String testCovered = "numLineUnCover";
+                        String testCovered = theClass.isLineInAnc(numLine) ? "numLineAnc" : "numLineUnCover";
                         int block = 0;
                         int branch = 0;
                         boolean blocks = false;
                         boolean branches = false;
                         for (ItemCoverage item : itemsForLine.get(numLine)) {
 
+                            if (item.isInAnc()){
+                                testCovered = "numLineAnc";
+                            }
+
                             if (!blocks && item.isBlock()) {
                                 blocks = true;
                             }
@@ -1173,7 +1271,7 @@
                 // just string without any items
             } else {
 
-                pw.println(" <td class=\"" + lineCov + "\">&nbsp;" + numLine + link + "</td>");
+                pw.println(" <td "+ancInfo+"class=\"" + lineCov + "\">&nbsp;" + numLine + link + "</td>");
                 pw.println(" <td class=\"nbHits\">&nbsp;</td>");
                 if (testService != null && (isAddTestsInfo || isMergeRepGenMode)) {
 
@@ -1181,7 +1279,8 @@
 
                         if (theClass.isCode(numLine)) {
 
-                            String testCovered = "numLineUnCover";
+                            String testCovered = theClass.isLineInAnc(numLine) ? "numLineAnc" : "numLineUnCover";
+                            ancInfo = "";
 
                             if (theClass.isLineCovered(numLine)) {
                                 for (int i = numLine; i >= 0; i--) {
@@ -1190,14 +1289,19 @@
                                             if (item.isCoveredByTest(k)) {
                                                 testCovered = "numLineCover";
                                             }
+                                            else{
+                                                if (item.isInAnc()){
+                                                    testCovered = "numLineAnc";
+                                                    ancInfo = "title = \""+item.getAncInfo()+"\" ";
+                                                }
+                                            }
                                         }
                                         break;
                                     }
                                 }
 
                             }
-
-                            pw.println(" <td class=\"" + testCovered + "\">&nbsp;</td>");
+                            pw.println(" <td " + ancInfo + "class=\"" + testCovered + "\">&nbsp;</td>");
 
                         } else {
                             pw.println(" <td class=\"nbHits\">&nbsp;</td>");
@@ -1227,7 +1331,8 @@
 
                 boolean isGreen = ((JavapCodeLine) javapLine).isVisited();
 
-                String nbHitsCov = isGreen ? "nbHitsCovered" : "nbHitsUncovered";
+                String unCover = theClass.isLineInAnc(numLine) ? "nbHitsAnc" : "nbHitsUncovered";
+                String nbHitsCov = isGreen ? "nbHitsCovered" :  unCover;
                 String htmlStr = javapLine.getTextLine().replaceAll("\\<", "&#60;").replaceAll("\\>", "&#62;");
 
                 pw.println(" <td>" + numLine + link + "</td>");
@@ -1246,7 +1351,7 @@
 
     }
 
-    private void generateMemberTable(PrintWriter pw, String fieldOrMethod,
+    private void generateMemberTable(PrintWriter pw, ClassCoverage theClass, String fieldOrMethod,
             List<? extends MemberCoverage> list, boolean isGenerate, boolean javapReport) {
         pw.println(" <p>");
         pw.println(" <table cellspacing=\"0\" cellpadding=\"0\"class=\"report\" id=\"mcoverage\">");
@@ -1277,8 +1382,24 @@
                 pw.println(" <td class=\"reportValue_covered\"><span class=\"text\">"
                         + c + "</span></td>");
             } else {
-                pw.println(" <td class=\"reportValue_uncovered\"><span class=\"text\">"
-                        + c + "</span></td>");
+                if (mcov.getData(mcov.getDataType()).getAnc() > 0){
+
+                    String tooltip = "";
+                    if (mcov instanceof MethodCoverage){
+                        String info = theClass.getAncInfo();
+                        if (info == null){
+                            info = ((MethodCoverage)mcov).getAncInfo() != null ? ((MethodCoverage)mcov).getAncInfo() :
+                                    ((MethodCoverage)mcov).getItems().get(0).getAncInfo();
+                        }
+                        tooltip = "title=\"" + info + "\" ";
+                    }
+                    pw.println(" <td class=\"reportValue_anc\""+tooltip+"><span class=\"text\">"
+                            + c + "</span></td>");
+                }
+                else {
+                    pw.println(" <td class=\"reportValue_uncovered\"><span class=\"text\">"
+                            + c + "</span></td>");
+                }
             }
 
             if (testService != null && (isAddTestsInfo || isMergeRepGenMode)) {
@@ -1288,8 +1409,24 @@
                         pw.println(" <td class=\"numLineCover\"><span class=\"text\">"
                                 + "<center>+</center>" + "</span></td>");
                     } else {
-                        pw.println(" <td class=\"numLineUnCover\"><span class=\"text\">"
-                                + "<center>-</center>" + "</span></td>");
+
+                        if (mcov.getData(mcov.getDataType()).getAnc() > 0){
+                            String tooltip = "";
+                            if (mcov instanceof MethodCoverage){
+                                String info = theClass.getAncInfo();
+                                if (info == null){
+                                    info = ((MethodCoverage)mcov).getAncInfo() != null ? ((MethodCoverage)mcov).getAncInfo() :
+                                            ((MethodCoverage)mcov).getItems().get(0).getAncInfo();
+                                }
+                                tooltip = "title=\"" + info + "\" ";
+                            }
+                            pw.println(" <td class=\"numLineAnc\" "+tooltip+"><span class=\"text\">"
+                                    + "<center>-</center>" + "</span></td>");
+                        }
+                        else {
+                            pw.println(" <td class=\"numLineUnCover\"><span class=\"text\">"
+                                    + "<center>-</center>" + "</span></td>");
+                        }
                     }
                 }
             }
@@ -1450,16 +1587,28 @@
     private String generatePercentResult(String percentValue) {
         String value = percentValue;
         String cov_total = "";
+        double anc = 0;
         int idx = value.indexOf("%");
         if (idx != -1) {
             value = value.substring(0, idx);
             cov_total = percentValue.substring(idx + 1);
+            String[] ancs = percentValue.split("/");
+            if (ancs.length == 3){
+                try {
+                    anc = Double.parseDouble(ancs[1])/Double.parseDouble(ancs[2].substring(0,ancs[2].indexOf(")")))*100;
+                }
+                catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
         }
 
         double rest = 0;
         boolean badNumber = false;
+        double dvalue = 0;
         try {
-            rest = 100d - new Double(value.replace(',', '.')).doubleValue();
+            dvalue = new Double(value.replace(',', '.')).doubleValue();
+            rest = 100d - (dvalue);
         } catch (NumberFormatException e) {
             badNumber = true;
         }
@@ -1473,8 +1622,17 @@
             sb.append("<td>");
             sb.append("<table class=\"percentGraph\" cellpadding=\"0\" cellspacing=\"0\">");
             sb.append("<tr>");
-            sb.append("<td class=\"percentCovered\" width=\"").append(value).append("\"></td>");
-            sb.append("<td class=\"percentUnCovered\" width=\"").append(String.valueOf(rest)).append("\"></td>");
+            if (anc > 0) {
+                sb.append("<td class=\"percentCovered\" width=\"").append(dvalue - anc).append("\"></td>");
+                sb.append("<td class=\"percentAnc\" width=\"").append(anc).append("\"></td>");
+                if (dvalue < 100) {
+                    sb.append("<td class=\"percentUnCovered\" width=\"").append(String.valueOf(rest)).append("\"></td>");
+                }
+            }
+            else{
+                sb.append("<td class=\"percentCovered\" width=\"").append(value).append("\"></td>");
+                sb.append("<td class=\"percentUnCovered\" width=\"").append(String.valueOf(rest)).append("\"></td>");
+            }
             sb.append("</tr>");
             sb.append("</table>");
             sb.append("</td>");
--- a/src/classes/com/sun/tdk/jcov/report/html/resources/style.css	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/html/resources/style.css	Mon Oct 26 14:31:30 2015 +0300
@@ -132,6 +132,13 @@
     background: #FF4652;
 }
 
+td.reportValue_anc{
+    font-size: inherit !important;
+    border: #dcdcdc 1px solid;
+    text-align: right;
+    background: #FFFF52;
+}
+
 td.spacer {
 	border-left: #FF4652 0px none;
 	border-right: #FF4652 0px none;
@@ -149,6 +156,11 @@
 	empty-cells: show;
 }
 
+td.percentAnc {
+    background: #FFFF52;
+    empty-cells: show;
+}
+
 td.numLine {
     background: #F0F0F0;
     border-right: #dcdcdc 1px solid;
@@ -170,6 +182,13 @@
     text-align: right;
 }
 
+td.numLineAnc {
+    background: #FFFF52;
+    border-right: #dcdcdc 1px solid;
+    padding-right: 3px;
+    text-align: right;
+}
+
 td.nbHits {
     background: #F0F0F0;
     border-right: #dcdcdc 1px solid;
@@ -191,6 +210,13 @@
     text-align: left;
 }
 
+td.nbHitsAnc {
+    background: #FFFF52;
+    border-right: #dcdcdc 1px solid;
+    padding-right: 3px;
+    text-align: left;
+}
+
 td.src {
     width: 100%;
 }
--- a/src/classes/com/sun/tdk/jcov/report/text/TextReportGenerator.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/report/text/TextReportGenerator.java	Mon Oct 26 14:31:30 2015 +0300
@@ -136,37 +136,37 @@
         }
 
         out.println(String.format(sumFormat,
-                coverage.getCoverageString(DataType.CLASS),
+                coverage.getCoverageString(DataType.CLASS, coverage.isAncFiltersSet()),
                 coverage.getData(DataType.METHOD).add(coverage.getData(DataType.FIELD)).toString(),
-                coverage.getCoverageString(DataType.BLOCK),
-                coverage.getCoverageString(DataType.BRANCH),
-                coverage.getCoverageString(DataType.LINE)));
+                coverage.getCoverageString(DataType.BLOCK, coverage.isAncFiltersSet()),
+                coverage.getCoverageString(DataType.BRANCH, coverage.isAncFiltersSet()),
+                coverage.getCoverageString(DataType.LINE, coverage.isAncFiltersSet())));
         for (PackageCoverage pkgCov : coverage) {
             out.println(String.format(pkgFormat,
                     pkgCov.isCovered() ? "+" : "-",
                     pkgCov.getName(),
-                    pkgCov.getCoverageString(DataType.CLASS),
+                    pkgCov.getCoverageString(DataType.CLASS, coverage.isAncFiltersSet()),
                     pkgCov.getData(DataType.METHOD).add(pkgCov.getData(DataType.FIELD)).toString(),
-                    pkgCov.getCoverageString(DataType.BLOCK),
-                    pkgCov.getCoverageString(DataType.BRANCH),
-                    pkgCov.getCoverageString(DataType.LINE)));
+                    pkgCov.getCoverageString(DataType.BLOCK, coverage.isAncFiltersSet()),
+                    pkgCov.getCoverageString(DataType.BRANCH, coverage.isAncFiltersSet()),
+                    pkgCov.getCoverageString(DataType.LINE, coverage.isAncFiltersSet())));
             for (ClassCoverage clsCov : pkgCov.getClasses()) {
                 out.println(String.format(clsFormat,
                         clsCov.isCovered() ? "+" : "-",
                         clsCov.getName(),
                         clsCov.getData(DataType.METHOD).add(clsCov.getData(DataType.FIELD)).toString(),
-                        clsCov.getCoverageString(DataType.BLOCK),
-                        clsCov.getCoverageString(DataType.BRANCH),
-                        clsCov.getCoverageString(DataType.LINE)));
+                        clsCov.getCoverageString(DataType.BLOCK, coverage.isAncFiltersSet()),
+                        clsCov.getCoverageString(DataType.BRANCH, coverage.isAncFiltersSet()),
+                        clsCov.getCoverageString(DataType.LINE, coverage.isAncFiltersSet())));
                 if (!generateShortFormat && showMethods) {
                     for (MethodCoverage mthCov : clsCov.getMethods()) {
                         out.println(String.format(mthFormat,
                                 mthCov.isCovered() ? "+" : "-",
                                 mthCov.getName() + mthCov.getSignature(),
                                 mthCov.getHitCount(),
-                                mthCov.getCoverageString(DataType.BLOCK),
-                                mthCov.getCoverageString(DataType.BRANCH),
-                                mthCov.getCoverageString(DataType.LINE)));
+                                mthCov.getCoverageString(DataType.BLOCK, coverage.isAncFiltersSet()),
+                                mthCov.getCoverageString(DataType.BRANCH, coverage.isAncFiltersSet()),
+                                mthCov.getCoverageString(DataType.LINE, coverage.isAncFiltersSet())));
                     }
                 }
                 if (!generateShortFormat && showFields) {
--- a/src/classes/com/sun/tdk/jcov/runtime/Collect.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/runtime/Collect.java	Mon Oct 26 14:31:30 2015 +0300
@@ -38,7 +38,7 @@
 public class Collect {
 
     // coverage data
-    public static final int MAX_SLOTS = 1200000;
+    public static final int MAX_SLOTS = 2000000;
     public static int SLOTS = MAX_SLOTS;
     private static final int MAX_SAVERS = 10;
     private static int nextSlot = 0;
--- a/src/classes/com/sun/tdk/jcov/runtime/JCovSESocketSaver.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/runtime/JCovSESocketSaver.java	Mon Oct 26 14:31:30 2015 +0300
@@ -46,16 +46,23 @@
 
         File file = null;
         String urlString = "";
-        try {
-            urlString = ClassLoader.getSystemClassLoader().getResource(JCovSESocketSaver.class.getCanonicalName().replaceAll("\\.", "/") + ".class").toString();
+        URL url = ClassLoader.getSystemClassLoader().getResource(JCovSESocketSaver.class.getCanonicalName().replaceAll("\\.", "/") + ".class");
+        if (url != null) {
+            urlString = url.toString();
             if (urlString.contains("file:") && urlString.contains("!")) {
                 urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!'));
             }
             urlString = urlString.replaceAll("jrt:", "file:");
-            URL url = new URL(urlString);
-            file = new File(url.toURI());
-        } catch (Exception e) {
-            System.err.println("Error while finding " + urlString + " file: " + e);
+            try {
+                url = new URL(urlString);
+                file = new File(url.toURI());
+            } catch (Exception e) {
+                System.err.println("Error while finding " + urlString + " file: " + e);
+            }
+        }
+
+        if (file == null){
+            file = new File(System.getProperty("java.home")+File.separator + NETWORK_DEF_PROPERTIES_FILENAME);
         }
 
         if (file != null && file.exists()) {
--- a/src/classes/com/sun/tdk/jcov/runtime/PropertyFinder.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/runtime/PropertyFinder.java	Mon Oct 26 14:31:30 2015 +0300
@@ -343,7 +343,13 @@
             }
         }
 
-        InputStream in = JCovSaver.class.getResourceAsStream(path);
+        InputStream in = null;
+        try {
+            in = JCovSaver.class.getResourceAsStream(path);
+        }
+        catch (Exception e){
+            //in will be null
+        }
         if (in != null) {
             try {
                 Properties p = new Properties();
--- a/src/classes/com/sun/tdk/jcov/util/Utils.java	Mon Apr 06 13:07:41 2015 +0300
+++ b/src/classes/com/sun/tdk/jcov/util/Utils.java	Mon Oct 26 14:31:30 2015 +0300
@@ -46,10 +46,7 @@
 import java.net.UnknownHostException;
 import java.nio.channels.FileChannel;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Vector;
+import java.util.*;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Formatter;
 import java.util.logging.Handler;
@@ -800,7 +797,15 @@
         return args.toString();
     }
 
-    public static Pattern[] concatFilters(String[] includes, String[] excludes) {
+    public static Pattern[] concatFilters(String[] includes, String[] excludes){
+        return concatFilters(includes, excludes, false);
+    }
+
+    public static Pattern[] concatModuleFilters(String[] includes, String[] excludes){
+        return concatFilters(includes, excludes, true);
+    }
+
+    private static Pattern[] concatFilters(String[] includes, String[] excludes, boolean modulePattern) {
         if (includes == null || includes.length == 1 && includes[0].equals("")) {
             includes = new String[0];
         }
@@ -813,20 +818,20 @@
             if (includes[i].contains("|")) {
                 String[] split = includes[i].split("\\|");
                 for (int j = 0; j < split.length; ++j) {
-                    list.add(new Pattern(split[j], true));
+                    list.add(new Pattern(split[j], true, modulePattern));
                 }
             } else {
-                list.add(new Pattern(includes[i], true));
+                list.add(new Pattern(includes[i], true, modulePattern));
             }
         }
         for (int i = 0; i < excludes.length; ++i) {
             if (excludes[i].contains("|")) {
                 String[] split = excludes[i].split("\\|");
                 for (int j = 0; j < split.length; ++j) {
-                    list.add(new Pattern(split[j], false));
+                    list.add(new Pattern(split[j], false, modulePattern));
                 }
             } else {
-                list.add(new Pattern(excludes[i], false));
+                list.add(new Pattern(excludes[i], false, modulePattern));
             }
         }
         alls = list.toArray(new Pattern[list.size()]);
@@ -870,19 +875,26 @@
          * @param element Should not be null
          * @param include
          */
-        public Pattern(String element, boolean include) {
+        public Pattern(String element, boolean include, boolean modulePattern) {
             try {
                 if ("/".equals(element)) {
                     this.element = element;
                     this.included = include;
                     this.patt = java.util.regex.Pattern.compile("/[a-zA-Z0-9_\\$]+");
                 } else {
-                    this.element = element.replaceAll("\\.", "/").replaceAll("([^\\\\])\\$", "$1\\\\\\$");
+                    if (modulePattern) {
+                        this.element = element.replaceAll("([^\\\\])\\$", "$1\\\\\\$");
+                    }
+                    else{
+                        this.element = element.replaceAll("\\.", "/").replaceAll("([^\\\\])\\$", "$1\\\\\\$");
+                    }
                     if (this.element.endsWith("/")) {
                         this.element = this.element.substring(0, this.element.length() - 1);
                     }
-                    if (this.element.length() == 0 || !this.element.startsWith("/")) {
-                        this.element = "/" + this.element;
+                    if (!modulePattern) {
+                        if (this.element.length() == 0 || !this.element.startsWith("/")) {
+                            this.element = "/" + this.element;
+                        }
                     }
                     this.patt = java.util.regex.Pattern.compile(this.element.replace('*', '#').replaceAll("##", "[a-zA-Z0-9_\\$/]*").replaceAll("#", "[a-zA-Z0-9_\\$]*") + "(/.*|\\$.*)*");
                     this.included = include;
@@ -1330,7 +1342,8 @@
                 && (!classname.equals("java/lang/ThreadGroup"))
                 && (!classname.equals("java/lang/RuntimePermission"))
                 && (!classname.equals("java/security/Permission"))
-                && (!classname.equals("java/security/BasicPermission"))) {
+                && (!classname.equals("java/security/BasicPermission"))
+                && (!classname.equals("java/lang/Class"))) {
             return true;
         }