private DexLookup GetOrCreateDex(ClassSource source, bool waitForResult)
        {
            string hash = GetHash(source);

            var jarFileName = GetJarFileName(source, hash);

            Task<DexLookup> dex;
            
            lock (_dexes)
            {
                if (_dexes.TryGetValue(jarFileName, out dex))
                {
                    if (!waitForResult)
                        return null;
                    return dex.Result;
                }
                    
                dex = new Task<DexLookup>(()=>
                {
                    var dexFileName = GetOrCreateDexFilename(source, hash);
                    return new DexLookup(DexLib.Dex.Read(dexFileName));
                }, TaskCreationOptions.LongRunning);

                _dexes[jarFileName] = dex;
            }

            dex.Start();

            if (waitForResult)
                return dex.Result;
            return null;
        }
        private string GetOrCreateDexFilename(ClassSource source, string hash)
        {
            string jarFileName = GetJarFileName(source, hash);
            
            if (!source.IsDiskFile && !File.Exists(jarFileName))
            {
                Directory.CreateDirectory(_temporaryDirectory);
                File.WriteAllBytes(jarFileName, source.JarData);
            }

            string baseName = Path.GetFileNameWithoutExtension(jarFileName);
            if (!baseName.Contains(hash)) baseName += "." + hash;
            var dexFileName = Path.Combine(_temporaryDirectory, baseName + ".dex");

            if (!File.Exists(dexFileName))
            {
                Directory.CreateDirectory(_temporaryDirectory);
                DxInvoker.CompileToDex(jarFileName, dexFileName, _generateDebugSymbols);
            }

            return dexFileName;
        }
        private string GetJarFileName(ClassSource source, string hash)
        {
            if (source.IsDiskFile)
            {
                return source.FileName;
            }

            string baseName = Path.GetFileName(source.FileName);
            return Path.Combine(_temporaryDirectory, baseName + "-" + hash + ".jar");
        }
 public void PreloadJar(ClassSource source)
 {
     GetOrCreateDex(source, waitForResult: false);
 }
        private string GetHash(ClassSource source)
        {
            if (source.JarStreamHash != null)
                return source.JarStreamHash;

            if (source.JarData != null)
                return JarReferenceHash.ComputeJarReferenceHash(source.JarData);

            return JarReferenceHash.ComputeJarReferenceHash(source.FileName);
        }