1.7.0\u 40上的Java WebStart签名JAR出错

1.7.0\u 40上的Java WebStart签名JAR出错,java,classloader,java-web-start,jnlp,jarsigner,Java,Classloader,Java Web Start,Jnlp,Jarsigner,我们知道jar softlinker的问题 并且使用了下面的类(在web上找到并进行了修改以处理Java7) 此异常重复52次(对于所有JAR) 我们已经确保所有52个jar/文件(除了JNLP本身)都已正确签名,并且在启动应用程序之前清除了java缓存 在windows机器上使用的JAVA版本是JDK 7u40 尝试的方案有: 删除jdk.certpath.disabledAlgorithms=MD2,RSA密钥大小问题(JRE版本){ callNoArgMethod(“getSignin

我们知道jar softlinker的问题

并且使用了下面的类(在web上找到并进行了修改以处理Java7)


此异常重复52次(对于所有JAR)

我们已经确保所有52个jar/文件(除了JNLP本身)都已正确签名,并且在启动应用程序之前清除了java缓存

在windows机器上使用的JAVA版本是JDK 7u40

尝试的方案有:

  • 删除jdk.certpath.disabledAlgorithms=MD2,RSA密钥大小<1024 从java.securites文件
  • 正在检查jar签名者证书。签名者证书使用SHA1 with RSA作为签名算法
  • 注:

  • 源代码在Java5U11中编译,并在Java7U40中运行
  • 我们还观察到一个差异。对于JRE6,当我们运行相同的 在这段代码中,它首先从java/jre6/lib路径加载JAVAWS.jar、Deploy.jar和plugin.jar,但在JRE7中,这些jar不会被加载
  • 这在64位和32位java版本中都尝试过,但没有成功


    非常感谢您的帮助

    @jorge\u B:我们使用ant任务在罐子上签名。但是由于Java6U19中的一个问题(软引用的JAR有时会被垃圾收集),我们决定在遇到JAVA版本6u19或更高版本时立即硬链接JAR。这个问题与jar签名无关。问题是当我们努力参考罐子时。我们的JAR没有得到硬引用,相反,我们在日志中得到了nosuchmethod和nosuchfield异常。

    import java.io.IOException;
    
    import java.io.IOException;
    import java.lang.ref.SoftReference;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.JarURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.*;
    import java.util.jar.JarFile;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * A utility class for working around the java webstart jar signing/security bug
     * <p/>
     * see http://bugs.sun.com/view_bug.do?bug_id=6967414 and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618
     *
     * @author Scott Chan
     */
    public class JarSignersHardLinker {
    
        private static final String JRE_VERSION_START = "1.";
        private static final int PROBLEM_JRE_VERSION = 6;
        private static final String DOT_ZERO = ".0_";
    
        /**
         * the 1.6.0 update where this problem first occurred
         */
        private static final int PROBLEM_JRE_UPDATE = 19;
        private static String majorVersionStr = null;
        public static final List sm_hardRefs = new ArrayList();
    
        protected static void makeHardSignersRef(JarFile jar) throws java.io.IOException {
            Logger.info("Making hard refs for: " + (jar != null ? jar.getName() : null) + " with Java Version: "+majorVersionStr);
            if (jar != null && jar.getClass().getName().equals("com.sun.deploy.cache.CachedJarFile")) {
    
                //lets attempt to get at the each of the soft links.
                //first neet to call the relevant no-arg method to ensure that the soft ref is populated
                //then we access the private member, resolve the softlink and throw it in a static list.
                if (majorVersionStr != null && Integer.parseInt(majorVersionStr) > PROBLEM_JRE_VERSION) {
                    callNoArgMethod("getSigningData", jar);
                    makeHardLink("signingDataRef", jar);
                } else {
                    callNoArgMethod("getSigners", jar);
                    makeHardLink("signersRef", jar);
                    callNoArgMethod("getSignerMap", jar);
                    makeHardLink("signerMapRef", jar);
    
    //            callNoArgMethod("getCodeSources", jar);
    //            makeHardLink("codeSourcesRef", jar);
                    callNoArgMethod("getCodeSourceCache", jar);
                    makeHardLink("codeSourceCacheRef", jar);
                }
            }
        }
    
        /**
         * if the specified field for the given instance is a Softreference
         * That soft reference is resolved and the returned ref is stored in a static list,
         * making it a hard link that should never be garbage collected
         *
         * @param fieldName
         * @param instance
         */
        private static void makeHardLink(String fieldName, Object instance) {
            Logger.info("attempting hard ref to " + instance.getClass().getName() + "." + fieldName);
            try {
                Field signersRef = instance.getClass().getDeclaredField(fieldName);
                signersRef.setAccessible(true);
                Object o = signersRef.get(instance);
                if (o instanceof SoftReference) {
                    SoftReference r = (SoftReference) o;
                    Object o2 = r.get();
                    sm_hardRefs.add(o2);
                } else {
                    Logger.warn(fieldName + ": is not an instance of soft reference");
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
                return;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Call the given no-arg method on the given instance
         *
         * @param methodName
         * @param instance
         */
        private static void callNoArgMethod(String methodName, Object instance) {
            Logger.info("calling noarg method hard ref to " + instance.getClass().getName() + "." + methodName + "()");
            try {
                Method m = instance.getClass().getDeclaredMethod(methodName);
                m.setAccessible(true);
                m.invoke(instance);
    
            } catch (SecurityException e1) {
                e1.printStackTrace();
            } catch (NoSuchMethodException e1) {
                e1.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * is the preloader enabled. ie: will the preloader run in the current environment
         *
         * @return
         */
        public static boolean isHardLinkerEnabled() {
            boolean isHardLinkerDisabled = false;  //change this to use whatever mechanism you use to enable or disable the preloader
            return !isHardLinkerDisabled && isRunningOnJre1_6_0_19OrHigher() && isRunningOnWebstart();
        }
    
        /**
         * is the application currently running on webstart
         * <p/>
         * detect the presence of a JNLPclassloader
         *
         * @return
         */
        public static boolean isRunningOnWebstart() {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            while (cl != null) {
                if (cl.getClass().getName().equals("com.sun.jnlp.JNLPClassLoader")) {
                    return true;
                }
                cl = cl.getParent();
            }
            return false;
    
        }
    
        /**
         * Is the JRE 1.6.0_19 or higher?
         *
         * @return
         */
    
        public static boolean isRunningOnJre1_6_0_19OrHigher() {
            String javaVersion = System.getProperty("java.version");
            // Sometimes java releases version 1.X.0_YY-rev for specific issue and specific user,
            // to resolve this we use patter instead of string split.
            //ERP-6460: Checking whether JRE is 6 update 19 or higher
            String updateStr = null;
            majorVersionStr = null;
            boolean isHardReferenceRequired = false;
    
            Pattern pattern = Pattern.compile(JRE_VERSION_START + "([6-9]+)" + DOT_ZERO + "([0-9]+)(.*)");
            Matcher matcher = pattern.matcher(javaVersion);
    
            while (matcher.find()) {
                majorVersionStr = matcher.group(1);
                updateStr = matcher.group(2);
                break;
            }
    
            try {
                if (majorVersionStr != null) {
                    int java_version = Integer.parseInt(majorVersionStr);
                    if (java_version > PROBLEM_JRE_VERSION) {
                        isHardReferenceRequired = true;
                    } else if (java_version == PROBLEM_JRE_VERSION && Integer.parseInt(updateStr) >= PROBLEM_JRE_UPDATE) {
                        isHardReferenceRequired = true;
                    }
                }
                return isHardReferenceRequired;
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return isHardReferenceRequired;
            }
        }
    
        /**
         * get all the JarFile objects for all of the jars in the classpath
         *
         * @return
         */
        public static Set<JarFile> getAllJarsFilesInClassPath() {
            Set<JarFile> jars = new LinkedHashSet<JarFile>();
            for (URL url : getAllJarUrls()) {
                try {
                    jars.add(getJarFile(url));
                } catch (IOException e) {
                    Logger.error("unable to retrieve jar at URL: " + url);
                }
            }
            return jars;
        }
    
        /**
         * Returns set of URLS for the jars in the classpath.
         * URLS will have the protocol of jar eg: jar:http://HOST/PATH/JARNAME.jar!/META-INF/MANIFEST.MF
         */
        static Set<URL> getAllJarUrls() {
            try {
                Set<URL> urls = new LinkedHashSet<URL>();
                Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");
                while (mfUrls.hasMoreElements()) {
                    URL jarUrl = mfUrls.nextElement();
    //                System.out.println(jarUrl);
                    if (!jarUrl.getProtocol().equals("jar")) {
                        continue;
                    }
                    urls.add(jarUrl);
                }
                return urls;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * get the jarFile object for the given url
         *
         * @param jarUrl
         * @return
         * @throws IOException
         */
        public static JarFile getJarFile(URL jarUrl) throws IOException {
            URLConnection urlConnnection = jarUrl.openConnection();
            if (urlConnnection instanceof JarURLConnection) {
                // Using a JarURLConnection will load the JAR from the cache when using Webstart 1.6
                // In Webstart 1.5, the URL will point to the cached JAR on the local filesystem
                JarURLConnection jcon = (JarURLConnection) urlConnnection;
                return jcon.getJarFile();
            } else {
                throw new AssertionError("Expected JarURLConnection");
            }
        }
    
        /**
         * Spawn a new thread to run through each jar in the classpath and create a hardlink
         * to the jars softly referenced signers infomation.
         */
        public static void go() {
            if (!isHardLinkerEnabled()) {
                return;
            }
            Logger.info("Starting Resource Preloader Hardlinker");
            Thread t = new Thread(new Runnable() {
    
                public void run() {
                    try {
                        Set<JarFile> jars = getAllJarsFilesInClassPath();
                        for (JarFile jar : jars) {
                            makeHardSignersRef(jar);
                        }
    
                    } catch (Exception e) {
                        Logger.error("Problem preloading resources", e);
                    } catch (Error e) {
                        Logger.error("Error preloading resources", e);
                    }
                }
    
            });
            t.start();
    
        }
    }
    
    导入java.lang.ref.SoftReference; 导入java.lang.reflect.Field; 导入java.lang.reflect.InvocationTargetException; 导入java.lang.reflect.Method; 导入java.net.JarURLConnection; 导入java.net.URL; 导入java.net.URLConnection; 导入java.util.*; 导入java.util.jar.jar文件; 导入java.util.regex.Matcher; 导入java.util.regex.Pattern; /** *用于解决JavaWebStart jar签名/安全缺陷的实用程序类 *

    *看http://bugs.sun.com/view_bug.do?bug_id=6967414 和http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618 * *@作者陈兆恺 */ 公共类JarSignerSharedLinker{ 私有静态最终字符串JRE\u VERSION\u START=“1。”; 私有静态最终整数问题_JRE_VERSION=6; 私有静态最终字符串DOT_ZERO=“.0_”; /** *首次出现此问题的1.6.0更新 */ 私有静态最终整数问题_JRE_UPDATE=19; 私有静态字符串majorVersionStr=null; public static final List sm_hardRefs=new ArrayList(); 受保护的静态void makeHardSignersRef(JarFile jar)抛出java.io.IOException{ Logger.info(“在Java版本为“+majorVersionStr”的情况下对“+(jar!=null?jar.getName():null)+”进行硬引用); if(jar!=null&&jar.getClass().getName().equals(“com.sun.deploy.cache.CachedJarFile”)){ //让我们尝试访问每个软链接。 //首先neet调用相关的no arg方法,以确保填充了soft ref //然后我们访问私有成员,解析软链接并将其放入静态列表中。 如果(majorVersionStr!=null&&Integer.parseInt(majorVersionStr)>问题(JRE版本){ callNoArgMethod(“getSigningData”,jar); makeHardLink(“signingDataRef”,jar); }否则{ callNoArgMethod(“getSigners”,jar); makeHardLink(“signersRef”,jar); callNoArgMethod(“getSignerMap”,jar); makeHardLink(“signerMapRef”,jar); //callNoArgMethod(“getCodeSources”,jar); //makeHardLink(“codeSourcesRef”,jar); callNoArgMethod(“getCodeSourceCache”,jar); makeHardLink(“codeSourceCacheRef”,jar); } } } /** *如果给定实例的指定字段是Softreference *软引用被解析,返回的ref存储在静态列表中, *使其成为一个不应被垃圾收集的硬链接 * *@param fieldName *@param实例 */ 私有静态void makeHardLink(字符串字段名,对象实例){ Logger.info(“正在尝试硬引用”+实例.getClass().getName()+”+字段名); 试一试{ Field signersRef=instance.getClass().getDeclaredField(fieldName); signersRef.setAccessible(true); 对象o=signersRef.get(实例); if(o实例of SoftReference){ 软参考r=(软参考)o; 对象o2=r.get(); sm_硬参考添加(o2); }否则{ Logger.warn(fieldName+“:不是软引用的实例”); } }捕获(无此字段例外){ e、 printStackTrace(); 回来 }捕获(非法访问例外e){ e、 printStackTrace(); } } /** *对给定实例调用给定的no-arg方法 * *@param methodName *@param实例 */ 私有静态void callNoArgMethod(字符串方法名,对象实例){ info(“调用noarg方法硬引用到“+instance.getClass().getName()+”“+methodName+”()”; 试一试{ 方法m=instance.getClass().getDeclaredMethod(methodName); m、 setAccessible(true); m、 调用(实例); }捕获(安全异常e1){ e1.printStackTrace(); }捕获(NoSuchMethodException e1){ e1.printStackTrace(); }捕获(IllegalArgumentException e){ e、 printStackTrace(); }捕获(非法访问例外e){ e、 printStackTrace(); }捕获(调用TargetException e){ e、 printStackTrace(); } } /** *是否启用预加载。即:预加载

    java.lang.NoSuchMethodException: com.sun.deploy.cache.CachedJarFile.getSigners()
      at java.lang.Class.getDeclaredMethod(Unknown Source)
      at com.XXXXXX.ui.main.JarSignersHardLinker.callNoArgMethod(JarSignersHardLinker.java:96)
      at com.XXXXXX.ui.main.JarSignersHardLinker.makeHardSignersRef(JarSignersHardLinker.java:45)
      at com.XXXXXX.ui.main.JarSignersHardLinker$1.run(JarSignersHardLinker.java:262)
      at java.lang.Thread.run(Unknown Source)
    java.lang.NoSuchFieldException: signersRef
      at java.lang.Class.getDeclaredField(Unknown Source)
      at com.XXXXXX.ui.main.JarSignersHardLinker.makeHardLink(JarSignersHardLinker.java:69)
      at com.XXXXXX.ui.main.JarSignersHardLinker.makeHardSignersRef(JarSignersHardLinker.java:46)
      at com.XXXXXX.ui.main.JarSignersHardLinker$1.run(JarSignersHardLinker.java:262)
      at java.lang.Thread.run(Unknown Source)
    
    import java.io.IOException;
    import java.lang.ref.SoftReference;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.JarURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.*;
    import java.util.jar.JarFile;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * A utility class for working around the java webstart jar signing/security bug
     * <p/>
     * see http://bugs.sun.com/view_bug.do?bug_id=6967414 and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618
     *
     * @author Scott Chan
     */
    public class JarSignersHardLinker {
    
        private static final String JRE_VERSION_START = "1.";
        private static final int PROBLEM_JRE_VERSION = 6;
        private static final String DOT_ZERO = ".0_";
    
        /**
         * the 1.6.0 update where this problem first occurred
         */
        private static final int PROBLEM_JRE_UPDATE = 19;
        private static String majorVersionStr = null;
        public static final List sm_hardRefs = new ArrayList();
    
        protected static void makeHardSignersRef(JarFile jar) throws java.io.IOException {
            Logger.info("Making hard refs for: " + (jar != null ? jar.getName() : null) + " with Java Version: "+majorVersionStr);
            if (jar != null && jar.getClass().getName().equals("com.sun.deploy.cache.CachedJarFile")) {
    
                //lets attempt to get at the each of the soft links.
                //first neet to call the relevant no-arg method to ensure that the soft ref is populated
                //then we access the private member, resolve the softlink and throw it in a static list.
                if (majorVersionStr != null && Integer.parseInt(majorVersionStr) > PROBLEM_JRE_VERSION) {
                    callNoArgMethod("getSigningData", jar);
                    makeHardLink("signingDataRef", jar);
                } else {
                    callNoArgMethod("getSigners", jar);
                    makeHardLink("signersRef", jar);
                    callNoArgMethod("getSignerMap", jar);
                    makeHardLink("signerMapRef", jar);
    
    //            callNoArgMethod("getCodeSources", jar);
    //            makeHardLink("codeSourcesRef", jar);
                    callNoArgMethod("getCodeSourceCache", jar);
                    makeHardLink("codeSourceCacheRef", jar);
                }
            }
        }
    
        /**
         * if the specified field for the given instance is a Softreference
         * That soft reference is resolved and the returned ref is stored in a static list,
         * making it a hard link that should never be garbage collected
         *
         * @param fieldName
         * @param instance
         */
        private static void makeHardLink(String fieldName, Object instance) {
            Logger.info("attempting hard ref to " + instance.getClass().getName() + "." + fieldName);
            try {
                Field signersRef = instance.getClass().getDeclaredField(fieldName);
                signersRef.setAccessible(true);
                Object o = signersRef.get(instance);
                if (o instanceof SoftReference) {
                    SoftReference r = (SoftReference) o;
                    Object o2 = r.get();
                    sm_hardRefs.add(o2);
                } else {
                    Logger.warn(fieldName + ": is not an instance of soft reference");
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
                return;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Call the given no-arg method on the given instance
         *
         * @param methodName
         * @param instance
         */
        private static void callNoArgMethod(String methodName, Object instance) {
            Logger.info("calling noarg method hard ref to " + instance.getClass().getName() + "." + methodName + "()");
            try {
                Method m = instance.getClass().getDeclaredMethod(methodName);
                m.setAccessible(true);
                m.invoke(instance);
    
            } catch (SecurityException e1) {
                e1.printStackTrace();
            } catch (NoSuchMethodException e1) {
                e1.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * is the preloader enabled. ie: will the preloader run in the current environment
         *
         * @return
         */
        public static boolean isHardLinkerEnabled() {
            boolean isHardLinkerDisabled = false;  //change this to use whatever mechanism you use to enable or disable the preloader
            return !isHardLinkerDisabled && isRunningOnJre1_6_0_19OrHigher() && isRunningOnWebstart();
        }
    
        /**
         * is the application currently running on webstart
         * <p/>
         * detect the presence of a JNLPclassloader
         *
         * @return
         */
        public static boolean isRunningOnWebstart() {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            while (cl != null) {
                if (cl.getClass().getName().equals("com.sun.jnlp.JNLPClassLoader")) {
                    return true;
                }
                cl = cl.getParent();
            }
            return false;
    
        }
    
        /**
         * Is the JRE 1.6.0_19 or higher?
         *
         * @return
         */
    
        public static boolean isRunningOnJre1_6_0_19OrHigher() {
            String javaVersion = System.getProperty("java.version");
            // Sometimes java releases version 1.X.0_YY-rev for specific issue and specific user,
            // to resolve this we use patter instead of string split.
            //ERP-6460: Checking whether JRE is 6 update 19 or higher
            String updateStr = null;
            majorVersionStr = null;
            boolean isHardReferenceRequired = false;
    
            Pattern pattern = Pattern.compile(JRE_VERSION_START + "([6-9]+)" + DOT_ZERO + "([0-9]+)(.*)");
            Matcher matcher = pattern.matcher(javaVersion);
    
            while (matcher.find()) {
                majorVersionStr = matcher.group(1);
                updateStr = matcher.group(2);
                break;
            }
    
            try {
                if (majorVersionStr != null) {
                    int java_version = Integer.parseInt(majorVersionStr);
                    if (java_version > PROBLEM_JRE_VERSION) {
                        isHardReferenceRequired = true;
                    } else if (java_version == PROBLEM_JRE_VERSION && Integer.parseInt(updateStr) >= PROBLEM_JRE_UPDATE) {
                        isHardReferenceRequired = true;
                    }
                }
                return isHardReferenceRequired;
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return isHardReferenceRequired;
            }
        }
    
        /**
         * get all the JarFile objects for all of the jars in the classpath
         *
         * @return
         */
        public static Set<JarFile> getAllJarsFilesInClassPath() {
            Set<JarFile> jars = new LinkedHashSet<JarFile>();
            for (URL url : getAllJarUrls()) {
                try {
                    jars.add(getJarFile(url));
                } catch (IOException e) {
                    Logger.error("unable to retrieve jar at URL: " + url);
                }
            }
            return jars;
        }
    
        /**
         * Returns set of URLS for the jars in the classpath.
         * URLS will have the protocol of jar eg: jar:http://HOST/PATH/JARNAME.jar!/META-INF/MANIFEST.MF
         */
        static Set<URL> getAllJarUrls() {
            try {
                Set<URL> urls = new LinkedHashSet<URL>();
                Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");
                while (mfUrls.hasMoreElements()) {
                    URL jarUrl = mfUrls.nextElement();
    //                System.out.println(jarUrl);
                    if (!jarUrl.getProtocol().equals("jar")) {
                        continue;
                    }
                    urls.add(jarUrl);
                }
                return urls;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * get the jarFile object for the given url
         *
         * @param jarUrl
         * @return
         * @throws IOException
         */
        public static JarFile getJarFile(URL jarUrl) throws IOException {
            URLConnection urlConnnection = jarUrl.openConnection();
            if (urlConnnection instanceof JarURLConnection) {
                // Using a JarURLConnection will load the JAR from the cache when using Webstart 1.6
                // In Webstart 1.5, the URL will point to the cached JAR on the local filesystem
                JarURLConnection jcon = (JarURLConnection) urlConnnection;
                return jcon.getJarFile();
            } else {
                throw new AssertionError("Expected JarURLConnection");
            }
        }
    
        /**
         * Spawn a new thread to run through each jar in the classpath and create a hardlink
         * to the jars softly referenced signers infomation.
         */
        public static void go() {
            if (!isHardLinkerEnabled()) {
                return;
            }
            Logger.info("Starting Resource Preloader Hardlinker");
            Thread t = new Thread(new Runnable() {
    
                public void run() {
                    try {
                        Set<JarFile> jars = getAllJarsFilesInClassPath();
                        for (JarFile jar : jars) {
                            makeHardSignersRef(jar);
                        }
    
                    } catch (Exception e) {
                        Logger.error("Problem preloading resources", e);
                    } catch (Error e) {
                        Logger.error("Error preloading resources", e);
                    }
                }
    
            });
            t.start();
    
        }
    }